Merge branch 'master' into HD-PSA
This commit is contained in:
Коммит
68d3e7c55c
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks.List
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// This specifies the Content of the List element.
|
||||
|
|
|
@ -11,9 +11,8 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks.List
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
internal class ListItemBuilder : MarkdownBlock
|
||||
{
|
||||
|
|
|
@ -10,9 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks.List
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
internal class ListItemPreamble
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks.List
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
internal class NestedListInfo
|
||||
{
|
||||
|
|
|
@ -17,8 +17,6 @@ using System.Runtime.CompilerServices;
|
|||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Blocks.List;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
[assembly: InternalsVisibleTo("UnitTests")]
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Enums
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// The alignment of content in a table column.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Enums
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the type of Hyperlink that is used.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Enums
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
{
|
||||
internal enum InlineParseMethod
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Enums
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// This specifies the type of style the List will be.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Enums
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the type of Block the Block element is.
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Enums
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines the type of Inline the Inline Element is.
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Helpers
|
||||
|
@ -511,5 +510,30 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Helpers
|
|||
|
||||
return startOfLine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given URL is allowed in a markdown link.
|
||||
/// </summary>
|
||||
/// <param name="url"> The URL to check. </param>
|
||||
/// <returns> <c>true</c> if the URL is valid; <c>false</c> otherwise. </returns>
|
||||
public static bool IsUrlValid(string url)
|
||||
{
|
||||
// URLs can be relative.
|
||||
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the scheme is allowed.
|
||||
foreach (var scheme in HyperlinkInline.KnownSchemes)
|
||||
{
|
||||
if (result.Scheme.Equals(scheme))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,8 +10,6 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
@ -69,16 +68,16 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
/// </summary>
|
||||
internal static readonly string[] KnownSchemes = new string[]
|
||||
{
|
||||
"http://",
|
||||
"https://",
|
||||
"ftp://",
|
||||
"steam://",
|
||||
"irc://",
|
||||
"news://",
|
||||
"mumble://",
|
||||
"ssh://",
|
||||
"ms-windows-store://",
|
||||
"sip:"
|
||||
"http",
|
||||
"https",
|
||||
"ftp",
|
||||
"steam",
|
||||
"irc",
|
||||
"news",
|
||||
"mumble",
|
||||
"ssh",
|
||||
"ms-windows-store",
|
||||
"sip"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -140,7 +139,7 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
// Check for a known scheme e.g. "https://".
|
||||
foreach (var scheme in KnownSchemes)
|
||||
{
|
||||
int schemeStart = tripPos - (scheme.Length - 3);
|
||||
int schemeStart = tripPos - scheme.Length;
|
||||
if (schemeStart >= 0 && schemeStart <= maxEnd - scheme.Length && string.Equals(markdown.Substring(schemeStart, scheme.Length), scheme, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// URL scheme found.
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
@ -36,6 +35,11 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
/// </summary>
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image Render URL.
|
||||
/// </summary>
|
||||
public string RenderUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a text to display on hover.
|
||||
/// </summary>
|
||||
|
@ -44,6 +48,11 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
/// <inheritdoc/>
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of a reference, if this is a reference-style link.
|
||||
/// </summary>
|
||||
public string ReferenceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets image width
|
||||
/// If value is greater than 0, ImageStretch is set to UniformToFill
|
||||
|
@ -72,6 +81,8 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
/// <returns> A parsed markdown image, or <c>null</c> if this is not a markdown image. </returns>
|
||||
internal static InlineParseResult Parse(string markdown, int start, int end)
|
||||
{
|
||||
int refstart = 0;
|
||||
|
||||
// Expect a '!' character.
|
||||
if (start >= end || markdown[start] != '!')
|
||||
{
|
||||
|
@ -109,16 +120,73 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
|
||||
// Expect the '(' character.
|
||||
pos++;
|
||||
if (pos == end || markdown[pos] != '(')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Skip whitespace
|
||||
pos++;
|
||||
while (pos < end && ParseHelpers.IsMarkdownWhiteSpace(markdown[pos]))
|
||||
string reference = string.Empty;
|
||||
string url = string.Empty;
|
||||
int imageWidth = 0;
|
||||
int imageHeight = 0;
|
||||
|
||||
if (pos < end && markdown[pos] == '[')
|
||||
{
|
||||
pos++;
|
||||
refstart = pos;
|
||||
|
||||
// Find the reference ']' character
|
||||
while (pos < end)
|
||||
{
|
||||
if (markdown[pos] == ']')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
reference = markdown.Substring(refstart + 1, pos - refstart - 1);
|
||||
}
|
||||
else if (pos < end && markdown[pos] == '(')
|
||||
{
|
||||
while (pos < end && ParseHelpers.IsMarkdownWhiteSpace(markdown[pos]))
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
// Extract the URL.
|
||||
int urlStart = pos;
|
||||
while (pos < end && markdown[pos] != ')')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
var imageDimensionsPos = markdown.IndexOf(" =", urlStart, pos - urlStart, StringComparison.Ordinal);
|
||||
|
||||
url = imageDimensionsPos > 0
|
||||
? TextRunInline.ResolveEscapeSequences(markdown, urlStart + 1, imageDimensionsPos)
|
||||
: TextRunInline.ResolveEscapeSequences(markdown, urlStart + 1, pos);
|
||||
|
||||
if (imageDimensionsPos > 0)
|
||||
{
|
||||
// trying to find 'x' which separates image width and height
|
||||
var dimensionsSepatorPos = markdown.IndexOf("x", imageDimensionsPos + 2, pos - imageDimensionsPos - 1, StringComparison.Ordinal);
|
||||
|
||||
// didn't find separator, trying to parse value as imageWidth
|
||||
if (dimensionsSepatorPos == -1)
|
||||
{
|
||||
var imageWidthStr = markdown.Substring(imageDimensionsPos + 2, pos - imageDimensionsPos - 2);
|
||||
|
||||
int.TryParse(imageWidthStr, out imageWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dimensions = markdown.Substring(imageDimensionsPos + 2, pos - imageDimensionsPos - 2).Split('x');
|
||||
|
||||
// got width and height
|
||||
if (dimensions.Length == 2)
|
||||
{
|
||||
int.TryParse(dimensions[0], out imageWidth);
|
||||
int.TryParse(dimensions[1], out imageHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == end)
|
||||
|
@ -126,51 +194,12 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
return null;
|
||||
}
|
||||
|
||||
// Extract the URL.
|
||||
int urlStart = pos;
|
||||
while (pos < end && markdown[pos] != ')')
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
var imageDimensionsPos = markdown.IndexOf(" =", urlStart, pos - urlStart, StringComparison.Ordinal);
|
||||
|
||||
var url = imageDimensionsPos > 0
|
||||
? TextRunInline.ResolveEscapeSequences(markdown, urlStart, imageDimensionsPos)
|
||||
: TextRunInline.ResolveEscapeSequences(markdown, urlStart, pos);
|
||||
|
||||
int imageWidth = 0;
|
||||
int imageHeight = 0;
|
||||
|
||||
if (imageDimensionsPos > 0)
|
||||
{
|
||||
// trying to find 'x' which separates image width and height
|
||||
var dimensionsSepatorPos = markdown.IndexOf("x", imageDimensionsPos + 2, pos - imageDimensionsPos - 1, StringComparison.Ordinal);
|
||||
|
||||
// didn't find separator, trying to parse value as imageWidth
|
||||
if (dimensionsSepatorPos == -1)
|
||||
{
|
||||
var imageWidthStr = markdown.Substring(imageDimensionsPos + 2, pos - imageDimensionsPos - 2);
|
||||
|
||||
int.TryParse(imageWidthStr, out imageWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dimensions = markdown.Substring(imageDimensionsPos + 2, pos - imageDimensionsPos - 2).Split('x');
|
||||
|
||||
// got width and height
|
||||
if (dimensions.Length == 2)
|
||||
{
|
||||
int.TryParse(dimensions[0], out imageWidth);
|
||||
int.TryParse(dimensions[1], out imageHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We found something!
|
||||
var result = new ImageInline
|
||||
{
|
||||
Tooltip = tooltip,
|
||||
RenderUrl = url,
|
||||
ReferenceId = reference,
|
||||
Url = url,
|
||||
Text = markdown.Substring(start, pos + 1 - start),
|
||||
ImageWidth = imageWidth,
|
||||
|
@ -179,6 +208,40 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
return new InlineParseResult(result, start, pos + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If this is a reference-style link, attempts to converts it to a regular link.
|
||||
/// </summary>
|
||||
/// <param name="document"> The document containing the list of references. </param>
|
||||
internal void ResolveReference(MarkdownDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException("document");
|
||||
}
|
||||
|
||||
if (ReferenceId == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Look up the reference ID.
|
||||
var reference = document.LookUpReference(ReferenceId);
|
||||
if (reference == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The reference was found. Check the URL is valid.
|
||||
if (!Common.IsUrlValid(reference.Url))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Everything is cool when you're part of a team.
|
||||
RenderUrl = reference.Url;
|
||||
ReferenceId = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the object into it's textual representation.
|
||||
/// </summary>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -14,7 +14,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
@ -198,7 +197,7 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
// Check the URL is okay.
|
||||
if (!url.IsEmail())
|
||||
{
|
||||
if (!IsUrlValid(url))
|
||||
if (!Common.IsUrlValid(url))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -243,7 +242,7 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
/// If this is a reference-style link, attempts to converts it to a regular link.
|
||||
/// </summary>
|
||||
/// <param name="document"> The document containing the list of references. </param>
|
||||
public void ResolveReference(MarkdownDocument document)
|
||||
internal void ResolveReference(MarkdownDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
|
@ -263,7 +262,7 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
}
|
||||
|
||||
// The reference was found. Check the URL is valid.
|
||||
if (!IsUrlValid(reference.Url))
|
||||
if (!Common.IsUrlValid(reference.Url))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -274,33 +273,6 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
|||
ReferenceId = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given URL is allowed in a markdown link.
|
||||
/// </summary>
|
||||
/// <param name="url"> The URL to check. </param>
|
||||
/// <returns> <c>true</c> if the URL is valid; <c>false</c> otherwise. </returns>
|
||||
private static bool IsUrlValid(string url)
|
||||
{
|
||||
// URLs can be relative.
|
||||
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the scheme is allowed.
|
||||
bool schemeIsAllowed = false;
|
||||
foreach (var scheme in HyperlinkInline.KnownSchemes)
|
||||
{
|
||||
if (url.StartsWith(scheme))
|
||||
{
|
||||
schemeIsAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return schemeIsAllowed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the object into it's textual representation.
|
||||
/// </summary>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Core;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
// ******************************************************************
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
{
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -14,9 +14,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Extensions;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Blocks;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Helpers;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Inlines
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Blocks;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
|
||||
namespace Microsoft.Toolkit.Parsers.Markdown.Render
|
||||
|
@ -222,12 +221,26 @@ namespace Microsoft.Toolkit.Parsers.Markdown.Render
|
|||
{
|
||||
// The element couldn't be resolved, just render it as text.
|
||||
RenderInlineChildren(element.Inlines, context);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
foreach (MarkdownInline inline in element.Inlines)
|
||||
{
|
||||
// Url is valid, create Link.
|
||||
RenderMarkdownLink(element, context);
|
||||
if (inline is ImageInline imageInline)
|
||||
{
|
||||
// this is an image, create Image.
|
||||
if (!string.IsNullOrEmpty(imageInline.ReferenceId))
|
||||
{
|
||||
imageInline.ResolveReference(Document);
|
||||
}
|
||||
|
||||
imageInline.Url = element.Url;
|
||||
RenderImage(imageInline, context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RenderMarkdownLink(element, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -128,6 +128,9 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
|
|||
Constants.ApplicationDisplayName = (await Package.Current.GetAppListEntriesAsync())[0].DisplayInfo.DisplayName;
|
||||
}
|
||||
|
||||
// Check if the Cache is Latest, wipe if not.
|
||||
Sample.EnsureCacheLatest();
|
||||
|
||||
Frame rootFrame = Window.Current.Content as Frame;
|
||||
|
||||
// Do not repeat app initialization when the Window already has content,
|
||||
|
|
|
@ -27,6 +27,7 @@ using Microsoft.Toolkit.Uwp.SampleApp.Models;
|
|||
using Microsoft.Toolkit.Uwp.UI.Animations;
|
||||
using Microsoft.Toolkit.Uwp.UI.Controls;
|
||||
using Microsoft.Toolkit.Uwp.UI.Media;
|
||||
using Newtonsoft.Json;
|
||||
using Windows.Foundation.Metadata;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
|
@ -38,8 +39,37 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
|
|||
{
|
||||
private const string _repoOnlineRoot = "https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/";
|
||||
private const string _docsOnlineRoot = "https://raw.githubusercontent.com/MicrosoftDocs/UWPCommunityToolkitDocs/";
|
||||
private const string _cacheSHAKey = "docs-cache-sha";
|
||||
|
||||
private static HttpClient client = new HttpClient();
|
||||
|
||||
public static async void EnsureCacheLatest()
|
||||
{
|
||||
var settingsStorage = new LocalObjectStorageHelper();
|
||||
|
||||
var onlineDocsSHA = await GetDocsSHA();
|
||||
var cacheSHA = settingsStorage.Read<string>(_cacheSHAKey);
|
||||
|
||||
bool outdatedCache = onlineDocsSHA != null && cacheSHA != null && onlineDocsSHA != cacheSHA;
|
||||
bool noCache = onlineDocsSHA != null && cacheSHA == null;
|
||||
|
||||
if (outdatedCache || noCache)
|
||||
{
|
||||
// Delete everything in the Cache Folder. Could be Pre 3.0.0 Cache data.
|
||||
foreach (var item in await ApplicationData.Current.LocalCacheFolder.GetItemsAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
await item.DeleteAsync(StorageDeleteOption.Default);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Update Cache Version info.
|
||||
settingsStorage.Save(_cacheSHAKey, onlineDocsSHA);
|
||||
}
|
||||
}
|
||||
|
||||
private string _cachedDocumentation = string.Empty;
|
||||
private string _cachedPath = string.Empty;
|
||||
|
||||
|
@ -654,5 +684,34 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async Task<string> GetDocsSHA()
|
||||
{
|
||||
try
|
||||
{
|
||||
var branchEndpoint = "https://api.github.com/repos/microsoftdocs/uwpcommunitytoolkitdocs/git/refs/heads/live";
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, branchEndpoint);
|
||||
request.Headers.Add("User-Agent", "Windows Community Toolkit Sample App");
|
||||
|
||||
using (request)
|
||||
{
|
||||
using (var response = await client.SendAsync(request))
|
||||
{
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var raw = await response.Content.ReadAsStringAsync();
|
||||
var json = JsonConvert.DeserializeObject<dynamic>(raw);
|
||||
return json["object"]["sha"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -356,7 +356,7 @@ To add an image, it is almost like a link. You just need to add a \! before.
|
|||
|
||||
So inline image syntax looks like this:
|
||||
|
||||
>\!\[Helpers Image](https:\//raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/Microsoft.Toolkit.Uwp.SampleApp/Assets/Helpers.png)
|
||||
>\!\[Helpers Image](https\://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/Microsoft.Toolkit.Uwp.SampleApp/Assets/Helpers.png)
|
||||
|
||||
which renders in:
|
||||
|
||||
|
@ -378,11 +378,11 @@ renders in
|
|||
|
||||
You can also specify image width like this:
|
||||
|
||||
>\!\[SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =32) (width is set to 32)
|
||||
>\!\[SVG logo](https\://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =32) (width is set to 32)
|
||||
|
||||
>\!\[SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =x64) (height is set to 64)
|
||||
>\!\[SVG logo](https\://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =x64) (height is set to 64)
|
||||
|
||||
>\!\[SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =128x64) (width=128, height=64)
|
||||
>\!\[SVG logo](https\://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =128x64) (width=128, height=64)
|
||||
|
||||
which renders in:
|
||||
|
||||
|
@ -390,6 +390,33 @@ which renders in:
|
|||
![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =x64)
|
||||
![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =128x64)
|
||||
|
||||
MarkdownTextblock supports links wrapped with Images.
|
||||
|
||||
>\[!\[image](https\://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/build/nuget.png)](https\://docs.microsoft.com/windows/uwpcommunitytoolkit/)
|
||||
|
||||
will render into
|
||||
|
||||
[![image](https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/build/nuget.png)](https://docs.microsoft.com/windows/uwpcommunitytoolkit/)
|
||||
|
||||
and when clicked will go to the Linked Page.
|
||||
|
||||
MarkdownTextBlock also supports Reference based links.
|
||||
|
||||
```
|
||||
[![image][1]][2]
|
||||
|
||||
[1]:https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/build/nuget.png
|
||||
[2]:https://docs.microsoft.com/windows/uwpcommunitytoolkit/
|
||||
|
||||
```
|
||||
|
||||
will render into
|
||||
|
||||
[![image][1]][2]
|
||||
|
||||
[1]:https://raw.githubusercontent.com/Microsoft/UWPCommunityToolkit/master/build/nuget.png
|
||||
[2]:https://docs.microsoft.com/windows/uwpcommunitytoolkit/
|
||||
|
||||
*****
|
||||
|
||||
# BLOCK QUOTES
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
<TextBox Margin="0,0,0,12"
|
||||
x:Name="DelegatedPermissionScopes"
|
||||
Header="Delegated Permission Scopes:"
|
||||
Text="Calendars.Read Mail.Read Mail.Send"
|
||||
Text="Calendars.Read Mail.Read Mail.Send User.Read"
|
||||
Visibility="Collapsed" />
|
||||
<TextBox Margin="0,0,0,12"
|
||||
x:Name="LoginHint"
|
||||
|
|
|
@ -21,6 +21,8 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
/// </summary>
|
||||
public class Tweet : Toolkit.Parsers.SchemaBase, ITwitterResult
|
||||
{
|
||||
private string _text;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets time item was created.
|
||||
/// </summary>
|
||||
|
@ -40,10 +42,14 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets text of the tweet (140 characters).
|
||||
/// Gets or sets text of the tweet (handles both 140 and 280 characters)
|
||||
/// </summary>
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
public string Text
|
||||
{
|
||||
get { return _text ?? FullText; }
|
||||
set { _text = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the extended mode.
|
||||
|
@ -63,6 +69,12 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
[JsonProperty("entities")]
|
||||
public TwitterEntities Entities { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Retweeted Tweet
|
||||
/// </summary>
|
||||
[JsonProperty("retweeted_status")]
|
||||
public Tweet RetweetedStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the creation date
|
||||
/// </summary>
|
||||
|
@ -79,5 +91,11 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
return dt;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets text of the tweet (280 characters).
|
||||
/// </summary>
|
||||
[JsonProperty("full_text")]
|
||||
private string FullText { get; set; }
|
||||
}
|
||||
}
|
|
@ -153,7 +153,7 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
string rawResult = null;
|
||||
try
|
||||
{
|
||||
var uri = new Uri($"{BaseUrl}/statuses/user_timeline.json?screen_name={screenName}&count={maxRecords}&include_rts=1");
|
||||
var uri = new Uri($"{BaseUrl}/statuses/user_timeline.json?screen_name={screenName}&count={maxRecords}&include_rts=1&tweet_mode=extended");
|
||||
|
||||
TwitterOAuthRequest request = new TwitterOAuthRequest();
|
||||
rawResult = await request.ExecuteGetAsync(uri, _tokens);
|
||||
|
@ -212,7 +212,7 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
{
|
||||
try
|
||||
{
|
||||
var uri = new Uri($"{BaseUrl}/search/tweets.json?q={Uri.EscapeDataString(hashTag)}&count={maxRecords}");
|
||||
var uri = new Uri($"{BaseUrl}/search/tweets.json?q={Uri.EscapeDataString(hashTag)}&count={maxRecords}&tweet_mode=extended");
|
||||
TwitterOAuthRequest request = new TwitterOAuthRequest();
|
||||
var rawResult = await request.ExecuteGetAsync(uri, _tokens);
|
||||
|
||||
|
@ -622,7 +622,7 @@ namespace Microsoft.Toolkit.Uwp.Services.Twitter
|
|||
{
|
||||
try
|
||||
{
|
||||
var uri = new Uri($"{BaseUrl}/statuses/home_timeline.json?count={maxRecords}");
|
||||
var uri = new Uri($"{BaseUrl}/statuses/home_timeline.json?count={maxRecords}&tweet_mode=extended");
|
||||
|
||||
TwitterOAuthRequest request = new TwitterOAuthRequest();
|
||||
var rawResult = await request.ExecuteGetAsync(uri, _tokens);
|
||||
|
|
|
@ -57,7 +57,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// </summary>
|
||||
private void NewImagelink_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
|
||||
{
|
||||
LinkHandled((string)(sender as Image).GetValue(HyperlinkUrlProperty), false);
|
||||
string hyperLink = (string)(sender as Image).GetValue(HyperlinkUrlProperty);
|
||||
bool isHyperLink = (bool)(sender as Image).GetValue(IsHyperlinkProperty);
|
||||
LinkHandled(hyperLink, isHyperLink);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -205,7 +205,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
/// <summary>
|
||||
/// Called when the render has a link we need to listen to.
|
||||
/// </summary>
|
||||
public void RegisterNewHyperLink(Image newImagelink, string linkUrl)
|
||||
public void RegisterNewHyperLink(Image newImagelink, string linkUrl, bool isHyperLink)
|
||||
{
|
||||
// Setup a listener for clicks.
|
||||
newImagelink.Tapped += NewImagelink_Tapped;
|
||||
|
@ -213,6 +213,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
// Associate the URL with the hyperlink.
|
||||
newImagelink.SetValue(HyperlinkUrlProperty, linkUrl);
|
||||
|
||||
// Set if the Image is HyperLink or not
|
||||
newImagelink.SetValue(IsHyperlinkProperty, isHyperLink);
|
||||
|
||||
// Add it to our list
|
||||
_listeningHyperlinks.Add(newImagelink);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
private static readonly DependencyProperty HyperlinkUrlProperty =
|
||||
DependencyProperty.RegisterAttached("HyperlinkUrl", typeof(string), typeof(MarkdownTextBlock), new PropertyMetadata(null));
|
||||
|
||||
// Checkes if clicked image is a hyperlink or not.
|
||||
private static readonly DependencyProperty IsHyperlinkProperty =
|
||||
DependencyProperty.RegisterAttached("IsHyperLink", typeof(string), typeof(MarkdownTextBlock), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dependency property for <see cref="CodeStyling"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
/// </summary>
|
||||
/// <param name="newImagelink">ImageLink to Register.</param>
|
||||
/// <param name="linkUrl">Url to Register.</param>
|
||||
void RegisterNewHyperLink(Image newImagelink, string linkUrl);
|
||||
/// <param name="isHyperLink">Is Image an IsHyperlink.</param>
|
||||
void RegisterNewHyperLink(Image newImagelink, string linkUrl, bool isHyperLink);
|
||||
}
|
||||
}
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Toolkit.Parsers.Markdown;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Blocks;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Render;
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
|
@ -328,6 +328,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
LineHeight = FontSize * 1.4
|
||||
};
|
||||
|
||||
textBlock.PointerWheelChanged += Preventative_PointerWheelChanged;
|
||||
|
||||
var paragraph = new Paragraph();
|
||||
textBlock.Blocks.Add(paragraph);
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Enums;
|
||||
using Microsoft.Toolkit.Parsers.Markdown;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Render;
|
||||
using Windows.UI.Text;
|
||||
|
@ -21,7 +21,6 @@ using Windows.UI.Xaml;
|
|||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Documents;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
||||
{
|
||||
|
@ -242,7 +241,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
var inlineCollection = localContext.InlineCollection;
|
||||
|
||||
var placeholder = InternalRenderTextRun(new TextRunInline { Text = element.Text, Type = MarkdownInlineType.TextRun }, context);
|
||||
var resolvedImage = await ImageResolver.ResolveImageAsync(element.Url, element.Tooltip);
|
||||
var resolvedImage = await ImageResolver.ResolveImageAsync(element.RenderUrl, element.Tooltip);
|
||||
|
||||
// if image can not be resolved we have to return
|
||||
if (resolvedImage == null)
|
||||
|
@ -250,22 +249,38 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
return;
|
||||
}
|
||||
|
||||
var image = new Image();
|
||||
var scrollViewer = new ScrollViewer();
|
||||
var viewbox = new Viewbox();
|
||||
scrollViewer.Content = viewbox;
|
||||
viewbox.Child = image;
|
||||
var image = new Image
|
||||
{
|
||||
Source = resolvedImage,
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
Stretch = ImageStretch
|
||||
};
|
||||
|
||||
var viewbox = new Viewbox
|
||||
{
|
||||
Child = image,
|
||||
StretchDirection = StretchDirection.DownOnly
|
||||
};
|
||||
|
||||
viewbox.PointerWheelChanged += Preventative_PointerWheelChanged;
|
||||
|
||||
var scrollViewer = new ScrollViewer
|
||||
{
|
||||
Content = viewbox,
|
||||
VerticalScrollMode = ScrollMode.Disabled,
|
||||
VerticalScrollBarVisibility = ScrollBarVisibility.Disabled
|
||||
};
|
||||
|
||||
var imageContainer = new InlineUIContainer() { Child = scrollViewer };
|
||||
|
||||
LinkRegister.RegisterNewHyperLink(image, element.Url);
|
||||
bool ishyperlink = false;
|
||||
if (element.RenderUrl != element.Url)
|
||||
{
|
||||
ishyperlink = true;
|
||||
}
|
||||
|
||||
image.Source = resolvedImage;
|
||||
image.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
image.VerticalAlignment = VerticalAlignment.Top;
|
||||
image.Stretch = ImageStretch;
|
||||
scrollViewer.VerticalScrollMode = ScrollMode.Disabled;
|
||||
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
|
||||
viewbox.StretchDirection = StretchDirection.DownOnly;
|
||||
LinkRegister.RegisterNewHyperLink(image, element.Url, ishyperlink);
|
||||
|
||||
if (ImageMaxHeight > 0)
|
||||
{
|
||||
|
|
|
@ -10,8 +10,11 @@
|
|||
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
|
||||
// ******************************************************************
|
||||
|
||||
using System.Reflection;
|
||||
using Windows.Foundation.Metadata;
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
||||
|
@ -26,6 +29,16 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
private static bool TextDecorationsSupported => (bool)(_textDecorationsSupported ??
|
||||
(_textDecorationsSupported = ApiInformation.IsTypePresent("Windows.UI.Text.TextDecorations")));
|
||||
|
||||
/// <summary>
|
||||
/// Super Hack to retain inertia and passing the Scroll data onto the Parent ScrollViewer.
|
||||
/// </summary>
|
||||
private static MethodInfo pointerWheelChanged = typeof(ScrollViewer).GetMethod("OnPointerWheelChanged", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Root Framework Element.
|
||||
/// </summary>
|
||||
private FrameworkElement RootElement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the interface that is used to register hyperlinks.
|
||||
/// </summary>
|
||||
|
|
|
@ -15,6 +15,7 @@ using Microsoft.Toolkit.Parsers.Core;
|
|||
using Microsoft.Toolkit.Parsers.Markdown;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Inlines;
|
||||
using Microsoft.Toolkit.Parsers.Markdown.Render;
|
||||
using Microsoft.Toolkit.Uwp.UI.Extensions;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Documents;
|
||||
|
@ -50,6 +51,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
public UIElement Render()
|
||||
{
|
||||
var stackPanel = new StackPanel();
|
||||
RootElement = stackPanel;
|
||||
Render(new UIElementCollectionRenderContext(stackPanel.Children) { Foreground = Foreground });
|
||||
|
||||
// Set background and border properties.
|
||||
|
@ -207,5 +209,23 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls.Markdown.Render
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Preventative_PointerWheelChanged(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
|
||||
{
|
||||
var pointerPoint = e.GetCurrentPoint((UIElement)sender);
|
||||
|
||||
if (pointerPoint.Properties.IsHorizontalMouseWheel)
|
||||
{
|
||||
e.Handled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var rootViewer = VisualTree.FindAscendant<ScrollViewer>(RootElement);
|
||||
if (rootViewer != null)
|
||||
{
|
||||
pointerWheelChanged?.Invoke(rootViewer, new object[] { e });
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -343,7 +343,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tick spacing, in units.
|
||||
/// Gets or sets the tick spacing, in units. Values of zero or less will be ignored when drawing.
|
||||
/// </summary>
|
||||
public int TickSpacing
|
||||
{
|
||||
|
@ -619,29 +619,32 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
radialGauge._root.Children.RemoveAll();
|
||||
radialGauge._compositor = radialGauge._root.Compositor;
|
||||
|
||||
// Ticks.
|
||||
SpriteVisual tick;
|
||||
for (double i = radialGauge.Minimum; i <= radialGauge.Maximum; i += radialGauge.TickSpacing)
|
||||
if (radialGauge.TickSpacing > 0)
|
||||
{
|
||||
tick = radialGauge._compositor.CreateSpriteVisual();
|
||||
tick.Size = new Vector2((float)radialGauge.TickWidth, (float)radialGauge.TickLength);
|
||||
tick.Brush = radialGauge._compositor.CreateColorBrush(radialGauge.TickBrush.Color);
|
||||
tick.Offset = new Vector3(100 - ((float)radialGauge.TickWidth / 2), 0.0f, 0);
|
||||
tick.CenterPoint = new Vector3((float)radialGauge.TickWidth / 2, 100.0f, 0);
|
||||
tick.RotationAngleInDegrees = (float)radialGauge.ValueToAngle(i);
|
||||
radialGauge._root.Children.InsertAtTop(tick);
|
||||
}
|
||||
// Ticks.
|
||||
SpriteVisual tick;
|
||||
for (double i = radialGauge.Minimum; i <= radialGauge.Maximum; i += radialGauge.TickSpacing)
|
||||
{
|
||||
tick = radialGauge._compositor.CreateSpriteVisual();
|
||||
tick.Size = new Vector2((float)radialGauge.TickWidth, (float)radialGauge.TickLength);
|
||||
tick.Brush = radialGauge._compositor.CreateColorBrush(radialGauge.TickBrush.Color);
|
||||
tick.Offset = new Vector3(100 - ((float)radialGauge.TickWidth / 2), 0.0f, 0);
|
||||
tick.CenterPoint = new Vector3((float)radialGauge.TickWidth / 2, 100.0f, 0);
|
||||
tick.RotationAngleInDegrees = (float)radialGauge.ValueToAngle(i);
|
||||
radialGauge._root.Children.InsertAtTop(tick);
|
||||
}
|
||||
|
||||
// Scale Ticks.
|
||||
for (double i = radialGauge.Minimum; i <= radialGauge.Maximum; i += radialGauge.TickSpacing)
|
||||
{
|
||||
tick = radialGauge._compositor.CreateSpriteVisual();
|
||||
tick.Size = new Vector2((float)radialGauge.ScaleTickWidth, (float)radialGauge.ScaleWidth);
|
||||
tick.Brush = radialGauge._compositor.CreateColorBrush(radialGauge.ScaleTickBrush.Color);
|
||||
tick.Offset = new Vector3(100 - ((float)radialGauge.ScaleTickWidth / 2), (float)radialGauge.ScalePadding, 0);
|
||||
tick.CenterPoint = new Vector3((float)radialGauge.ScaleTickWidth / 2, 100 - (float)radialGauge.ScalePadding, 0);
|
||||
tick.RotationAngleInDegrees = (float)radialGauge.ValueToAngle(i);
|
||||
radialGauge._root.Children.InsertAtTop(tick);
|
||||
// Scale Ticks.
|
||||
for (double i = radialGauge.Minimum; i <= radialGauge.Maximum; i += radialGauge.TickSpacing)
|
||||
{
|
||||
tick = radialGauge._compositor.CreateSpriteVisual();
|
||||
tick.Size = new Vector2((float)radialGauge.ScaleTickWidth, (float)radialGauge.ScaleWidth);
|
||||
tick.Brush = radialGauge._compositor.CreateColorBrush(radialGauge.ScaleTickBrush.Color);
|
||||
tick.Offset = new Vector3(100 - ((float)radialGauge.ScaleTickWidth / 2), (float)radialGauge.ScalePadding, 0);
|
||||
tick.CenterPoint = new Vector3((float)radialGauge.ScaleTickWidth / 2, 100 - (float)radialGauge.ScalePadding, 0);
|
||||
tick.RotationAngleInDegrees = (float)radialGauge.ValueToAngle(i);
|
||||
radialGauge._root.Children.InsertAtTop(tick);
|
||||
}
|
||||
}
|
||||
|
||||
// Needle.
|
||||
|
|
|
@ -396,10 +396,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
rangeSelector.RangeMax = newValue;
|
||||
}
|
||||
|
||||
if (newValue < oldValue)
|
||||
{
|
||||
rangeSelector.SyncThumbs();
|
||||
}
|
||||
rangeSelector.SyncThumbs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -448,10 +445,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
rangeSelector.RangeMin = newValue;
|
||||
}
|
||||
|
||||
if (newValue > oldValue)
|
||||
{
|
||||
rangeSelector.SyncThumbs();
|
||||
}
|
||||
rangeSelector.SyncThumbs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -497,26 +491,18 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
if (newValue < rangeSelector.Minimum)
|
||||
{
|
||||
rangeSelector.RangeMin = rangeSelector.Minimum;
|
||||
return;
|
||||
}
|
||||
|
||||
if (newValue > rangeSelector.Maximum)
|
||||
else if (newValue > rangeSelector.Maximum)
|
||||
{
|
||||
rangeSelector.RangeMin = rangeSelector.Maximum;
|
||||
return;
|
||||
}
|
||||
|
||||
rangeSelector.SyncActiveRectangle();
|
||||
|
||||
if (newValue > rangeSelector.RangeMax)
|
||||
else if (newValue > rangeSelector.RangeMax)
|
||||
{
|
||||
rangeSelector.RangeMax = newValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeSelector.SyncActiveRectangle();
|
||||
}
|
||||
|
||||
rangeSelector.SyncThumbs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -562,26 +548,18 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
|
|||
if (newValue < rangeSelector.Minimum)
|
||||
{
|
||||
rangeSelector.RangeMax = rangeSelector.Minimum;
|
||||
return;
|
||||
}
|
||||
|
||||
if (newValue > rangeSelector.Maximum)
|
||||
else if (newValue > rangeSelector.Maximum)
|
||||
{
|
||||
rangeSelector.RangeMax = rangeSelector.Maximum;
|
||||
return;
|
||||
}
|
||||
|
||||
rangeSelector.SyncActiveRectangle();
|
||||
|
||||
if (newValue < rangeSelector.RangeMin)
|
||||
else if (newValue < rangeSelector.RangeMin)
|
||||
{
|
||||
rangeSelector.RangeMin = newValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeSelector.SyncActiveRectangle();
|
||||
}
|
||||
|
||||
rangeSelector.SyncThumbs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -409,10 +409,15 @@ namespace Microsoft.Toolkit.Uwp.UI
|
|||
var folder = await GetCacheFolderAsync().ConfigureAwait(false);
|
||||
baseFile = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false) as StorageFile;
|
||||
|
||||
if (baseFile == null || await IsFileOutOfDateAsync(baseFile, CacheDuration).ConfigureAwait(false))
|
||||
bool downloadDataFile = baseFile == null || await IsFileOutOfDateAsync(baseFile, CacheDuration).ConfigureAwait(false);
|
||||
|
||||
if (baseFile == null)
|
||||
{
|
||||
baseFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting).AsTask().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (downloadDataFile)
|
||||
{
|
||||
uint retries = 0;
|
||||
try
|
||||
{
|
||||
|
|
|
@ -472,9 +472,9 @@ namespace UnitTests.Markdown.Parse
|
|||
[TestCategory("Parse - inline")]
|
||||
public void Hyperlink_Negative_SchemeOnly()
|
||||
{
|
||||
AssertEqual("http:",
|
||||
AssertEqual("http",
|
||||
new ParagraphBlock().AddChildren(
|
||||
new TextRunInline { Text = "http:" }));
|
||||
new TextRunInline { Text = "http" }));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -508,9 +508,9 @@ namespace UnitTests.Markdown.Parse
|
|||
[TestCategory("Parse - inline")]
|
||||
public void Hyperlink_Negative_AngleBracketsPrefixOnly()
|
||||
{
|
||||
AssertEqual("<http://>",
|
||||
AssertEqual("<http>",
|
||||
new ParagraphBlock().AddChildren(
|
||||
new TextRunInline { Text = "<http://>" }));
|
||||
new TextRunInline { Text = "<http>" }));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -32,7 +32,9 @@ namespace UnitTests.Markdown.Parse
|
|||
Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =1)",
|
||||
Tooltip = "SVG logo",
|
||||
ImageWidth = 1,
|
||||
ImageHeight = 0
|
||||
ImageHeight = 0,
|
||||
RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg",
|
||||
ReferenceId = string.Empty
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -49,7 +51,9 @@ namespace UnitTests.Markdown.Parse
|
|||
Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =x1)",
|
||||
Tooltip = "SVG logo",
|
||||
ImageWidth = 0,
|
||||
ImageHeight = 1
|
||||
ImageHeight = 1,
|
||||
RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg",
|
||||
ReferenceId = string.Empty
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -66,7 +70,9 @@ namespace UnitTests.Markdown.Parse
|
|||
Tooltip = "SVG logo",
|
||||
Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg =128x64)",
|
||||
ImageWidth = 128,
|
||||
ImageHeight = 64
|
||||
ImageHeight = 64,
|
||||
RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg",
|
||||
ReferenceId = string.Empty
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -83,7 +89,9 @@ namespace UnitTests.Markdown.Parse
|
|||
Tooltip = "SVG logo",
|
||||
Text = "![SVG logo](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg%20=32)",
|
||||
ImageWidth = 0,
|
||||
ImageHeight = 0
|
||||
ImageHeight = 0,
|
||||
RenderUrl = "https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg%20=32",
|
||||
ReferenceId = string.Empty
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,18 +32,28 @@ If you don't have one, you need to create an Office 365 Developer Site. There ar
|
|||
|
||||
### 2. Register you application in Azure Active Directory
|
||||
|
||||
To authenticate your app, you need to register your app with Azure AD, and provide some details about your app. You can register your app manually by using the [Azure Management Portal](http://manage.windowsazure.com), or by using Visual Studio.
|
||||
To authenticate your app, you need to register your app with Azure AD, and provide some details about your app.
|
||||
|
||||
To register your app manually, see [Manually register your app with Azure AD so it can access Office 365 APIs.](https://msdn.microsoft.com/en-us/office/office365/howto/add-common-consent-manually)
|
||||
#### Register the App to use Azure AD v1 Endpoint
|
||||
|
||||
To register your app by using Visual Studio, see [Using Visual Studio to register your app and add Office 365 APIs.](https://msdn.microsoft.com/office/office365/HowTo/adding-service-to-your-Visual-Studio-project)
|
||||
You can register your app manually by using the [Azure Management Portal](http://portal.azure.com), or by using Visual Studio:
|
||||
1. To register your app by using Visual Studio, see [Using Visual Studio to register your app and add Office 365 APIs.](https://msdn.microsoft.com/office/office365/HowTo/adding-service-to-your-Visual-Studio-project)
|
||||
2. To register your app manually, see [Manually register your app with Azure AD so it can access Office 365 APIs.](https://msdn.microsoft.com/en-us/office/office365/howto/add-common-consent-manually). Here is a summary to register your App manually:
|
||||
- Go to the [Azure Management Portal](http://portal.azure.com)
|
||||
- Go to the "Azure Active Directory" option
|
||||
- Go to "App Registrations" option
|
||||
- Click on the "New application registration" button
|
||||
- Enter a name for your App
|
||||
- Specify your application as a **Native**
|
||||
- Specify the Redirect Uri as **urn:ietf:wg:oauth:2.0:oob**
|
||||
- Click "Create" button
|
||||
|
||||
After you've registered your app, Azure AD will generate a client ID for your app. You'll need to use this client ID to get your access token.
|
||||
|
||||
When you register your app in the [Azure Management Portal](http://manage.windowsazure.com), you will need to configure details about your application with the following steps:
|
||||
When you register your app in the [Azure Management Portal](http://portal.azure.com), you will need to configure details about your application with the following steps:
|
||||
|
||||
1. Specify your application as a **Web application and/or web API**
|
||||
2. Specify the Redirect Uri as **http://localhost:8000**
|
||||
1. Click "Settings" button
|
||||
2. Go to "Required permissions" option
|
||||
3. Add Application: Choose **Microsoft Graph** API
|
||||
4. Specify the permission levels the MicrosoftGraph Service requires from the Office 365 API (Microsoft Graph). Choose at least:
|
||||
* **Sign in and read user profile** to access user's profile.
|
||||
|
@ -54,10 +64,20 @@ When you register your app in the [Azure Management Portal](http://manage.window
|
|||
|
||||
|Setting|Value|
|
||||
|----------|:-------------:|
|
||||
|Web application and/or web API|Yes|
|
||||
|Redirect Uri|http://localhost:8080|
|
||||
|Native application|Yes|
|
||||
|Redirect Uri|urn:ietf:wg:oauth:2.0:oob|
|
||||
|Resource to Add|Microsoft Graph|
|
||||
|Delegate Permissions |Sign in and read user profile, Read user mail and Send mail, Read user calendars|
|
||||
|Delegate Permissions |Sign in and read user profile, Read user mail, Send mail as a user, Read user calendars|
|
||||
|
||||
#### Register the App to use Azure AD v2 Endpoint
|
||||
|
||||
1. Go to the [App Registration Portal](https://apps.dev.microsoft.com)
|
||||
2. Click in the "Add an app" button.
|
||||
3. Enter the app name and click "create"
|
||||
4. Once the App is created, copy the Application Id to use it later.
|
||||
5. Next, add a Platform to the App clicking in "Add Platform" and select "Native Application" tile.
|
||||
6. Scroll to the Microsoft Graph Permissions section (by default the User.Read permission is added). Add the following permissions: Sign in and read user profile, Read user mail, Send mail as a user, Read user calendars.
|
||||
7. Finally, save your changes.
|
||||
|
||||
## Syntax
|
||||
|
||||
|
|
|
@ -34,10 +34,11 @@ In the code section below the GetUserTimeLineAsync method returns some Tweet obj
|
|||
| Property | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| **CreatedAt** | string | The date and time of the Tweet formatted by Twitter |
|
||||
| **Text** | string | The text of the Tweet |
|
||||
| **Text** | string | The text of the Tweet (if retweet, the text might not be complete - use the RetweetedStatus object for the original tweet)|
|
||||
| **Id** | string | The Twitter status identifier |
|
||||
| **GeoData** | TwitterGeoData | A class containing the latitude and longitude of the Tweet |
|
||||
| **User** | TwitterUser | A class containing the user ID, Name, ScreenName, and ProfileImageUrl |
|
||||
| **RetweetedStatus** | Tweet | if this tweet is a retweet, this object will contain the original tweet |
|
||||
|
||||
## Syntax
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче