diff --git a/README.md b/README.md index 07e32cb7c91b..4b9d11fe47f6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ - ## **Pixel-Perfect. Multi-Platform. C# & Windows XAML. Today.** [![NuGet](https://img.shields.io/nuget/v/uno.sdk.svg?style=flat&color=159bff)](https://www.nuget.org/packages/uno.sdk/) @@ -16,6 +15,7 @@ [![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-brightgreen.svg?style=flat)](https://github.com/unoplatform/uno/blob/master/CONTRIBUTING.md) # What is the Uno Platform? + The Uno Platform is an Open-source platform for building single codebase native mobile, web, desktop, and embedded apps quickly. It allows C# and WinUI XAML and/or C# code to run on all target platforms, while allowing you to control every pixel. It comes with support for Fluent, Material, and Cupertino design systems out of the box. Uno Platform implements a growing number of the WinUI APIs, such as **Microsoft.UI.Xaml** to build your UI, and WinRT to get cross platform access to non-UI APIs (sensors, file system, devices, etc...), to enable WinUI applications to run on all platforms with native performance. @@ -34,6 +34,7 @@ For a larger example and features demo: * Try the [WebAssembly Uno Playground](https://playground.platform.uno) live in your browser. # Uno Platform Features + * Supported platforms: * Windows 10 and Windows 11 * Windows 7 (via Skia Desktop) @@ -47,7 +48,7 @@ For a larger example and features demo: * [Uno.UITest](https://github.com/unoplatform/Uno.UITest), a library to create Cross-Platform UI Tests for WebAssembly, iOS, and Android. * Cross Platform Controls: * [Control Templating](https://learn.microsoft.com/windows/uwp/design/controls-and-patterns/control-templates) - * [Data Templating](https://code.msdn.microsoft.com/Data-Binding-in-UWP-b5c98114) + * [Data Templating](https://learn.microsoft.com/windows/uwp/data-binding) * [Styling](https://learn.microsoft.com/windows/uwp/design/controls-and-patterns/xaml-styles) * [Rich Animations](https://learn.microsoft.com/windows/uwp/design/motion/xaml-animation) * [Composition API](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/composition) @@ -65,7 +66,7 @@ For a larger example and features demo: * [ColorCode-Universal](https://github.com/unoplatform/uno.ColorCode-Universal) * [LibVLCSharp](https://github.com/videolan/libvlcsharp) * [MapsUI](https://github.com/Mapsui/Mapsui) - * [LiveCharts](https://github.com/beto-rodriguez/LiveCharts2) + * [LiveCharts2](https://github.com/beto-rodriguez/LiveCharts2) * Any WinUI project * Responsive Design: * [Visual State Manager](https://learn.microsoft.com/uwp/api/Microsoft.UI.Xaml.VisualStateManager) @@ -74,7 +75,7 @@ For a larger example and features demo: * Platform Specific: * Native controls and properties via [conditional XAML](doc/articles/platform-specific-xaml.md) * Any of the existing Xamarin iOS/Android libraries available - + # Live WebAssembly Apps Here's a list of live apps made with the Uno Platform for WebAssembly. @@ -82,7 +83,10 @@ Here's a list of live apps made with the Uno Platform for WebAssembly. * The [Uno Platform Playground](https://playground.platform.uno) ([Source](https://github.com/unoplatform/uno.Playground)). * The [Uno Gallery](https://gallery.platform.uno) demonstrates the use of Fluent and Material guidelines. * The [NuGet Package Explorer](https://nuget.info) ([Source](https://github.com/NuGetPackageExplorer/NuGetPackageExplorer)). -* The [Uno Calculator](https://calculator.platform.uno), a simple yet powerful iOS/Android/WebAssembly C# port of the calculator that ships with Windows ([Source](https://github.com/unoplatform/calculator)). Also try the [iOS version](https://apps.apple.com/app/id1464736591), the [Android version](https://play.google.com/store/apps/details?id=uno.platform.calculator) and [Linux version](https://snapcraft.io/uno-calculator). +* The [Uno Calculator](https://calculator.platform.uno), a simple yet powerful iOS/Android/WebAssembly C# port of the calculator that ships with Windows ([Source](https://github.com/unoplatform/calculator)), but is also available on other Platforms: + * [iOS version](https://apps.apple.com/app/id1464736591) + * [Android version](https://play.google.com/store/apps/details?id=uno.platform.calculator) + * [Linux version](https://snapcraft.io/uno-calculator). * The [Community Toolkit Labs App](https://toolkitlabs.dev/) * [SkiaSharp fork for the Uno Platform](https://skiasharp-wasm.platform.uno/), Skia is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library ([Source](https://github.com/unoplatform/Uno.SkiaSharp)). * The [Uno.WindowsCommunityToolkit](https://windowstoolkit-wasm.platform.uno/) ([Source](https://github.com/unoplatform/uno.WindowsCommunityToolkit)). @@ -106,6 +110,7 @@ Contribute to Uno in your browser using [GitPod.io](https://gitpod.io), follow [ [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/unoplatform/uno) # Contributors + Thanks go to these wonderful people (List made with [contrib.rocks](https://contrib.rocks)): [![Uno Platform Contributors](https://contrib.rocks/image?repo=unoplatform/uno&max=500)](https://github.com/unoplatform/uno/graphs/contributors) diff --git a/build/cSpell.json b/build/cSpell.json index 07983340dead..274bee6eaa0a 100644 --- a/build/cSpell.json +++ b/build/cSpell.json @@ -25,11 +25,13 @@ "datacontext", "datagrid", "decompile", + "deeplink", "devs", "dbus", "Dismissable", "dmgbuild", - "Docfx", + "docfx", + "dotnet", "ellipsize", "Entra", "Expando", @@ -54,6 +56,7 @@ "laggy", "layouter", "layouting", + "Layouting", "Listview", "listviewbase", "Linq", @@ -71,6 +74,7 @@ "netstandard", "neumorphic", "oidc", + "Omni", "Omnisharp", "overscroll", "Packt", @@ -79,6 +83,7 @@ "Pluralsight", "POSIX", "reentrantly", + "resizetizer", "Resizetizer", "resw", "roadmap", @@ -121,156 +126,156 @@ "subviews" ], "ignoreWords": [ - "ADAL", - "AEHD", - "appsettings", - "applicationdata", - "applicationmodel", - "Authenticode", - "automagically", - "bluetoothdevice", - "browserwasm", - "commandbar", - "CLSID", - "datatransfer", - "Divio's", - "emcc", - "emscripten", - "Flatpickr", - "Giesel", - "GPIO", - "hdpi", - "Headered", - "Hoefling", - "HRESULT", - "IDBFS", - "Infragistics", - "Jiterpreter", - "jonathanpeppers's", - "Krueger", - "kiota", - "libgtk", - "libwebkit", - "libvlc", - "lightsensor", - "Liu's", - "macios", - "Matteo", - "McCaffrey", - "mdpi", - "Mergify", - "mlaunch", - "netstd", - "nventive", - "odel", - "pdate", - "progressring", - "pwsh", - "Ronica", - "Serilog", - "Sideloading", - "sideload", - "Singh", - "slnf", - "startscreen", - "Stetho", - "Talkin", - "timeentry", - "UADO", - "Udemy", - "UNOB", - "UNOX", - "UVSC", - "uitest", - "upri", - "userprofile", - "winui", - "xhdpi", - "xxhdpi", - "xxxhdpi", - "illinker", - "Onoh", - "Findlay", - "Logpoints", - "addin", - "Yowza", - "unpackaged", - "GNSS", - "vibrationdevice", - "viewmanagement", - "winappsdk", - "notimplemented", - "winrt", - "winapp", - "wapproj's", - "xamlmerge", - "xbind", - "xcprivacy", - "jlaban", - "sasakrsmanovic", - "maccatalyst", - "settingscard", - "storecontext", - "tvos", - "appleuikit", - "uikit", - "settingscard", - "trackpad", - "COEP", - "TFMs" + "ADAL", + "AEHD", + "appsettings", + "applicationdata", + "applicationmodel", + "Authenticode", + "automagically", + "bluetoothdevice", + "browserwasm", + "commandbar", + "CLSID", + "datatransfer", + "Divio's", + "emcc", + "emscripten", + "Flatpickr", + "Giesel", + "GPIO", + "hdpi", + "Headered", + "Hoefling", + "HRESULT", + "IDBFS", + "Infragistics", + "Jiterpreter", + "jonathanpeppers's", + "Krueger", + "kiota", + "libgtk", + "libwebkit", + "libvlc", + "lightsensor", + "Liu's", + "macios", + "Matteo", + "McCaffrey", + "mdpi", + "Mergify", + "mlaunch", + "netstd", + "nventive", + "odel", + "pdate", + "progressring", + "pwsh", + "Ronica", + "Serilog", + "Sideloading", + "sideload", + "Singh", + "slnf", + "startscreen", + "Stetho", + "Talkin", + "timeentry", + "UADO", + "Udemy", + "UNOB", + "UNOX", + "UVSC", + "uitest", + "upri", + "userprofile", + "winui", + "xhdpi", + "xxhdpi", + "xxxhdpi", + "illinker", + "Onoh", + "Findlay", + "Logpoints", + "addin", + "Yowza", + "unpackaged", + "GNSS", + "vibrationdevice", + "viewmanagement", + "winappsdk", + "notimplemented", + "winrt", + "winapp", + "wapproj's", + "xamlmerge", + "xbind", + "xcprivacy", + "jlaban", + "sasakrsmanovic", + "maccatalyst", + "settingscard", + "storecontext", + "tvos", + "appleuikit", + "uikit", + "settingscard", + "trackpad", + "COEP", + "TFMs" ], "patterns": [ - { - "name": "Markdown uid", - "pattern": "^(?=uid:).*$", - "description": "" - }, - { - "name": "Markdown links", - "pattern": "\\((.*)\\)", - "description": "" - }, - { - "name": "Markdown code blocks", - "pattern": "/^(\\s*`{3,}).*[\\s\\S]*?^\\1/gmx", - "description": "Taken from the cSpell example at https://cspell.org/configuration/patterns/#verbose-regular-expressions" - }, - { - "name": "Inline code blocks", - "pattern": "\\`([^\\`\\r\\n]+?)\\`", - "description": "https://stackoverflow.com/questions/41274241/how-to-capture-inline-markdown-code-but-not-a-markdown-code-fence-with-regex" - }, - { - "name": "Link contents", - "pattern": "\\", - "description": "" - }, - { - "name": "Snippet references", - "pattern": "-- snippet:(.*)", - "description": "" - }, - { - "name": "Snippet references 2", - "pattern": "\\<\\[sample:(.*)", - "description": "another kind of snippet reference" - }, - { - "name": "Multi-line code blocks", - "pattern": "/^\\s*```[\\s\\S]*?^\\s*```/gm" - } + { + "name": "Markdown uid", + "pattern": "^(?=uid:).*$", + "description": "" + }, + { + "name": "Markdown links", + "pattern": "\\((.*)\\)", + "description": "" + }, + { + "name": "Markdown code blocks", + "pattern": "/^(\\s*`{3,}).*[\\s\\S]*?^\\1/gmx", + "description": "Taken from the cSpell example at https://cspell.org/configuration/patterns/#verbose-regular-expressions" + }, + { + "name": "Inline code blocks", + "pattern": "\\`([^\\`\\r\\n]+?)\\`", + "description": "https://stackoverflow.com/questions/41274241/how-to-capture-inline-markdown-code-but-not-a-markdown-code-fence-with-regex" + }, + { + "name": "Link contents", + "pattern": "\\", + "description": "" + }, + { + "name": "Snippet references", + "pattern": "-- snippet:(.*)", + "description": "" + }, + { + "name": "Snippet references 2", + "pattern": "\\<\\[sample:(.*)", + "description": "another kind of snippet reference" + }, + { + "name": "Multi-line code blocks", + "pattern": "/^\\s*```[\\s\\S]*?^\\s*```/gm" + } ], "ignoreRegExpList": [ - "Markdown uid", - "Markdown links", - "Markdown code blocks", - "Inline code blocks", - "Link contents", - "Snippet references", - "Snippet references 2", - "Multi-line code blocks" + "Markdown uid", + "Markdown links", + "Markdown code blocks", + "Inline code blocks", + "Link contents", + "Snippet references", + "Snippet references 2", + "Multi-line code blocks" ], "ignorePaths": [ - "../doc/index.md" + "../doc/index.md" ] } diff --git a/doc/.feature-template-uno-only.md b/doc/.feature-template-uno-only.md index 96928942699d..a331990d0889 100644 --- a/doc/.feature-template-uno-only.md +++ b/doc/.feature-template-uno-only.md @@ -1,4 +1,6 @@ - +--- +uid: Uno.Doc-Templates.Feature.Uno-only +--- # YourFeature @@ -18,7 +20,7 @@ -| Feature | Windows | Android | iOS | Web (WASM) | macOS | Linux (Skia) | Win 7 (Skia) | +| Feature | Windows | Android | iOS | Web (WASM) | macOS | Linux (Skia) | Win 7 (Skia) | |---------------|-------|-------|-------|-------|-------|-------|-| | Feature1 | ✔ | ✔/✖ (choose appropriate) | ? (fill in) | ? | ? | ? | ? | | Feature2... | ✔ | ? | ? | ? | ? | ? | ? | diff --git a/doc/.feature-template.md b/doc/.feature-template.md index b3822ecb6667..c14fa8676ebf 100644 --- a/doc/.feature-template.md +++ b/doc/.feature-template.md @@ -1,9 +1,11 @@ - +--- +uid: Uno.Doc-Templates.Feature.Uno-Specifics +--- # YourFeature - + > [!TIP] > This article covers Uno-specific information for YourFeature. For a full description of the feature and instructions on using it, see [Link text](https://learn.microsoft.com/doc_link) @@ -12,7 +14,7 @@ ## Supported features -| Feature | Windows | Android | iOS | Web (WASM) | macOS | Linux (Skia) | Win 7 (Skia) | +| Feature | Windows | Android | iOS | Web (WASM) | macOS | Linux (Skia) | Win 7 (Skia) | |---------------|-------|-------|-------|-------|-------|-------|-| | Feature1 | ✔ | ✔/✖ (choose appropriate) | ? (fill in) | ? | ? | ? | ? | | Feature2... | ✔ | ? | ? | ? | ? | ? | ? | diff --git a/doc/.howto-template.md b/doc/.howto-template.md index 265c9c196503..8fb484fd6e30 100644 --- a/doc/.howto-template.md +++ b/doc/.howto-template.md @@ -1,3 +1,7 @@ +--- +uid: Uno.Doc-Templates.How-To +--- + # How to [complete TaskX] @@ -9,7 +13,7 @@ * If your guide ends up being very long, consider splitting it into multiple pages. * Do place your doc in the doc/articles/guides directory. If you have multiple pages, put them in their own subdirectory. * Do include screenshots showing what the output looks like. -* Do **preserve the correct formatting** for parts of this template that are in DocFX-flavored Markdown - https://platform.uno/docs/articles/uno-development/docfx.html#docfx-flavored-markdown +* Do **preserve the correct formatting** for parts of this template that are in [DocFX-flavored Markdown](articles/contributing/Documentation/docfx.md#docfx-flavored-markdown) * Add a short intro explaining who and what your guide is for. @@ -32,21 +36,17 @@ * [**Mono**](https://www.mono-project.com/download/stable/) -* **.NET Core SDK** - * [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1) (**version 3.1.8 (SDK 3.1.402)** or later) - * [.NET Core 5.0 SDK](https://dotnet.microsoft.com/download/dotnet-core/5.0) (**version 5.0 (SDK 5.0.100)** or later) +* **.NET SDK** + * [latest .NET SDK](https://dotnet.microsoft.com/en-us/download) > Use `dotnet --version` from the terminal to get the version installed. ### [JetBrains Rider](#tab/tabid-rider) -* [**Rider Version 2020.2+**](https://www.jetbrains.com/rider/download/) -* [**Rider Xamarin Android Support Plugin**](https://plugins.jetbrains.com/plugin/12056-rider-xamarin-android-support/) (you may install it directly from Rider) +* [**Rider**](https://www.jetbrains.com/rider/download/) --- -
- > [!TIP] > For a step-by-step guide to installing the prerequisites for your preferred IDE and environment, consult the [Get Started guide](../get-started.md). @@ -60,8 +60,6 @@ See the completed sample on GitHub: [YourSample](https://github.com/unoplatform/Uno.Samples/tree/master/UI/YourSample) -
- --- [!include[getting-help](includes/getting-help.md)] diff --git a/doc/README.md b/doc/README.md index b3930b0480a4..7960d818f21a 100644 --- a/doc/README.md +++ b/doc/README.md @@ -45,17 +45,17 @@ npm install ## Generated Implemented views -The process of generating implemented views is documented on this page. [Building docs website locally with DocFX](https://platform.uno/docs/articles/uno-development/docfx.html?tabs=tabid-1#building-docs-website-locally-with-docfx). -As stated in the documentation, it will probably fail, but it will create stub files and let DocFx build without errors. -By default, the build swallows DocFx errors (it prints them in the console), that is for simplicity since you don't need -the implemented views. To test DocFx and break on error run the `npm run strict` command. +The process of generating implemented views is documented on this page. [Building docs website locally with DocFX](xref:Uno.Contributing.docfx#building-docs-website-locally-with-docfx). +As stated in the documentation, it will probably fail, but it will create stub files and let docfx build without errors. +By default, the build swallows docfx errors (it prints them in the console), that is for simplicity since you don't need +the implemented views. To test docfx and break on error run the `npm run strict` command. ## Deploy -DocFx will use the content of the `styles` folder when building. When working locally, source-maps are generated to help +docfx will use the content of the `styles` folder when building. When working locally, source-maps are generated to help debugging the site; the javascript and css are not minified for the same reason. It's very important that the build command is ran just before committing your work; this will minify the code, clean up the `styles` and `_site` -folders and build the DocFx according to the `docfx.json`. The CI only runs the DocFx command, it will not regenerate +folders and build the docfx according to the `docfx.json`. The CI only runs the docfx command, it will not regenerate the `styles` folder. ## Commands @@ -124,18 +124,18 @@ Every file in the `styles` folder is automatically generated and should not be m Spell-checking for the docs is done as part of a GitHub Action. -If you'd like to perform the same check locally, you can run: +If you'd like to perform the same check locally, you can use the vs code extension `Code Spell Checker` and configure it to use the [cSpell.json](../build/cSpell.json) file in the directory `build` of the Uno Repository, or use the npm provided version and run: -* `npm install -g cspell@8.3.2` to install the cSpell CLI +* `npm install -g cspell@latest` to install the cSpell CLI * `cspell --config ./cSpell.json "doc/**/*.md" --no-progress` to check all the markdown files in the `doc` folder. ### Markdown linting the docs Markdown linting for the docs is done as part of a GitHub Action. -If you'd like to perform the same check locally, you can run: +If you'd like to perform the same check locally, you can use the vs code extension `markdownlint` or use npm with running: -* `npm install -g markdownlint-cli@0.38.0` to install the markdownlint CLI +* `npm install -g markdownlint-cli@latest` to install the markdownlint CLI * `markdownlint "doc/**/*.md"` to lint all the markdown files in the `doc` folder. You can also install the [markdownlint Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) to easily check markdown linting and style while writing documentation. @@ -146,4 +146,4 @@ The local environment is usually located on port `3000` unless another process i You have to remove the `docs` fragment from the WordPress menu to reach your local documentation server. -For detailed instructions on how to run DocFx locally, please refer to the [DocFx Local Setup Guide](https://platform.uno/docs/articles/uno-development/docfx.html?tabs=tabid-1). +For detailed instructions on how to run docfx locally, please refer to the [docfx Local Setup Guide](xref:Uno.Contributing.docfx). diff --git a/doc/articles/contributing/Documentation/anchor-links.md b/doc/articles/contributing/Documentation/anchor-links.md new file mode 100644 index 000000000000..1371aa7dbcb8 --- /dev/null +++ b/doc/articles/contributing/Documentation/anchor-links.md @@ -0,0 +1,52 @@ +--- +uid: Uno.Contributing.Documentation.Anchor-links +--- + +# Anchor Links in Documentation + +Anchor links (also called **fragment links**) allow you to link directly to a specific section within a doc file. They are useful for cross-referencing headings and improving navigation in long documentation pages. + +## How Anchor Links Work + +Anchor links in docfx (and Markdig) are automatically generated from Markdown headings. For example: + +```markdown +## My Section Title +``` + +Generates the anchor: + +```md +#my-section-title +``` + +You can then link to this section using: + +```markdown +[Jump to My Section](#my-section-title) +``` + +> [!NOTE] +> Anchors are generated by converting the heading to lowercase and replacing spaces and most special characters with hyphens. + +## Best Practices + +- Use anchor links to help readers jump between related sections. +- Always verify that the anchor exists to avoid broken links. +- Avoid using identical headings in the same file – they will result in duplicate anchors. + +## Linking to Anchors in Other Files + +You can link to a specific heading in another Markdown file like this: + +```markdown +[Go to Subsection](otherfile.md#subsection-heading) +``` + +Make sure the linked file is part of the TOC or referenced properly so that DocFX includes it in the output. + +## Common Pitfalls + +- ❌ `#My-Section-Title` → won't work (wrong casing) +- ❌ `#my section title` → won't work (missing `-` between the words) +- ❌ Linking to headings that are dynamically generated (e.g., via include files) may break if anchors are not preserved diff --git a/doc/articles/uno-development/doc-on-docs.md b/doc/articles/contributing/Documentation/doc-on-docs.md similarity index 85% rename from doc/articles/uno-development/doc-on-docs.md rename to doc/articles/contributing/Documentation/doc-on-docs.md index b5dd9836708e..f7c5270c3f3a 100644 --- a/doc/articles/uno-development/doc-on-docs.md +++ b/doc/articles/contributing/Documentation/doc-on-docs.md @@ -2,25 +2,25 @@ uid: Uno.Contributing.Docs --- -# Contributing docs to Uno Platform +# Contributing Documentation to Uno Platform Good documentation is essential, and writing docs is a valued contribution that makes Uno more useful for everybody. This article covers *when* to write docs and *what* you should write, with a focus on two of the most common forms of documentation: step-by-step guides (ie howtos or tutorials), and feature documentation. We have a few different fill-in-the-blanks style templates, linked below. -For the DocFX tool used to build the docs website, see [more info here](docfx.md). +For the DocFX tool used to build the docs website, see [more info here](xref:Uno.Contributing.docfx). ## Key links -* how-to template: https://github.com/unoplatform/uno/blob/master/doc/.howto-template.md -* WinUI feature template: https://github.com/unoplatform/uno/blob/master/doc/.feature-template.md -* Uno-only feature template: https://github.com/unoplatform/uno/blob/master/doc/.feature-template-uno-only.md +* [How-to template](xref:Uno.Doc-Templates.How-To) +* [WinUI feature template](xref:Uno.Doc-Templates.Feature.Uno-Specifics) +* [Uno-only feature template](xref:Uno.Doc-Templates.Feature.Uno-only) ## Resources Some useful resources on writing good technical documentation: -* [ReactiveUI docs style guide](https://www.reactiveui.net/contribute/content-style-guide/) +* [ReactiveUI docs style guide](https://www.reactiveui.net/contribute/content-style-guide/grammar-and-mechanics.html) * [Divio's Documentation System](https://documentation.divio.com/) ## Writing step-by-step guides @@ -29,7 +29,7 @@ Step-by-step guides that address a particular problem or use case that multiple * For longer tutorials, it's fine to split the content over multiple pages. * Guides should always be accompanied by working code. Standalone applications should be added to the [Uno.Samples repository](https://github.com/unoplatform/Uno.Samples) and linked to from the associated tutorial. -* Use the [how-to template](https://github.com/unoplatform/uno/blob/master/doc/.howto-template.md) as a starting point. +* Use the [how-to template](xref:Uno.Doc-Templates.How-To) as a starting point. * Structure guides as a series of clear, actionable steps. After carrying out every step as described, the user should end up with working code that demonstrates the objective of the guide (either a standalone sample, or a new feature in their existing app). ## Documenting features @@ -44,7 +44,7 @@ There's two different cases: Uno's API matches WinUI's API, and most of the time, a new Uno feature will map to an existing WinUI feature. -In this case, to the extent that the behavior you're adding is the same as the WinUI behavior, you **don't** need to add documentation. The existing WinUI documentation is fine. It's already linked to from [Uno's reference documentation](../implemented-views.md). +In this case, to the extent that the behavior you're adding is the same as the WinUI behavior, you **don't** need to add documentation. The existing WinUI documentation is fine. It's already linked to from [Uno's reference documentation](../../implemented-views.md). What if the Uno behavior deviates from WinUI behavior? @@ -58,7 +58,7 @@ In those cases, it's important to add documentation. Copy the [WinUI feature tem Rarely, features are added to Uno Platform that aren't part of WinUI (`VisibleBoundsPadding` and `ElevatedView` are two examples). Somewhat more commonly, platform-specific functionality or options are added to an existing feature. -It's important to document these novel features when you add them, since they aren't covered anywhere else. Again, copy the [Uno-only feature template here](https://github.com/unoplatform/uno/blob/master/doc/.feature-template-uno-only.md) to the [features directory](https://github.com/unoplatform/uno/tree/master/doc/articles/features) and fill in the sections. +It's important to document these novel features when you add them, since they aren't covered anywhere else. Again, copy the [Uno-only feature template here](xref:Uno.Doc-Templates.Feature.Uno-Only) to the [features directory](../../features/) and fill in the sections. ## Updating the documentation from linked repositories diff --git a/doc/articles/contributing/Documentation/docfx.md b/doc/articles/contributing/Documentation/docfx.md new file mode 100644 index 000000000000..c4926ea5cd76 --- /dev/null +++ b/doc/articles/contributing/Documentation/docfx.md @@ -0,0 +1,168 @@ +--- +uid: Uno.Contributing.docfx +--- + + + +# The Uno documentation website and docfx + +Uno Platform's docs website uses [docfx](https://dotnet.github.io/docfx/) to convert Markdown (.md) files in the [articles folder](../../../articles) into [HTML files](xref:Uno.Documentation.Intro). + +## docfx-flavored Markdown + +docfx supports extended Markdown syntaxes that are treated specially when converting to html. + +### Formatted blockquotes + +You can use [specially-styled blockquotes](https://dotnet.github.io/docfx/spec/docfx_flavored_markdown.html#note-warningtipimportant), to call special attention to particular information. + +The following note types are supported, including an example for each one: + +```markdown +> [!NOTE] +> Useful information that users should know, even when skimming content. +``` + +> [!NOTE] +> Useful information that users should know, even when skimming content. + +```markdown +> [!TIP] +> Helpful advice for doing things better or more easily. +``` + +> [!TIP] +> Helpful advice for doing things better or more easily. + +```markdown +> [!IMPORTANT] +> Key information users need to know to achieve their goal. +``` + +> [!IMPORTANT] +> Key information users need to know to achieve their goal. + +```markdown +> [!CAUTION] +> Advises about risks or negative outcomes of certain actions. +``` + +> [!CAUTION] +> Advises about risks or negative outcomes of certain actions. + +```markdown +> [!WARNING] +> Urgent info that needs immediate user attention to avoid problems. +``` + +> [!WARNING] +> Urgent info that needs immediate user attention to avoid problems. + +### Tabs + +DocFX can generate tabs. Make sure to follow the [syntax specification](https://dotnet.github.io/docfx/docs/markdown.html#tabs) precisely. + +#### Example + +Markdown: + +```md +# [WinUI](#tab/tabid-1) + +`WinUI.Namespace` + +# [Uno Platform](#tab/tabid-2) + +`Uno.Namespace` + +--- +``` + +Html output: + +# [WinUI](#tab/tabid-1) + +`WinUI.Namespace` + +# [Uno Platform](#tab/tabid-2) + +`Uno.Namespace` + +--- + +> [!NOTE] +> Use `---` in the Markdown sample is Important, to not include more Content in the tabbed area than actually wanted, but will not be rendered in the served documentation. +> [!TIP] +> It is possible to use `***` alternatively for the same task. + +- [How To: Anchoring Links](xref:Uno.Contributing.Documentation.Anchor-links) + +## Linking to the Table of Contents + +Normally when you add a new markdown file, you also add it to [articles/toc.yml](../../toc.yml). This allows it to show up in the left sidebar TOC on the docs website. +The script [`check_toc`](../check_toc.ps1) checks for dead links in the TOC, as well as Markdown files in the `articles` folder that are not part of the TOC. + +> [!NOTE] +> At the moment it's not part of the CI, but contributors can run it locally and fix any bad or missing links. + +To use it, follow this Steps: + +1. Open a Power-Shell Terminal at the Root Directory of your locally cloned Uno Repository. +2. Navigate to the `articles` Directory of your local Uno.UI Repository: + + ```ps + cd doc/articles + ``` + + > [!IMPORTANT] + > This execution Directory is important to get the correct links for the TOC! + +3. Run the script with `& .\check_toc.ps1`, which will create a file named `toc_additions.yml` in the same directory as it has been executed from. + +4. Open the file and add the missing links to [toc.yml](..\toc.yml) in the **appropriate** category. + + > [!NOTE] + > Visual Studio 2022 does not show the generated file by default. + > To open it, enable `show all Files` in the solution browser: + + ![check-toc-find-toc-additions-file](../assets/check-toc-find-toc-additions-file.gif) + +## Building docs website locally with docfx + +Sometimes, you may want to run docfx locally to ensure that your changes render correctly in HTML. To do this, first generate the *implemented views* documentation. + +### Run docfx locally + +To run docfx locally and check the resulting html: + +1. Open the `Uno.UI-Tools.slnf` solution filter in the `src` folder with Visual Studio. +2. Edit the properties of the `Uno.UwpSyncGenerator` project. Under the 'Debug' tab, set Application arguments to "doc". +3. Set `Uno.UwpSyncGenerator` as startup project and run it. It may fail to generate the full implemented views content; if so, it should still nonetheless generate stubs so that docfx can run successfully. +4. Open a Terminal at the Root Directory of your locally cloned Uno Repository. +5. Install docfx globally: `dotnet tool install -g docfx` +6. Run the following command: `docfx build doc/docfx.json` and attach any nested foldername you want by adding `-o your-nested-output-path`, default: `_site` +7. When docfx builds successfully, it will create the html output at `uno-clone-repo\doc\[your-nested-output-path\]_site`, which you can serve by one of the following options: + a. Execute the command `docfx serve doc/docfx.json` in your terminal. + b. Use a [local server](#use-a-local-server). + +### Use a local server + +You can use `dotnet-serve` as a simple command-line HTTP server for example. + +1. Install `dotnet-serve` using the following command: `dotnet tool install --global dotnet-serve`. For more info about its usage and options,[please refer to the documentation](https://github.com/natemcmaster/dotnet-serve). +2. Using the command prompt, navigate to `C:\src\Uno.UI\docs-local-dist\_site` (replacing `C:\src\Uno.UI` with your local path to the Uno.UI repository) and run the following command `dotnet serve -o -S`. This will start a simple server with HTTPS and open the browser directly. + +## Run the documentation generation performance test + +If needed, you can also run a script that will give you a performance summary for the documentation generation. + +To run the script on Windows: + +1. Make sure `crosstargeting_override.props` is not defining UnoTargetFrameworkOverride +2. Open a Developer Command Prompt for Visual Studio (2019 or 2022) +3. Go to the uno\build folder (not the uno\src\build folder) +4. Run the `run-doc-generation.cmd` script; make sure to follow the instructions + +## Import Uno Extensions and Tools docs + +[!INCLUDE [advises-to-import-external-docs](./external/uno.extensions/doc/README.md)] diff --git a/doc/articles/uno-development/Internal-DependencyProperty-Generator.md b/doc/articles/contributing/Internal-DependencyProperty-Generator.md similarity index 100% rename from doc/articles/uno-development/Internal-DependencyProperty-Generator.md rename to doc/articles/contributing/Internal-DependencyProperty-Generator.md diff --git a/doc/articles/uno-development/Internal-WeakEventHelper.md b/doc/articles/contributing/Internal-WeakEventHelper.md similarity index 100% rename from doc/articles/uno-development/Internal-WeakEventHelper.md rename to doc/articles/contributing/Internal-WeakEventHelper.md diff --git a/doc/articles/uno-development/Uno-UI-Layouting-Android.md b/doc/articles/contributing/Uno-UI-Layouting-Android.md similarity index 99% rename from doc/articles/uno-development/Uno-UI-Layouting-Android.md rename to doc/articles/contributing/Uno-UI-Layouting-Android.md index 16127630e052..3ff6da1d38f5 100644 --- a/doc/articles/uno-development/Uno-UI-Layouting-Android.md +++ b/doc/articles/contributing/Uno-UI-Layouting-Android.md @@ -1,5 +1,5 @@ --- -uid: Uno.Contributing.LayoutingAndroid +uid: Uno.Contributing.Layouting.Android --- # Layouting in Android diff --git a/doc/articles/uno-development/Uno-UI-Layouting-iOS.md b/doc/articles/contributing/Uno-UI-Layouting-iOS.md similarity index 99% rename from doc/articles/uno-development/Uno-UI-Layouting-iOS.md rename to doc/articles/contributing/Uno-UI-Layouting-iOS.md index 1c2d94c2b1b9..637d83c51961 100644 --- a/doc/articles/uno-development/Uno-UI-Layouting-iOS.md +++ b/doc/articles/contributing/Uno-UI-Layouting-iOS.md @@ -1,5 +1,5 @@ --- -uid: Uno.Contributing.LayoutingiOS +uid: Uno.Contributing.Layouting.iOS --- # Layouting in iOS diff --git a/doc/articles/uno-development/api-extensions.md b/doc/articles/contributing/api-extensions.md similarity index 100% rename from doc/articles/uno-development/api-extensions.md rename to doc/articles/contributing/api-extensions.md diff --git a/doc/articles/uno-development/assets/SamplesApp.png b/doc/articles/contributing/assets/SamplesApp.png similarity index 100% rename from doc/articles/uno-development/assets/SamplesApp.png rename to doc/articles/contributing/assets/SamplesApp.png diff --git a/doc/articles/contributing/assets/check-toc-find-toc-additions-file.gif b/doc/articles/contributing/assets/check-toc-find-toc-additions-file.gif new file mode 100644 index 000000000000..7d1cb30a11a9 Binary files /dev/null and b/doc/articles/contributing/assets/check-toc-find-toc-additions-file.gif differ diff --git a/doc/articles/uno-development/contributing-intro.md b/doc/articles/contributing/contributing-intro.md similarity index 55% rename from doc/articles/uno-development/contributing-intro.md rename to doc/articles/contributing/contributing-intro.md index 9b12dbdfa52b..770260be1844 100644 --- a/doc/articles/uno-development/contributing-intro.md +++ b/doc/articles/contributing/contributing-intro.md @@ -1,24 +1,24 @@ --- uid: Uno.Contributing.Intro --- - + # Contributing to Uno Everyone is welcome to contribute to the Uno Platform. Here you'll find useful information for new and returning contributors. For starters, please read our [Code of Conduct](https://github.com/unoplatform/uno/blob/master/CODE_OF_CONDUCT.md), which sets out our commitment to an open, welcoming, harassment-free community. -If you're wondering where to start, [read about ways to contribute to Uno](ways-to-contribute.md). Or, you can peruse the list of [first-timer-friendly open issues](https://github.com/unoplatform/Uno/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). +If you're wondering where to start, [read about ways to contribute to Uno](xref:Uno.Contributing.WaysToContribute). Or, you can peruse the list of [first-timer-friendly open issues](https://github.com/unoplatform/Uno/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). ## Understanding the Uno codebase -For a refresher on what Uno is and what it does and does not do, read [What is the Uno Platform?](../intro.md) +For a refresher on what Uno is and what it does and does not do, read [What is the Uno Platform?](xref:Uno.Documentation.Intro) -Get an [in-depth introduction to how Uno works](uno-internals-overview.md), or jump straight to platform-specific details on how Uno works on [Android](uno-internals-android.md), [iOS](uno-internals-ios.md), [WebAssembly](uno-internals-wasm.md), or [macOS](uno-internals-macos.md). +Get an [in-depth introduction to how Uno works](xref:Uno.Contributing.Overview), or jump straight to platform-specific details on how Uno works on [Android](xref:Uno.Contributing.Android), [iOS](xref:Uno.Contributing.iOS), [WebAssembly](xref:Uno.Contributing.Wasm), or [macOS](xref:Uno.Contributing.macOS). ## Building and debugging Uno -For the prerequisites you'll need, as well as useful tips like using [solution filters](https://learn.microsoft.com/visualstudio/ide/filtered-solutions) and cross-targeting overrides to quickly load and build Uno for a single platform, start with the guide to [Building Uno.UI](building-uno-ui.md). The guide to [Debugging Uno.UI](debugging-uno-ui.md) will show you how to debug Uno.UI code either in the included UI samples or in an application outside the Uno.UI solution. +For the prerequisites you'll need, as well as useful tips like using [solution filters](https://learn.microsoft.com/visualstudio/ide/filtered-solutions) and cross-targeting overrides to quickly load and build Uno for a single platform, start with the guide to [Building Uno.UI](xref:Uno.Contributing.BuildingUno). The guide to [Debugging Uno.UI](xref:Uno.Contributing.DebuggingUno) will show you how to debug Uno.UI code either in the included UI samples or in an application outside the Uno.UI solution. You can contribute to Uno directly from your browser using GitPod, [find out how](xref:Uno.Features.Gitpod). @@ -26,11 +26,11 @@ Whether you're fixing a bug or working on a new feature, [inspecting the visual ## Writing code in Uno -See [Uno's code conventions and common patterns here](../contributing/guidelines/code-style.md). +See [Uno's code conventions and common patterns here](xref:Uno.Contributing.CodeStyle). ## Implementing a new feature -See how to implement a new [feature here](xref:Uno.Contributing.ImplementWinUIWinRTAPI). +See how to implement a new [feature here](xref:Uno.Contributing.ImplementWinUIWinRT-API). ## Experimenting with Samples App @@ -38,15 +38,15 @@ The [Samples App](xref:Uno.Contributing.SamplesApp) is the development app conta This app is available live at these locations, built from the default branch: -- WebAssembly: https://aka.platform.uno/wasm-samples-app +- [WebAssembly: `https://aka.platform.uno/wasm-samples-app`](https://aka.platform.uno/wasm-samples-app) ## Adding tests Uno's stability rests upon a comprehensive testing suite. A code contribution usually isn't complete without a test. -See the [Guidelines for creating tests](../contributing/guidelines/creating-tests.md) for an overview of the different types of tests used by Uno, and how to add one. +See the [Guidelines for creating tests](xref:Uno.Contributing.Tests.CreatingTests) for an overview of the different types of tests used by Uno, and how to add one. -[Working with the Samples Applications](working-with-the-samples-apps.md) provides instructions on adding a new UI sample to Uno, and authoring a UI Test to verify that the sample works. +[Working with the Samples Applications](xref:Uno.Contributing.SamplesApp) provides instructions on adding a new UI sample to Uno, and authoring a UI Test to verify that the sample works. ## Creating a Pull Request @@ -56,23 +56,23 @@ Uno uses [Git](https://git-scm.com/) for version control, and GitHub to host the [Tutorials | Atlassian](https://www.atlassian.com/git/tutorials) > [!IMPORTANT] -> Before you commit your code, take a minute to familiarize yourself with the [Conventional Commits format](git-conventional-commits.md) Uno uses. +> Before you commit your code, take a minute to familiarize yourself with the [Conventional Commits format](xref:Uno.Contributing.ConventionalCommits) Uno uses. -Read the [Guidelines for pull requests](../contributing/guidelines/pull-requests.md) in Uno. +Read the [Guidelines for pull requests](xref:Uno.Contributing.PullRequests) in Uno. -Uno's CI process [runs a tool to guard against inadvertent binary breaking changes](../contributing/guidelines/breaking-changes.md). +Uno's CI process [runs a tool to guard against inadvertent binary breaking changes](xref:Uno.Contributing.BreakingChanges). ## Info for the core team This section covers practices and utilities used by core maintainers. -Uno uses [Dependabot to automatically update external dependencies](../contributing/guidelines/updating-dependencies.md). +Uno uses [Dependabot to automatically update external dependencies](xref:Uno.Contributing.UpdatingDependencies). -Read the [guidelines for issue triage](../contributing/guidelines/issue-triage.md). +Read the [guidelines for issue triage](xref:Uno.Contributing.UpdatingDependencies). -Tools and procedures for creating stable releases are described [here](release-procedure.md). +- [Information about Tools and procedures for creating stable releases](xref:Uno.Contributing.ReleaseProcedure). -Build artifacts produced by the CI are documented [here](../contributing/build-artifacts.md). +- [Information about Build artifacts produced by the CI](xref:Uno.Contributing.Artifacts). ### More questions? diff --git a/doc/articles/uno-development/git-conventional-commits.md b/doc/articles/contributing/git/git-conventional-commits.md similarity index 100% rename from doc/articles/uno-development/git-conventional-commits.md rename to doc/articles/contributing/git/git-conventional-commits.md diff --git a/doc/articles/contributing/guidelines/pull-requests.md b/doc/articles/contributing/git/pull-requests.md similarity index 89% rename from doc/articles/contributing/guidelines/pull-requests.md rename to doc/articles/contributing/git/pull-requests.md index 7a77f104d638..c31fbb0504b6 100644 --- a/doc/articles/contributing/guidelines/pull-requests.md +++ b/doc/articles/contributing/git/pull-requests.md @@ -10,7 +10,7 @@ If you don't know what a pull request is, read the [About pull requests document If you are an outside contributor, please fork the Uno Platform repository you would like to contribute to your account. See the GitHub documentation for [forking a repo](https://help.github.com/articles/fork-a-repo/) if you have any questions about this. -Make sure the repository can build and all tests pass, as well as follow the current [coding guidelines](code-style.md). +Make sure the repository can build and all tests pass, as well as follow the current [coding guidelines](xref:Uno.Contributing.CodeStyle). Pull requests should all be made to the **master** branch. @@ -44,7 +44,7 @@ Make sure to rebase your work on the latest default branch of the Uno repository **Commit/Pull Request Format** -All commits **must** be in the [Conventional Commits format](../../uno-development/git-conventional-commits.md), otherwise the build will fail. +All commits **must** be in the [Conventional Commits format](xref:Uno.Contributing.ConventionalCommits), otherwise the build will fail. We use this convention to automatically generate release notes for new releases, and means that your commit messages will appear untouched in the release notes. @@ -64,7 +64,7 @@ Make sure that: When opening a PR, you'll see the description is filled by a template. Make sure to read through the template and fill the missing parts in it. -If you haven't [added tests](creating-tests.md) appropriate to your changes, the reviewers will probably ask you to add some. +If you haven't [added tests](xref:Uno.Contributing.Tests.CreatingTests) appropriate to your changes, the reviewers will probably ask you to add some. ## Reviewing diff --git a/doc/articles/contributing/git/sourcecontrol-overview.md b/doc/articles/contributing/git/sourcecontrol-overview.md new file mode 100644 index 000000000000..aa8159927d44 --- /dev/null +++ b/doc/articles/contributing/git/sourcecontrol-overview.md @@ -0,0 +1,20 @@ +--- +uid: Uno.Contributing.Source-Control +--- +# Source Control Overview + +## Common Source Control Applications + +Here you can find some common Source Control Applications that can also be used for Uno Applications and Contributing to Uno Platform: + +- Git Bash +- Git GUI +- GitHub (Web, Desktop, Mobile) +- Atlassian SourceTree (Desktop) + +## 📄 Related Pages + +- [Conventional Commits](xref:Uno.Contributing.ConventionalCommits) +- [Pull Requests](xref:Uno.Contributing.PullRequests) +- [Git Pod](xref:Uno.Features.Gitpod) +- [Codespaces](xref:Uno.Features.Codespaces) diff --git a/doc/articles/contributing/guidelines/breaking-changes.md b/doc/articles/contributing/guidelines/breaking-changes.md index 7a23ed34bc97..da8a1a43e03c 100644 --- a/doc/articles/contributing/guidelines/breaking-changes.md +++ b/doc/articles/contributing/guidelines/breaking-changes.md @@ -11,7 +11,7 @@ go unnoticed. As [part of our continuous integration process](https://github.com This process only diffs against previous versions of Uno, not against the WinUI assemblies, so it doesn't pick up all forms of mismatches. There are [some inconsistencies](https://github.com/unoplatform/uno/pull/1300) dating from before SyncGenerator was added. At some point it might be a good idea to extend SyncGenerator tool to try to report them all (or even automatically fix them) -Breaking changes must be marked as such when committed using the [Conventional Commits formatting](../../uno-development/git-conventional-commits.md). +Breaking changes must be marked as such when committed using the [Conventional Commits formatting](xref:Uno.Contributing.ConventionalCommits). ## When are binary breaking changes acceptable? @@ -21,7 +21,7 @@ Changes that break compatibility with the public API surface of WinUI are genera ### Restoring cross-platform compatibility - ok, but discuss with core team -In some cases, Uno's existing API is close to WinUI, but not identical. (Hypothetical example: a property with type `DependencyObject[]` on Uno, but type `IList` on WinUI.) This is mostly the case for older code that was written before the use of [generated `NotImplemented` stubs](../../uno-development/uno-internals-overview.md#generated-notimplemented-stubs) and the `PackageDiff` tool, which act in combination to prevent these kinds of errors when implementing new features. +In some cases, Uno's existing API is close to WinUI, but not identical. (Hypothetical example: a property with type `DependencyObject[]` on Uno, but type `IList` on WinUI.) This is mostly the case for older code that was written before the use of [generated `NotImplemented` stubs](xref:Uno.Contributing.Overview#generated-notimplemented-stubs) and the `PackageDiff` tool, which act in combination to prevent these kinds of errors when implementing new features. In these cases, we do want to align Uno with WinUI, even at the expense of a breaking change. However, we tend to be more careful with when we merge these changes, compared to other bugfixes. We prefer to 'batch' many such breaking changes into a single stable release cycle, rather than wear out consumers' patience with a steady trickle of breaking changes each release. @@ -33,13 +33,13 @@ Note that some cases may be sufficiently benign that the breaking change is acce The diff tool guards against all changes to Uno's public API surface, including functionality that has no equivalent in WinUI's API surface. -In the cases where these Uno-only APIs are exposed intentionally (example: the [`VisibleBoundsPadding` behavior](../../features/VisibleBoundsPadding.md)), we would usually reject breaking changes, unless there were a very compelling reason for them. +In the cases where these Uno-only APIs are exposed intentionally (example: the [`VisibleBoundsPadding` behavior](xref:Uno.Features.VisibleBoundsPadding)), we would usually reject breaking changes, unless there were a very compelling reason for them. In other cases, this might be functionality that's inadvertently exposed - in other words, functionality that was made public when it should really have been internal. Here the validity of the breaking change should be considered on a case-by-case basis, taking into account the risk of breaking existing Uno app code (and conversely, the possibility for the Uno-only APIs to collide with 'brownfield' WinUI code). Again, the principle of 'batching' breaking changes applies. ## Adding breaking changes to the allow list -Where a breaking change is acceptable according to the above criteria, and after discussion with the core team where appropriate, it can be marked as such using the [build/PackageDiffIgnore.xml](https://github.com/unoplatform/uno/blob/master/build/PackageDiffIgnore.xml) file. +Where a breaking change is acceptable according to the above criteria, and after discussion with the core team where appropriate, it can be marked as such using the [build/PackageDiffIgnore.xml](../../../../build/PackageDiffIgnore.xml) file. Please refer to the documentation of the [Uno.PackageDiff tool](https://github.com/unoplatform/uno.PackageDiff) for more information. diff --git a/doc/articles/uno-development/building-uno-ui.md b/doc/articles/contributing/guidelines/building-uno-ui.md similarity index 89% rename from doc/articles/uno-development/building-uno-ui.md rename to doc/articles/contributing/guidelines/building-uno-ui.md index e094e9427652..d170fc6ad63e 100644 --- a/doc/articles/uno-development/building-uno-ui.md +++ b/doc/articles/contributing/guidelines/building-uno-ui.md @@ -12,9 +12,9 @@ This article explains how to build Uno.UI locally, for instance, if you wish to - Select the **ASP.NET and Web Development** workload - Select the **.NET Multi-Platform App UI development** workload - Select the **.NET desktop development** workload - - To build the UWP flavor of Uno, you'll need **UWP Development**, install all recent UWP SDKs, starting from 10.0.19041 (or above or equal to `TargetPlatformVersion` line [in this file](https://github.com/unoplatform/uno/blob/master/src/Uno.CrossTargetting.targets)) -- Install (**Tools** / **Android** / **Android SDK manager**) all Android SDKs starting from 7.1 (or the Android versions `TargetFrameworks` [list used here](https://github.com/unoplatform/uno/blob/master/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.netcoremobile.csproj)) -- Run [Uno.Check](https://github.com/unoplatform/uno.check) on your dev machine to setup .NET Android/iOS workloads + - To build the UWP flavor of Uno, you'll need **UWP Development**, install all recent UWP SDKs, starting from 10.0.19041 (or above or equal to `TargetPlatformVersion` line [in this file](../../../../src/Uno.CrossTargetting.targets)) +- Install (**Tools** / **Android** / **Android SDK manager**) all Android SDKs starting from 7.1 (or the Android versions `TargetFrameworks` [list used here](../../../../src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.netcoremobile.csproj)) +- Run [Uno.Check](xref:UnoCheck.UsingUnoCheck) on your dev machine to setup .NET Android/iOS workloads - Install the latest [.NET SDK](https://aka.ms/dotnet/download) from Microsoft. ## Recommended Windows hardware @@ -54,7 +54,7 @@ The step-by-step process is: - For Skia, you can right-click on the corresponding `Uno.UI.Runtime.Skia.[Win32|X11|macOS|iOS|Android|Wpf]` project 1. Optionally adjust additional parameters in `crosstargeting_override.props`, such as `UnoDisableNetAnalyzers`, which can improve the build time during debugging sessions. -Once you've built successfully, for the next steps, [consult the guide here](debugging-uno-ui.md) for debugging Uno.UI. +Once you've built successfully, for the next steps, [consult the guide here](xref:Uno.Contributing.DebuggingUno) for debugging Uno.UI. > [!IMPORTANT] > You will need to repeat the above steps 2. and subsequent when changing the active `UnoTargetFrameworkOverride` value. @@ -78,7 +78,7 @@ Note that long paths may be required when building Uno, and invalid paths errors It's recommended to build using the single-target approach, but it's also possible to build for all targets at once, if you wish. 1. If you've previously followed the single-target steps, comment out the `` line in your `crosstargeting_override.props` file. -2. Open the [Uno.UI.sln](https://github.com/unoplatform/uno/blob/master/src/Uno.UI.sln) +2. Open the [Uno.UI.sln](../../../../src/Uno.UI.sln) 3. Select the `Uno.UI` project 4. Build @@ -106,14 +106,14 @@ In order to update those reference assemblies, set ` ### Using the Package Diff tool -Refer to the [guidelines for breaking changes](../contributing/guidelines/breaking-changes.md) document. +Refer to the [guidelines for breaking changes](xref:Uno.Contributing.BreakingChanges) document. ### Updating the Nuget packages used by the Uno.UI solution -The versions used are centralized in the [Directory.Build.targets](https://github.com/unoplatform/uno/blob/master/src/Directory.Build.targets) file, and all the +The versions used are centralized in the [Directory.Build.targets](../../../../src/Directory.Build.targets) file, and all the locations where `` are used. -When updating the versions of NuGet packages, make sure to update all the .nuspec files in the [`build/nuget` folder](https://github.com/unoplatform/uno/tree/master/build/nuget). +When updating the versions of NuGet packages, make sure to update all the .nuspec files in the [`build/nuget` folder](../../../../build/nuget). ### Running the SyncGenerator tool @@ -126,8 +126,8 @@ The tool needs to be run on Windows because of its dependency on the Windows SDK To run the synchronization tool: - Open a `Developer Command Prompt for Visual Studio` (2019 or 2022) -- Go to the `uno\build` folder (not the `uno\src\build` folder) -- Run the `run-api-sync-tool.cmd` script; make sure to follow the instructions +- Run [`uno\build\run-api-sync-tool.cmd`](../../../../build/run-api-sync-tool.cmd) (! not the `uno\src\build` folder !) you can do so by following the link on this text. +- make sure to follow the instructions Note that the tool needs to be run manually and is not run as part of the CI. diff --git a/doc/articles/contributing/guidelines/code-style.md b/doc/articles/contributing/guidelines/code-style.md index 8fe61c623662..0c6ea57df118 100644 --- a/doc/articles/contributing/guidelines/code-style.md +++ b/doc/articles/contributing/guidelines/code-style.md @@ -18,7 +18,7 @@ This section describes some recurring patterns and practices you'll see in Uno c ### Partial classes -[Partial class definitions](https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) are used extensively in Uno. The two main use cases for partial classes are [platform-specific code](../../platform-specific-csharp.md) and [generated code](../../uno-development/uno-internals-overview.md#generated-notimplemented-stubs). +[Partial class definitions](https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) are used extensively in Uno. The two main use cases for partial classes are [platform-specific code](../../platform-specific-csharp.md) and [generated code](xref:Uno.Contributing.Overviewmd#generated-notimplemented-stubs). However, in some cases where it makes sense, partial class files are also used for logical separation of code. If you're implementing a type that owns a lot of dependency properties, consider putting these in a separate partial, to avoid cluttering up the file where the actual business logic is with DP boilerplate. Another use case for a partial is a nested class with a large definition. @@ -26,13 +26,13 @@ However, in some cases where it makes sense, partial class files are also used f Uno uses lightweight `IDisposables` widely for robust lifetime management. The most commonly used types for this purpose are `SerialDisposable`, `CompositeDisposable`, `CancellationDisposable`, and `DisposableAction`. -If you've used the `Reactive Extensions` framework, these names [might be familiar](https://learn.microsoft.com/previous-versions/dotnet/reactive-extensions/hh229090(v=vs.103)), and in fact these disposables behave identically to their Rx equivalents. However, they've been transplanted into [Uno](https://github.com/unoplatform/uno/tree/master/src/Uno.Foundation/Uno.Core.Extensions/Uno.Core.Extensions.Disposables/Disposables), to avoid having to take a dependency on `System.Reactive`. +If you've used the `Reactive Extensions` framework, these names [might be familiar](https://learn.microsoft.com/previous-versions/dotnet/reactive-extensions/hh229090(v=vs.103)), and in fact these disposables behave identically to their Rx equivalents. However, they've been transplanted into [Uno](../../../../src/Uno.Foundation/Uno.Core.Extensions/Uno.Core.Extensions.Disposables/Disposables), to avoid having to take a dependency on `System.Reactive`. ### Extension methods [Extension methods](https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) are used throughout the Uno Platform codebase to add reusable functionality to existing types, particularly types coming from the Xamarin bindings. Extension methods should be defined in a dedicated class, with the naming convention `[TypeName]Extensions.cs`, where `TypeName` is the name of the type either being returned or passed as the `this` parameter. -A number of extensions to the standard .NET types already exists in [Uno.Foundation](https://github.com/unoplatform/uno/tree/master/src/Uno.Foundation/Uno.Core.Extensions). So, you should check those first to see if they do what you need. +A number of extensions to the standard .NET types already exists in [Uno.Foundation](../../../../src/Uno.Foundation/Uno.Core.Extensions). So, you should check those first to see if they do what you need. When adding a new extension method class, it should typically be marked `internal`, to avoid naming clashes with existing consumer code. diff --git a/doc/articles/uno-development/debugging-templates.md b/doc/articles/contributing/guidelines/debugging-templates.md similarity index 96% rename from doc/articles/uno-development/debugging-templates.md rename to doc/articles/contributing/guidelines/debugging-templates.md index 8d1a36d5591c..68cfd8f55570 100644 --- a/doc/articles/uno-development/debugging-templates.md +++ b/doc/articles/contributing/guidelines/debugging-templates.md @@ -17,7 +17,7 @@ Some of the templates are reusing the same sources. For example the full solutio To make modifications to those templates and test the result: -- In Visual Studio, open the solution using the [Uno.UI-SolutionTemplates.slnf](building-uno-ui.md) filter +- In Visual Studio, open the solution using the [Uno.UI-SolutionTemplates.slnf](xref:Uno.Contributing.BuildingUno) filter - Right click on the `Uno.ProjectTemplates.Dotnet` project, select `Pack` - This will create a `Uno.ProjectTemplates.Dotnet.255.255.255.255.nupkg` file - Install this file using `dotnet new -i C:\[your_path]\bin\Debug\Uno.ProjectTemplates.Dotnet.255.255.255.255.nupkg` diff --git a/doc/articles/uno-development/debugging-uno-ui.md b/doc/articles/contributing/guidelines/debugging-uno-ui.md similarity index 94% rename from doc/articles/uno-development/debugging-uno-ui.md rename to doc/articles/contributing/guidelines/debugging-uno-ui.md index 2d1fc75f2779..da7399d87ac9 100644 --- a/doc/articles/uno-development/debugging-uno-ui.md +++ b/doc/articles/contributing/guidelines/debugging-uno-ui.md @@ -7,7 +7,7 @@ uid: Uno.Contributing.DebuggingUno > [!NOTE] > [Find instructions for building the Uno.UI solution here.](xref:Uno.Contributing.BuildingUno) -## Debugging Uno.UI samples +## Debugging Uno.UI samples To debug the **SamplesApp** in the Uno.UI solution, which includes an extensive set of samples and test cases for the controls supported by Uno.UI, as well as non-UI features: @@ -18,7 +18,7 @@ To debug the **SamplesApp** in the Uno.UI solution, which includes an extensive 3. Set `SamplesApp.[TargetPlatform]` as the selected Startup Project. 4. Launch the samples app from Visual Studio. -See [this article](working-with-the-samples-apps.md) for more information on working with the SamplesApp and authoring new samples. +See [this article](xref:Uno.Contributing.SamplesApp) for more information on working with the SamplesApp and authoring new samples. ## Debugging Uno in another application @@ -48,7 +48,7 @@ Then, here are the steps to use a local build of Uno.UI in another application: To debug Uno.UI code in the application, follow these steps (using `FrameworkElement.MeasureOverride()` as an example): -1. Open [`FrameworkElement.cs`](https://github.com/unoplatform/uno/blob/master/src/Uno.UI/UI/Xaml/FrameworkElement.cs) in the Uno.UI solution. +1. Open [`FrameworkElement.cs`](../../../../src/Uno.UI/UI/Xaml/FrameworkElement.cs) in the Uno.UI solution. 2. Right-click on the `FrameworkElement.cs` tab header in Visual Studio and choose 'Copy Full Path'. 3. Switch to the Visual Studio instance where your application is open. 4. In your application solution, choose File->Open->File... or simply `Ctrl+O`, paste the path to `FrameworkElement.cs` into the file open dialog, and open `FrameworkElement.cs` in the application solution. diff --git a/doc/articles/contributing/guidelines/implementing-a-new-winui-winrt-feature.md b/doc/articles/contributing/guidelines/implementing-new-winui-winrt-api.md similarity index 95% rename from doc/articles/contributing/guidelines/implementing-a-new-winui-winrt-feature.md rename to doc/articles/contributing/guidelines/implementing-new-winui-winrt-api.md index 324e6b06c4c9..b223237da189 100644 --- a/doc/articles/contributing/guidelines/implementing-a-new-winui-winrt-feature.md +++ b/doc/articles/contributing/guidelines/implementing-new-winui-winrt-api.md @@ -1,5 +1,5 @@ --- -uid: Uno.Contributing.ImplementWinUIWinRTAPI +uid: Uno.Contributing.ImplementWinUIWinRT-API --- # Guidelines for implementing a new WinUI/WinRT API @@ -36,6 +36,6 @@ If your API implementation is for a specific platform: when implemented for Android only. -When implementing a feature, try to place as much code as possible in a common source file (a non-suffixed file), so that it is reused across platforms. Make sure to follow [partial classes coding guidelines](code-style.md). +When implementing a feature, try to place as much code as possible in a common source file (a non-suffixed file), so that it is reused across platforms. Make sure to follow [partial classes coding guidelines](xref:Uno.Contributing.CodeStyle). Note that the generated files may be overridden at any point, and placing custom code (aside from changing the `NotImplemented` values) will be overwritten. diff --git a/doc/articles/uno-development/release-procedure.md b/doc/articles/contributing/guidelines/release-procedure.md similarity index 100% rename from doc/articles/uno-development/release-procedure.md rename to doc/articles/contributing/guidelines/release-procedure.md diff --git a/doc/articles/contributing/guidelines/updating-dependencies.md b/doc/articles/contributing/guidelines/updating-dependencies.md index 1290851add38..94ea7c9c97f7 100644 --- a/doc/articles/contributing/guidelines/updating-dependencies.md +++ b/doc/articles/contributing/guidelines/updating-dependencies.md @@ -22,7 +22,7 @@ The following dependencies don't change the public API surface and are typically - Moq The following dependencies require manual adjustments before merging: - + - [docfx.console](https://github.com/unoplatform/Uno/pull/1082/commits/c222caf8c23b35e19f6b33cd624cbfa714250bfe) - `Microsoft.CodeAnalysis.*`. Those dependencies need to be aligned with the source generation task package, for which the dependency cannot be be explicitly provided. - `Xamarin.GooglePlayServices.*`. Those dependencies are added per TargetFramework (Android SDK version), not updated. diff --git a/doc/articles/uno-development/listviewbase-internals.md b/doc/articles/contributing/listviewbase-internals.md similarity index 98% rename from doc/articles/uno-development/listviewbase-internals.md rename to doc/articles/contributing/listviewbase-internals.md index cb741d8f13e0..0a53ae431c30 100644 --- a/doc/articles/uno-development/listviewbase-internals.md +++ b/doc/articles/contributing/listviewbase-internals.md @@ -6,7 +6,7 @@ uid: Uno.Contributing.ListViewBase This document describes the internal operations of Uno's `ListViewBase` implementation(s) in detail, aimed at contributors. -Before reading it, you should first read the documentation of [ListViewBase aimed at Uno app developers](../controls/ListViewBase.md), which covers the high-level differences between Uno's implementation and UWP's implementation. +Before reading it, you should first read the documentation of [ListViewBase aimed at Uno app developers](xref:Uno.Controls.ListViewBase), which covers the high-level differences between Uno's implementation and UWP's implementation. ## Introduction @@ -48,7 +48,7 @@ Architecturally, the Android and iOS implementations share a similar high-level (As an aside, this division of labor has no equivalent in `ListView`, but a somewhat similar approach is taken by WinUI's newer [`ItemsRepeater`](https://learn.microsoft.com/windows/winui/api/microsoft.ui.xaml.controls.itemsrepeater) control, also available in Uno.) -[This diagram](../controls/ListViewBase.md#difference-in-the-visual-tree) shows how the `NativeListViewBase` view is incorporated into the visual tree, and the resulting difference from WinUI. The key differences are: +[This diagram](xref:Uno.Controls.ListViewBase#difference-in-the-visual-tree) shows how the `NativeListViewBase` view is incorporated into the visual tree, and the resulting difference from UWP. The key differences are: - the scrolling container is the `NativeListViewBase` itself, not the `ScrollViewer`. Thus, the `ItemsPresenter` is **outside** the scrollable region. Additionally, there's no ScrollContentPresenter; instead, there's a ListViewBaseScrollContentPresenter. (It was implemented this way back when ScrollContentPresenter inherited directly from the native scroll container.) - the `ItemsStackPanel` (or `ItemsWrapGrid`) is not actually present in the visual tree. These items' panels are created, and their configured values (eg, `Orientation`) are used to set the behavior of the list, but they are not actually loaded into the visual hierarchy or measured and arranged. They just act as a facade for the native layouter. diff --git a/doc/articles/uno-development/creating-mocked-tests.md b/doc/articles/contributing/tests/creating-mocked-tests.md similarity index 92% rename from doc/articles/uno-development/creating-mocked-tests.md rename to doc/articles/contributing/tests/creating-mocked-tests.md index 504e4cf960a0..5c88b636bad7 100644 --- a/doc/articles/uno-development/creating-mocked-tests.md +++ b/doc/articles/contributing/tests/creating-mocked-tests.md @@ -1,5 +1,5 @@ --- -uid: Uno.Contributing.CreateMockedTests +uid: Uno.Contributing.Tests.CreateMockedTests --- # Creating unit tests in Uno.UI.Tests @@ -10,7 +10,7 @@ Adding tests here is closest to the 'traditional' unit test experience: you can ## Running tests in Uno.UI.Tests -1. Open and build the Uno.UI solution [for the unit tests target](building-uno-ui.md). +1. Open and build the Uno.UI solution [for the unit tests target](xref:Uno.Contributing.BuildingUno). 2. Open Test Explorer from the TEST menu. 3. Tests are listed under `Uno.UI.Tests`. You can run all tests or a subsection, with or without debugging. Tests run in a vanilla .NET Framework environment. (Note: You usually don't need to run `Uno.Xaml.Tests` tests locally, unless you're making changes to low-level XAML parsing in `Uno.Xaml`. ) @@ -19,4 +19,4 @@ Adding tests here is closest to the 'traditional' unit test experience: you can 1. Locate the test class corresponding to the control or class you want to create a test for. If you need to add a new test class, create the file as `Namespace_In_Snake_Case/ControlNameTests/Given_ControlName.cs`. be marked with the `[TestClass]` attribute. 2. Add tests for your cases, naming it as `When_Your_Scenario` and marking it with the `[TestMethod]` attribute. (For more information about the 'Given-When-Then' naming style, read ) -The mocking layer of Uno.UI for unit tests has been added as needed, and depending on your case, you may encounter areas of functionality that aren't supported. Your options if that happens are either to add the missing mocking, or to [add the test in Uno.UI.RuntimeTests](creating-runtime-tests.md) instead. +The mocking layer of Uno.UI for unit tests has been added as needed, and depending on your case, you may encounter areas of functionality that aren't supported. Your options if that happens are either to add the missing mocking, or to [add the test in Uno.UI.RuntimeTests](xref:Uno.Contributing.Tests.RuntimeTests) instead. diff --git a/doc/articles/contributing/tests/creating-ps-pester-tests.md b/doc/articles/contributing/tests/creating-ps-pester-tests.md new file mode 100644 index 000000000000..7f3e70c5c11a --- /dev/null +++ b/doc/articles/contributing/tests/creating-ps-pester-tests.md @@ -0,0 +1,23 @@ +--- +uid: Uno.Contributing.Tests.PowerShell-Pester-Tests +--- + +# Testing PowerShell Scripts with Pester + +## Introduction + +Some Parts of Uno.UI like the [check-toc.ps1](xref:Uno.Contributing.docfx) or the [import_external_docs_test.ps1](../../../import_external_docs_test.ps1) used for Contribution and general Uno Documentation deployment, are written in PowerShell. To make sure, they are working properly, the recommended and most common used Testing Framework is [Pester](https://pester.dev/docs/quick-start). + + + + +## Showing Pester Test Result in CI + +Pester integrates seamlessly with CI pipelines, allowing you to automate the validation of your PowerShell scripts. By including Pester tests in your CI configuration, you can ensure that changes to the script any dependant Modules or Functions do not introduce regressions. Most CI systems, such as GitHub Actions or Azure Pipelines, support running Pester tests and can display detailed test results in their interfaces. + +For more information, refer to the [Pester Test Results Documentation](https://pester.dev/docs/usage/test-results). + +## Related Pages + +- [The Uno docs website and DocFX](xref:Uno.Contributing.docfx) +- [`Installing Pester 5+`](https://pester.dev/docs/introduction/installation) diff --git a/doc/articles/uno-development/creating-runtime-tests.md b/doc/articles/contributing/tests/creating-runtime-tests.md similarity index 98% rename from doc/articles/uno-development/creating-runtime-tests.md rename to doc/articles/contributing/tests/creating-runtime-tests.md index 46ccc56a34c0..ba60c630c61e 100644 --- a/doc/articles/uno-development/creating-runtime-tests.md +++ b/doc/articles/contributing/tests/creating-runtime-tests.md @@ -1,5 +1,5 @@ --- -uid: Uno.Contributing.CreateRuntimeTests +uid: Uno.Contributing.Tests.CreateRuntimeTests --- # Creating unit tests in Uno.UI.RuntimeTests @@ -8,13 +8,13 @@ Platform-runtime unit tests are relatively cheap (in terms of developer producti Tests in Uno.UI.RuntimeTests are easy to write. There are a few special attributes and environmental helpers to know about, which this guide will cover. -For other types of automated tests used internally by Uno.UI, [see here](../contributing/guidelines/creating-tests.md). +For other types of automated tests used internally by Uno.UI, [see here](xref:Uno.Contributing.Tests.CreatingTests). ## Running tests locally Since the Uno.UI.RuntimeTests tests run in the platform environment using the real Uno.UI binaries, they must be run from within SamplesApp. -1. Build and launch the SamplesApp, following [the instructions here](working-with-the-samples-apps.md). Note: if you're testing a mobile platform, it's recommended to run on a tablet in landscape mode. On a phone-sized layout, a few tests will fail because they don't have enough space to measure properly. +1. Build and launch the SamplesApp, following [the instructions here](xref:Uno.Contributing.SamplesApp). Note: if you're testing a mobile platform, it's recommended to run on a tablet in landscape mode. On a phone-sized layout, a few tests will fail because they don't have enough space to measure properly. 2. From the sample menu, navigate to 'Unit Tests' > 'Unit Tests Runner' or click on the top-left-most button. 3. (Optional) Add a filter string in the text input control at the top of the page (for example the name or part of the name of your test method); only tests matching the filter will be run. Otherwise, all tests will run. > On mobile devices with limit screen width, you can drag the grid-slitter (the horizontal and vertical blue bars) to make more space for the filter textbox or test area. diff --git a/doc/articles/contributing/guidelines/creating-tests.md b/doc/articles/contributing/tests/creating-tests.md similarity index 82% rename from doc/articles/contributing/guidelines/creating-tests.md rename to doc/articles/contributing/tests/creating-tests.md index 11b1c3ca5584..b63b1340ba8c 100644 --- a/doc/articles/contributing/guidelines/creating-tests.md +++ b/doc/articles/contributing/tests/creating-tests.md @@ -1,5 +1,5 @@ --- -uid: Uno.Contributing.CreatingTests +uid: Uno.Contributing.Tests.CreatingTests --- # Guidelines for creating tests @@ -12,9 +12,9 @@ This guide offers an overview of the various types of tests used within Uno, and The 'TLDR' rule of thumb for adding tests is: -- if you're testing platform-independent functionality, like the dependency property system, [use Uno.UI.Tests](../../uno-development/creating-mocked-tests.md); -- if you're testing platform-dependent functionality that can be verified programmatically in-process, like checking that a control is measured and arranged properly, [use Uno.UI.RuntimeTests](../../uno-development/creating-runtime-tests.md); -- if your test needs to simulate user interaction or check that the final screen output is correct, [use SamplesApp.UITests](../../uno-development/creating-ui-tests.md). +- if you're testing platform-independent functionality, like the dependency property system, [use Uno.UI.Tests](xref:Uno.Contributing.Tests.CreateMockedTests); +- if you're testing platform-dependent functionality that can be verified programmatically in-process, like checking that a control is measured and arranged properly, [use Uno.UI.RuntimeTests](xref:Uno.Contributing.Tests.CreateRuntimeTests); +- if your test needs to simulate user interaction or check that the final screen output is correct, [use SamplesApp.UITests](xref:Uno.Contributing.Tests.CreateUITests). ## Types of tests @@ -47,7 +47,7 @@ They can verify assertions about the state of the app: - onscreen bounds of a view element - comparing screenshots at different stages of the app, and asserting equality or inequality -A complete set of instructions for authoring UI tests is available in [Using the SamplesApp documentation](../../uno-development/working-with-the-samples-apps.md). +A complete set of instructions for authoring UI tests is available in [Using the SamplesApp documentation](xref:Uno.Contributing.SamplesApp). Although only a subset of the samples in the SamplesApp are covered by automated UI tests, _all_ samples are screen-shotted on every build, and a reporting tool (runs on Skia, Wasm, Android, and iOS) reports any screenshots that differ from the previous build. Currently, the build isn't gated on these checks, but this may be adjusted in the future. @@ -70,23 +70,23 @@ The platform runtime tests also have access to internal Uno.UI members if need b ### XAML code generation tests (`XamlGenerationTests`) -These specifically target [the parser](https://github.com/unoplatform/uno/tree/master/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator) which generates C# code from XAML files. They are 'tests' in a simple sense that if the parser throws an error, or if it generates invalid C# code, they will fail the CI build. +These specifically target [the parser](../../../../src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator) which generates C# code from XAML files. They are 'tests' in a simple sense that if the parser throws an error, or if it generates invalid C# code, they will fail the CI build. If you want to actually test that generated XAML produces correct behavior, which will be the case most of the time, you should use one of the other test types. ### Source generator tests -These can be used to assert that a given input to a given source generator produces specific expected diagnostics. The infrastructure for the tests easily allows to test the generator output exactly, but you should avoid that kind of assertion if you can. These tests exist in [`Uno.UI.SourceGenerators.Tests`](https://github.com/unoplatform/uno/tree/master/src/SourceGenerators/Uno.UI.SourceGenerators.Tests). +These can be used to assert that a given input to a given source generator produces specific expected diagnostics. The infrastructure for the tests easily allows to test the generator output exactly, but you should avoid that kind of assertion if you can. These tests exist in [`Uno.UI.SourceGenerators.Tests`](../../../../src/SourceGenerators/Uno.UI.SourceGenerators.Tests). ### UI snapshot tests -These are 'semi-automated' tests that takes a screenshot of each sample in the [SamplesApp](https://github.com/unoplatform/uno/tree/master/src/SamplesApp/UITests.Shared). +These are 'semi-automated' tests that takes a screenshot of each sample in the [SamplesApp](../../../../src/SamplesApp/UITests.Shared). -On Android, iOS, and Wasm, a minimal UI test is [generated](https://github.com/unoplatform/uno/blob/master/src/SamplesApp/SamplesApp.UITests.Generator/SnapShotTestGenerator.cs) which simply runs the sample (which automatically takes a screenshot of the loaded sample). +On Android, iOS, and Wasm, a minimal UI test is [generated](../../../../src/SamplesApp/SamplesApp.UITests.Generator/SnapShotTestGenerator.cs) which simply runs the sample (which automatically takes a screenshot of the loaded sample). On Skia and macOS, we [loop over the samples and load them](https://github.com/unoplatform/uno/blob/b1a6eddcad3bcca6d9756b0a57ff6cf458321048/src/SamplesApp/SamplesApp.UnitTests.Shared/Controls/UITests/Presentation/SampleChooserViewModel.cs#L364-L427), then [save a screenshot](https://github.com/unoplatform/uno/blob/b1a6eddcad3bcca6d9756b0a57ff6cf458321048/src/SamplesApp/SamplesApp.UnitTests.Shared/Controls/UITests/Presentation/SampleChooserViewModel.cs#L1221-L1244) of each sample using `RenderTargetBitmap` and `BitmapEncoder`. This is generally faster than relying on UI tests. -The screenshots from each sample, as well as all screenshots generated by the main UI tests (using the `TakeScreenshot()` method), are [compared](https://github.com/unoplatform/uno/tree/master/src/Uno.UI.TestComparer) with the same sample from the most recent merged CI build. +The screenshots from each sample, as well as all screenshots generated by the main UI tests (using the `TakeScreenshot()` method), are [compared](../../../../src/Uno.UI.TestComparer) with the same sample from the most recent merged CI build. **Failed** comparisons will not fail the build (for one thing, it's possible the differences are expected or even desired). Instead, a report is generated, with a summary added to the PR as a comment listing all samples that changed. The onus is on the PR author to manually review these changes to ensure that no regressions have been introduced. @@ -132,6 +132,7 @@ As a rule of thumb, if the behavior you're testing can be verified by a unit tes If you're fixing a bug that can be verified by a static sample, create a SamplesApp sample that can be monitored by the snapshot comparer. If you're fixing a bug that involves user interaction or multiple asynchronous UI operations, or you want a hard verification of the onscreen visual state, then create a UI test. + ## What can't be tested? @@ -139,4 +140,4 @@ Some UI behaviors are difficult to test in an automated fashion, such as transie Some non-UI APIs may not be testable in the emulated environment on the CI build. -If you're working on something that falls under one of these descriptions, you should add a [sample](https://github.com/unoplatform/uno/tree/master/src/SamplesApp/UITests.Shared) that covers the bug or feature you're working on, and verify that the existing samples in the same feature category aren't negatively affected by your changes. Also, you should mark such sample as a manual test. For more information about manual tests, see [Adding a manual test sample section in Using the SamplesApp documentation](../../uno-development/working-with-the-samples-apps.md#adding-a-manual-test-sample). +If you're working on something that falls under one of these descriptions, you should add a [sample](../../../../src/SamplesApp/UITests.Shared) that covers the bug or feature you're working on, and verify that the existing samples in the same feature category aren't negatively affected by your changes. Also, you should mark such sample as a manual test. For more information about manual tests, see [Adding a manual test sample section in Using the SamplesApp documentation](xref:Uno.Contributing.SamplesApp#adding-a-manual-test-sample). diff --git a/doc/articles/uno-development/creating-ui-tests.md b/doc/articles/contributing/tests/creating-ui-tests.md similarity index 87% rename from doc/articles/uno-development/creating-ui-tests.md rename to doc/articles/contributing/tests/creating-ui-tests.md index 00e51731c437..982746c4bf32 100644 --- a/doc/articles/uno-development/creating-ui-tests.md +++ b/doc/articles/contributing/tests/creating-ui-tests.md @@ -16,19 +16,19 @@ UI tests contribute significantly to the CI build time, and for many purposes a - you can put the app in the required state programmatically, and - you can verify the correct behavior programmatically (eg by checking DesiredSize, ActualWidth/ActualHeight etc). - For more on general testing strategy in Uno.UI, see [Guidelines for creating tests](../contributing/guidelines/creating-tests.md). + For more on general testing strategy in Uno.UI, see [Guidelines for creating tests](xref:Uno.Contributing.Tests.CreatingTests). > [!NOTE] -> [Platform runtime unit tests](../contributing/guidelines/creating-tests.md) are generally preferred to UI tests as their execution performance is generally faster than UI Tests. +> [Platform runtime unit tests](xref:Uno.Contributing.Tests.CreatingTests) are generally preferred to UI tests as their execution performance is generally faster than UI Tests. ## Running UI tests locally 1. Ensure [your environment is configured](xref:Uno.GetStarted.vs2022) for the platform you want to run on. 1. Ensure `UnoTargetFrameworkOverride` is set to `net7.0-android` for testing on Android, `net7.0-ios` for testing on iOS, and `net7.0` for testing on Wasm. -1. Open Uno.UI with the [correct target override and solution filter](building-uno-ui.md) for the platform you want to run on. -1. [Build and run the SamplesApp](working-with-the-samples-apps.md) at least once. +1. Open Uno.UI with the [correct target override and solution filter](xref:Uno.Contributing.BuildingUno) for the platform you want to run on. +1. [Build and run the SamplesApp](xref:Uno.Contributing.SamplesApp) at least once. 1. Only Android and WASM are supported from Visual Studio for Windows. (Running tests on iOS using a Mac is possible, see additional instructions below.) -1. If testing on WebAssembly, ensure that [`WebAssemblyDefaultUri`](https://github.com/unoplatform/uno/blob/master/src/SamplesApp/SamplesApp.UITests/Constants.cs) matches Url used when the sample app was launched in the step above. Visual Studio may change the Url on demand to avoid conflicts with already running sites on the same machine. +1. If testing on WebAssembly, ensure that [`WebAssemblyDefaultUri`](../../../../src/SamplesApp/SamplesApp.UITests/Constants.cs) matches Url used when the sample app was launched in the step above. Visual Studio may change the Url on demand to avoid conflicts with already running sites on the same machine. 1. Open the [Test Explorer](https://learn.microsoft.com/visualstudio/test/run-unit-tests-with-test-explorer) in Visual Studio. 1. UI tests are grouped under 'SamplesApp.UITests'. From the Test Explorer you can run all tests, debug a single test, etc. @@ -47,8 +47,8 @@ UI tests contribute significantly to the CI build time, and for many purposes a ## Adding a new test -1. Typically the first step is to [add a sample to the SamplesApp](working-with-the-samples-apps.md) that reproduces the bug you're fixing or demonstrates the functionality you're adding, unless you can do so with an existing sample. -2. The UI test fixtures themselves are located in [SamplesApp.UITests](https://github.com/unoplatform/uno/tree/master/src/SamplesApp/SamplesApp.UITests). Locate the test class corresponding to the control or class you want to create a test for. If you need to add a new test class, create the file as `Namespace_In_Snake_Case/ControlNameTests/ControlName_Tests.cs`. The class should inherit from `SampleControlUITestBase` and be marked with the `[TestFixture]` attribute. +1. Typically the first step is to [add a sample to the SamplesApp](xref:Uno.Contributing.SamplesApp) that reproduces the bug you're fixing or demonstrates the functionality you're adding, unless you can do so with an existing sample. +2. The UI test fixtures themselves are located in [SamplesApp.UITests](../../../../src/SamplesApp/SamplesApp.UITests). Locate the test class corresponding to the control or class you want to create a test for. If you need to add a new test class, create the file as `Namespace_In_Snake_Case/ControlNameTests/ControlName_Tests.cs`. The class should inherit from `SampleControlUITestBase` and be marked with the `[TestFixture]` attribute. 3. Add your test, making sure to include the `[Test]` and `[AutoRetry]` attributes. (The `[AutoRetry]` attributes indicates that the test should be retried if it fails. Currently it's required for all tests.) ## Selectively ignore tests per platform diff --git a/doc/articles/uno-development/themeresource-internals.md b/doc/articles/contributing/themeresource-internals.md similarity index 97% rename from doc/articles/uno-development/themeresource-internals.md rename to doc/articles/contributing/themeresource-internals.md index bf6e39c9bf21..db252c263518 100644 --- a/doc/articles/uno-development/themeresource-internals.md +++ b/doc/articles/contributing/themeresource-internals.md @@ -41,7 +41,7 @@ The resource update machinery can be broadly split into two parts: registering r ### Registering assignations for updates -ThemeResource assignments can only be created in XAML - WinUI provides no way to create them in code. Thus, in Uno, all assignations come ultimately from either [XamlFileGenerator](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs) or XamlReader/[XamlObjectBuilder](https://github.com/unoplatform/uno/blob/master/src/Uno.UI/UI/Xaml/Markup/Reader/XamlObjectBuilder.cs). +ThemeResource assignments can only be created in XAML - WinUI provides no way to create them in code. Thus, in Uno, all assignations come ultimately from either [XamlFileGenerator](../../../src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs) or XamlReader/[XamlObjectBuilder](../../../src/Uno.UI/UI/Xaml/Markup/Reader/XamlObjectBuilder.cs). There are 3 cases for ThemeResource assignations that are handled differently: diff --git a/doc/articles/uno-development/uno-internals-android.md b/doc/articles/contributing/uno-internals-android.md similarity index 87% rename from doc/articles/uno-development/uno-internals-android.md rename to doc/articles/contributing/uno-internals-android.md index 4978b6febf91..148e5d1c5c2c 100644 --- a/doc/articles/uno-development/uno-internals-android.md +++ b/doc/articles/contributing/uno-internals-android.md @@ -4,13 +4,13 @@ uid: Uno.Contributing.Android # How Uno works on Android -This article explores Android-specific details of Uno's internals, with a focus on information that's useful for contributors to Uno. For an overview of how Uno works on all platforms, see [this article](uno-internals-overview.md). +This article explores Android-specific details of Uno's internals, with a focus on information that's useful for contributors to Uno. For an overview of how Uno works on all platforms, see [this article](xref:Uno.Contributing.Overview). Some particulars of Android: ## Some classes are written in Java -Several base classes and helper classes are written in native Java code. These are located in [Uno.UI.BindingHelper.Android](https://github.com/unoplatform/uno/tree/master/src/Uno.UI.BindingHelper.Android/Uno/UI). +Several base classes and helper classes are written in native Java code. These are located in [Uno.UI.BindingHelper.Android](../../../src/Uno.UI.BindingHelper.Android/Uno/UI). The Xamarin.Android framework gives complete access to the Android API from managed C#, so why write anything in Java? The reason is performance. The interop between Java and C# can be costly, and instrumented profiling identified that certain virtual methods when overridden in C# and called in heavily-used paths (eg measure and arrange) imposed a measurable performance penalty. Over time, these 'hot' methods have been lowered to Java classes, particularly the `UnoViewGroup` class. @@ -25,4 +25,4 @@ Recall that `UIElement` implements `DependencyObect` [as an interface](uno-inter ## Layouting -Uno's measure and arrange logic is triggered from the native Android layout cycle. For a schematic of the control flow, see [Layouting in Android](Uno-UI-Layouting-Android.md). +Uno's measure and arrange logic is triggered from the native Android layout cycle. For a schematic of the control flow, see [Layouting in Android](xref:Uno.Contributing.Layouting.Android). diff --git a/doc/articles/uno-development/uno-internals-hotreload.md b/doc/articles/contributing/uno-internals-hotreload.md similarity index 100% rename from doc/articles/uno-development/uno-internals-hotreload.md rename to doc/articles/contributing/uno-internals-hotreload.md diff --git a/doc/articles/uno-development/uno-internals-ios.md b/doc/articles/contributing/uno-internals-ios.md similarity index 84% rename from doc/articles/uno-development/uno-internals-ios.md rename to doc/articles/contributing/uno-internals-ios.md index 8495d9e8c9a6..734aedf81872 100644 --- a/doc/articles/uno-development/uno-internals-ios.md +++ b/doc/articles/contributing/uno-internals-ios.md @@ -4,15 +4,15 @@ uid: Uno.Contributing.iOS # How Uno works on iOS -This article explores iOS-specific details of Uno's internals, with a focus on information that's useful for contributors to Uno. For an overview of how Uno works on all platforms, see [this article](uno-internals-overview.md). +This article explores iOS-specific details of Uno's internals, with a focus on information that's useful for contributors to Uno. For an overview of how Uno works on all platforms, see [this article](xref:Uno.Contributing.Overview). ## UIElement inherits from UIView `UIElement` in Uno is a native view on iOS, inheriting from the general `UIView` type. To elaborate, `UIElement`'s base classes are the following: `UIKit.UIView` → `Uno.UI.Controls.BindableUIView` → `Windows.UI.Xaml.UIElement` -Recall that `UIElement` implements `DependencyObject` [as an interface](uno-internals-overview.md) in Uno. +Recall that `UIElement` implements `DependencyObject` [as an interface](xref:Uno.Contributing.Overview) in Uno. ## Layouting -Uno's measure and arrange logic is triggered from the native iOS layout cycle. For a schematic of the control flow, see [Layouting in iOS](Uno-UI-Layouting-iOS.md). +Uno's measure and arrange logic is triggered from the native iOS layout cycle. For a schematic of the control flow, see [Layouting in iOS](xref:Uno.Contributing.Layouting.iOS). diff --git a/doc/articles/uno-development/uno-internals-macos.md b/doc/articles/contributing/uno-internals-macos.md similarity index 93% rename from doc/articles/uno-development/uno-internals-macos.md rename to doc/articles/contributing/uno-internals-macos.md index 255a8cad6ff5..ac3ec6e05115 100644 --- a/doc/articles/uno-development/uno-internals-macos.md +++ b/doc/articles/contributing/uno-internals-macos.md @@ -4,14 +4,14 @@ uid: Uno.Contributing.macOS # How Uno works on macOS -This article explores macOS-specific details of Uno's internals, with a focus on information that's useful for contributors to Uno. For an overview of how Uno works on all platforms, see [this article](uno-internals-overview.md). +This article explores macOS-specific details of Uno's internals, with a focus on information that's useful for contributors to Uno. For an overview of how Uno works on all platforms, see [this article](xref:Uno.Contributing.Overview). ## UIElement inherits from NSView `UIElement` in Uno is a native view on macOS, inheriting from the general `NSView` type. To elaborate, `UIElement`'s base classes are the following: `AppKit.NSView` → `Uno.UI.Controls.BindableNSView` → `Windows.UI.Xaml.UIElement` -Recall that `UIElement` implements `DependencyObect` [as an interface](uno-internals-overview.md) in Uno. +Recall that `UIElement` implements `DependencyObect` [as an interface](xref:Uno.Contributing.Overview) in Uno. ## Similarities with iOS diff --git a/doc/articles/uno-development/uno-internals-overview.md b/doc/articles/contributing/uno-internals-overview.md similarity index 82% rename from doc/articles/uno-development/uno-internals-overview.md rename to doc/articles/contributing/uno-internals-overview.md index 6609353ea6d6..ba1bba8bd8f0 100644 --- a/doc/articles/uno-development/uno-internals-overview.md +++ b/doc/articles/contributing/uno-internals-overview.md @@ -59,9 +59,10 @@ Notice the platform conditionals, since a member may be implemented for some pla For more details on how Uno Platform runs on each platform, see platform-specific information for: -* [Android](uno-internals-android.md) -* [iOS](uno-internals-ios.md) -* [WebAssembly](uno-internals-wasm.md) +* [Android](xref:Uno.Contributing.Android) +* [iOS](xref:Uno.Contributing.iOS) +* [WebAssembly](xref:Uno.Contributing.Wasm) +* [macOS](xref:Uno.Contributing.macOS) ## Uno.WinUI build-time tooling @@ -69,18 +70,18 @@ For more details on how Uno Platform runs on each platform, see platform-specifi This is the most substantial compile-time task that Uno Platform carries out. Whenever an app or class library is built, all contained XAML files are parsed and converted to C# files, which are then compiled in the usual way. (Note that this differs from WinUI, which parses XAML to XAML Binary Format (.xbf) files which are processed by the WinUI runtime.) -Uno Platform uses existing libraries to parse a given XAML file into a XAML object tree, then Uno-specific code is responsible for interpreting the XAML object tree as a tree of visual elements and their properties. Most of this takes place within the [`XamlFileGenerator`](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs) class. +Uno Platform uses existing libraries to parse a given XAML file into a XAML object tree, then Uno-specific code is responsible for interpreting the XAML object tree as a tree of visual elements and their properties. Most of this takes place within the [`XamlFileGenerator`](../../../src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs) class. ### DependencyObject implementation generator -On [Android](uno-internals-android.md), [iOS](uno-internals-ios.md), and [macOS](uno-internals-macos.md), `UIElement` (the base view type in WinUI) inherits from the native view class on the respective platform. This poses a challenge because `UIElement` inherits from the `DependencyObject` class in UWP/WinUI, which is a key part of the dependency property system. Uno makes this work by breaking from WinUI and having `DependencyObject` be an interface rather than a type. +On [Android](uno-internals-android.md), [iOS](uno-internals-ios.md), and [macOS](uno-internals-macos.md), `UIElement` (the base view type in UWP/WinUI) inherits from the native view class on the respective platform. This poses a challenge because `UIElement` inherits from the `DependencyObject` class in UWP/WinUI, which is a key part of the dependency property system. Uno makes this work by breaking from UWP/WinUI and having `DependencyObject` be an interface rather than a type. -Class library authors and app authors sometimes inherit directly from `DependencyObject` rather than a more derived type. To support this scenario seamlessly, the [`DependencyObjectGenerator` task](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs) looks for such classes and [generates](https://github.com/unoplatform/Uno.SourceGeneration) a partial implementation for the `DependencyObject` interface, ie, the methods that on UWP would be inherited from the base class. +Class library authors and app authors sometimes inherit directly from `DependencyObject` rather than a more derived type. To support this scenario seamlessly, the [`DependencyObjectGenerator` task](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs) looks for such classes and [generates](https://github.com/unoplatform/Uno.SourceGeneration) a partial implementation for the `DependencyObject` interface, ie the methods that on UWP would be inherited from the base class. ### Formatting image assets -Different platforms have different requirements for where bundled image files are located and how multiple versions of the same asset are handled (eg, to target different resolutions). The [asset retargeting task](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs) copies the image assets located in the shared project to the appropriate location and format for the target platform. +Different platforms have different requirements for where bundled image files are located and how multiple versions of the same asset are handled (eg, to target different resolutions). The [asset retargeting task](../../../src/SourceGenerators/Uno.UI.Tasks/Assets/RetargetAssets.cs) copies the image assets located in the shared project to the appropriate location and format for the target platform. ### Formatting string resources -As with images, different platforms have different requirements for the location and formatting of localized string resources. The [ResourcesGenerationTask](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs) reads the strings defined in WinUI's `*.resw` files in the shared project, and generates the appropriate platform-specific file. +As with images, different platforms have different requirements for location and formatting of localized string resources. The [ResourcesGenerationTask](https://github.com/unoplatform/uno/blob/master/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs) reads the strings defined in UWP's `*.resw` files in the shared project, and generates the appropriate platform-specific file. diff --git a/doc/articles/uno-development/uno-internals-wasm.md b/doc/articles/contributing/uno-internals-wasm.md similarity index 100% rename from doc/articles/uno-development/uno-internals-wasm.md rename to doc/articles/contributing/uno-internals-wasm.md diff --git a/doc/articles/uno-development/ways-to-contribute.md b/doc/articles/contributing/ways-to-contribute.md similarity index 90% rename from doc/articles/uno-development/ways-to-contribute.md rename to doc/articles/contributing/ways-to-contribute.md index 0c8fed905afb..9046247b6861 100644 --- a/doc/articles/uno-development/ways-to-contribute.md +++ b/doc/articles/contributing/ways-to-contribute.md @@ -21,7 +21,7 @@ Here are questions you can consider before you file a bug to make sure you're no Pre-Submission check: -1. Did you read the [documentation](https://platform.uno/docs/articles/intro.html)? +1. Did you read the [documentation](xref:Uno.Documentation.Intro)? 2. Did you check the latest [pre-release](https://www.nuget.org/packages/Uno.UI/absoluteLatest) of Uno Platform to see if the issue has been fixed? 3. Does the issue exist on the WinUI project (in which case it is not an Uno Platform issue) @@ -72,7 +72,7 @@ The WinUI framework is pretty big, but many hands make light work. We welcome co ### Diving into the code -The [contributor's guide](contributing-intro.md) has plenty of resources to help you get up and running with Uno's code, including a [guide to building and debugging Uno.UI](debugging-uno-ui.md), and a [guide to Uno's internals](uno-internals-overview.md). +The [contributor's guide](xref:Uno.Contributing.Intro) has plenty of resources to help you get up and running with Uno's code, including a [guide to building and debugging Uno.UI](xref:Uno.Contributing.DebuggingUno), and a [guide to Uno's internals](xref:Uno.Contributing.Overview). ### Finding an issue to work on @@ -84,15 +84,15 @@ In either case, once you're ready, leave a comment on the issue indicating that ### Getting down to work -The [contributor's guide](contributing-intro.md) has the information you need. The most important points are: +The [contributor's guide](xref:Uno.Contributing.Intro) has the information you need. The most important points are: - Work in [your own fork of Uno](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) -- Be sure to use the [Conventional Commits format](git-conventional-commits.md) -- Once you're done, you'll probably need to [add a test](../contributing/guidelines/creating-tests.md) +- Be sure to use the [Conventional Commits format](xref:Uno.Contributing.ConventionalCommits) +- Once you're done, you'll probably need to [add a test](xref:Uno.Contributing.Tests.CreatingTests) ### Creating a PR -Once you're ready to create a PR, check out the [Guidelines for pull requests](../contributing/guidelines/pull-requests.md) in Uno. +Once you're ready to create a PR, check out the [Guidelines for pull requests](xref:Uno.Contributing.PullRequests) in Uno. ### Need help? diff --git a/doc/articles/uno-development/working-with-the-samples-apps.md b/doc/articles/contributing/working-with-the-samples-apps.md similarity index 89% rename from doc/articles/uno-development/working-with-the-samples-apps.md rename to doc/articles/contributing/working-with-the-samples-apps.md index 69fadaedaad4..2bed5ab53935 100644 --- a/doc/articles/uno-development/working-with-the-samples-apps.md +++ b/doc/articles/contributing/working-with-the-samples-apps.md @@ -7,13 +7,13 @@ uid: Uno.Contributing.SamplesApp The SamplesApp in Uno.UI is an Uno application containing a large number of UI and non-UI samples. It serves a few purposes: * Allow for manually testing new features and investigating bugs, -* Provide UI for [automated UI tests](creating-ui-tests.md), +* Provide UI for [automated UI tests](xref:Uno.Contributing.Tests.CreateUITests), * Allow automated comparison of static snapshots between Uno versions, * Document the functionality supported by Uno. This article details how to run SamplesApp and how to add a new sample. -For instructions on working with automated UI tests, [go here](creating-ui-tests.md). +For instructions on working with automated UI tests, [go here](xref:Uno.Contributing.Tests.CreateUITests). ## Running SamplesApp @@ -22,7 +22,7 @@ The SamplesApp from latest master branch for WebAssembly is available online: ht To run the SamplesApp locally: 1. Ensure [your environment is configured](xref:Uno.GetStarted.vs2022) for the platform you want to run on. -2. Open Uno.UI with the [correct target override and solution filter](building-uno-ui.md) for the platform you want to run on. +2. Open Uno.UI with the [correct target override and solution filter](xref:Uno.Contributing.BuildingUno) for the platform you want to run on. 3. Select `SamplesApp.[Platform]` as the startup app. (Eg, `SamplesApp.iOS` if you're running on iOS.) 4. If you're testing on a mobile platform, use a tablet if possible, as the app is optimized for a tablet layout. 5. Run SamplesApp. @@ -37,7 +37,7 @@ By default, SamplesApp starts in debugging mode on localhost, making it inaccess ## Sample organization -Samples are located in the [`UITests.Shared` project](https://github.com/unoplatform/uno/tree/master/src/SamplesApp/UITests.Shared). UI-related samples are generally grouped by control, or by functional area for samples that aren't specific to a particular control (eg `VisualStateTests`). Non-UI samples are generally grouped by namespace of the tested feature. +Samples are located in the [`UITests.Shared` project](../../../src/SamplesApp/UITests.Shared). UI-related samples are generally grouped by control, or by functional area for samples that aren't specific to a particular control (eg `VisualStateTests`). Non-UI samples are generally grouped by namespace of the tested feature. Note that there's no 'master list' of samples. Instead, individual samples are tagged with `SampleAttribute` (or `SampleControlInfoAttribute`, for older samples), and the SamplesApp automatically picks up all samples using the attribute. @@ -107,7 +107,7 @@ have changed. ### Troubleshooting the tests -It is possible to enable the chromium head using the configuration parameters in the [app.ts](https://github.com/unoplatform/uno/blob/master/src/SamplesApp/SamplesApp.Wasm.UITests/app.ts) file. +It is possible to enable the chromium head using the configuration parameters in the [app.ts](../../../src/SamplesApp/SamplesApp.Wasm.UITests/app.ts) file. ## Creating performance benchmarks with BenchmarkDotNet diff --git a/doc/articles/controls/GLCanvasElement.md b/doc/articles/controls/GLCanvasElement.md index 42c8d2f79b83..4d9cc49bb148 100644 --- a/doc/articles/controls/GLCanvasElement.md +++ b/doc/articles/controls/GLCanvasElement.md @@ -47,7 +47,7 @@ To detect errors in initializing the OpenGL environment, `GLCanvasElement` expos ## How to use Silk.NET -To learn more about using [Silk.NET](https://www.nuget.org/packages/Silk.NET.OpenGL/) as a C# binding for OpenGL, see the examples in the Silk.NET repository [here](https://github.com/dotnet/Silk.NET/tree/main/examples/CSharp). Note that the windowing and inputs APIs in Silk.NET are not relevant to `GLCanvasElement`, since we only use Silk.NET as an OpenGL binding library, not a windowing library. +To learn more about using [Silk.NET](https://www.nuget.org/packages/Silk.NET.OpenGL/) as a C# binding for OpenGL, see the examples in the [Silk.NET repository](https://github.com/dotnet/Silk.NET/tree/main/examples/CSharp). Note that the windowing and inputs APIs in Silk.NET are not relevant to `GLCanvasElement`, since we only use Silk.NET as an OpenGL binding library, not a windowing library. ## Full example diff --git a/doc/articles/controls/ToggleSwitch.md b/doc/articles/controls/ToggleSwitch.md index b458a0ebf216..e976695920fe 100644 --- a/doc/articles/controls/ToggleSwitch.md +++ b/doc/articles/controls/ToggleSwitch.md @@ -25,7 +25,7 @@ The Native Style for ToggleSwitch on Android is based on `SwitchCompat`, a Mater It does not make any attempt to use the platform provided widget on those devices which it is available normally. This ensures the same behavior on all system versions. -#### Platform support +#### Platform support on Android | Property | `BindableSwitchCompat` | |----------------------|:----------------------:| @@ -91,7 +91,7 @@ If you need the native style but you want to change the Text, ThumbTint and Trac Based on the UISwitch. -#### Platform support +#### Platform support on iOS | Property | BindableUISwitch | | ------------------------------------------ |:----------------:| diff --git a/doc/articles/controls/map-control-support.md b/doc/articles/controls/map-control-support.md index baf0353ee40f..2cc25cfa33a6 100644 --- a/doc/articles/controls/map-control-support.md +++ b/doc/articles/controls/map-control-support.md @@ -83,8 +83,7 @@ To use the map component, you will need an API key for Windows and Android. Here ### Windows -For the detailed procedure for Windows, see [Request a maps authentication key -](https://learn.microsoft.com/windows/uwp/maps-and-location/authentication-key) documentation. +For the detailed procedure for Windows, see [Request a maps authentication key](https://learn.microsoft.com/windows/uwp/maps-and-location/authentication-key) documentation. + Go to + Login to your account or register if you don't have one diff --git a/doc/articles/create-an-app-vs2022.md b/doc/articles/create-an-app-vs2022.md index d1ddca826745..b3e8e3a4d621 100644 --- a/doc/articles/create-an-app-vs2022.md +++ b/doc/articles/create-an-app-vs2022.md @@ -12,7 +12,7 @@ To create an Uno Platform app: 1. Create a new C# solution using the **Uno Platform App** template, from Visual Studio's **Start Page**, then click the **Next** button - ![Visual Studio - Get started - Selecting `create a new project` option](Assets/tutorial01/newproject1.PNG) + ![Visual Studio - Get started - Selecting `create a new project` option](Assets/tutorial01/newproject1.PNG) ![Visual Studio - Create a new project - Selecting `Uno Platform App` option](Assets/tutorial01/newproject2.PNG) 1. Configure your new project by providing a project name and a location, check the "**Place solution and project in the same directory**" option, then click the **Create** button @@ -24,7 +24,7 @@ To create an Uno Platform app: 1. Choose a template preset to build your application - ![Visual Studio - Configure your new project](getting-started/wizard/assets/intro.png) + ![Visual Studio - Configure your new project](wizard/assets/intro.png) > [!TIP] > For a detailed overview of the Uno Platform project template wizard and all its options, see [this](xref:Uno.GettingStarted.UsingWizard). @@ -33,11 +33,11 @@ To create an Uno Platform app: 1. Click the create button -1. Ensure that the lower left IDE icon shows a check mark and says "Ready" ![A checkmark with a text saying ready](getting-started/wizard/assets/vs2022-ready-statusbar.png). This ensures that the projects have been created, and their dependencies have been restored completely. +1. Ensure that the lower left IDE icon shows a check mark and says "Ready" ![A checkmark with a text saying ready](wizard/assets/vs2022-ready-statusbar.png). This ensures that the projects have been created, and their dependencies have been restored completely. 1. A Windows Firewall window may appear. If you do not intend to do Linux development with WSL, check "Private networks" only. Otherwise, check "Public networks" and "Private networks". -1. A banner at the top of the editor may ask to reload projects, click **Reload projects**: +1. A banner at the top of the editor may ask to reload projects, click **Reload projects**: ![Visual Studio - A banner indicating to reload projects](Assets/quick-start/vs2022-project-reload.png) 1. > [!IMPORTANT] @@ -77,7 +77,7 @@ To run the **WebAssembly** (Wasm) head: - In the debugger toolbar, click the down arrow to select **MyApp (WebAssembly)** - ![Visual Studio - Select the Wasm profile](getting-started/wizard/assets/wasm-debugger-dropdown.png) + ![Visual Studio - Select the Wasm profile](wizard/assets/wasm-debugger-dropdown.png) - Press the `MyApp (WebAssembly)` button to deploy the app - To run/debug your WebAssembly app on a mobile device, you can utilize the Dev Tunnels feature of Visual Studio 2022 (see [Microsoft Learn documentation](https://learn.microsoft.com/aspnet/core/test/dev-tunnels) to get started) @@ -95,7 +95,7 @@ To run the **Windows** (WinAppSDK) head: - In the debugger toolbar, click the down arrow to select **MyApp (WinAppSDK Packaged)** or **MyApp (WinAppSDK Unpackaged)** - ![Visual Studio - Select the WinappSDK profile](getting-started/wizard/assets/winappsdk-debugger-dropdown.png) + ![Visual Studio - Select the WinappSDK profile](wizard/assets/winappsdk-debugger-dropdown.png) - Press the `MyApp (WinAppSDK Packaged)` or `MyApp (WinAppSDK Unpackaged)` button to deploy the app - If you have not enabled Developer Mode, the Settings app should open to the appropriate page. Turn on Developer Mode and accept the disclaimer. @@ -150,4 +150,4 @@ Learn more about: - [Uno Platform App solution structure](xref:Uno.Development.AppStructure) - [Troubleshooting](xref:Uno.UI.CommonIssues) - [How-tos and Tutorials](xref:Uno.Tutorials.Intro) See real-world examples with working code. -- [List of views implemented in Uno](implemented-views.md) for the set of available controls and their properties. +- [List of views implemented in Uno](..\implemented-views.md) for the set of available controls and their properties. diff --git a/doc/articles/faq.md b/doc/articles/faq.md index 0e3c46eba30a..44aa46aa29a7 100644 --- a/doc/articles/faq.md +++ b/doc/articles/faq.md @@ -8,7 +8,7 @@ uid: Uno.Development.FAQ ### What is the Uno Platform? -Uno Platform lets you write an application once in XAML and/or C#, and deploy it to [any target platform](getting-started/requirements.md). Read more [here](xref:Uno.Documentation.Intro). +Uno Platform lets you write an application once in XAML and/or C#, and deploy it to [any target platform](getting-started/requirements.md). Read more about this in the [Intro](xref:Uno.Documentation.Intro). ### Who makes Uno Platform? @@ -93,7 +93,7 @@ If you have an existing VB.NET application that you would like to port/modernize To be exact, add "Class Library" VB project (not "Class Library (.Net Framework)", and not "Class Library (Universal Windows)"). Use ".NET Standard 2.0" as Target Framework. To use this library in Uno heads for all platforms, add a reference to this library (the simplest way is to right-click on "References" nodes inside these heads). You can also use the same Class Library in your original VB project. The same Class Library can also be used in any other .NET Standard compatible projects. -Additionally, if you’d like to move any of your VB.NET code to C#, you may be able to use automated tools such as https://converter.telerik.com +Additionally, if you’d like to move any of your VB.NET code to C#, you may be able to use automated tools such as [Telerik Converter](https://converter.telerik.com) The best course of action is to do a POC and our team is happy to assist you in validating Uno Platform’s fit. Please [contact us](https://platform.uno/contact) with any queries. diff --git a/doc/articles/features/PasswordVault.md b/doc/articles/features/PasswordVault.md index d0df83bc6a73..e34a50027d93 100644 --- a/doc/articles/features/PasswordVault.md +++ b/doc/articles/features/PasswordVault.md @@ -12,10 +12,10 @@ uid: Uno.Features.PasswordVault ## Supported features -| Feature | Windows | Android | iOS | Web (WASM) Linux (Skia) | Win 7 (Skia) | Tizen | -|----------------------|---------|---------|---------|--------------------------|--------------|-------| -| `PasswordVault` | ✔ | ✔ | ✔ | ✖ | ✖ | ✖ | ✖ | -| `PasswordCredential` | ✔ | Partial | Partial | Partial | ✖ | ✖ | ✖ | +| Feature | Windows | Android | iOS | Web (WASM) | Linux (Skia) | Win 7 (Skia) | Tizen | +|----------------------|---------|---------|---------|--------------------------|---------------|-------| +| `PasswordVault` | ✔ | ✔ | ✔ | ✖ | ✖ | ✖ | ✖ | +| `PasswordCredential` | ✔ | Partial | Partial | Partial | ✖ | ✖ | ✖ | ## `PasswordVault` diff --git a/doc/articles/features/dialogs.md b/doc/articles/features/dialogs.md index 35cd128a3eff..684c2b9fcd0e 100644 --- a/doc/articles/features/dialogs.md +++ b/doc/articles/features/dialogs.md @@ -36,6 +36,7 @@ It is crucial to set the `XamlRoot` property before calling `ShowAsync`. This wa ### Opening a `ContentDialog` from a Model/ViewModel When you want to open a `ContentDialog` from a Model or ViewModel, you can pass the `XamlRoot` from the view to the model or view model by creating a service (e.g., `IXamlRootProvider`) that is initialized at the start of the app with the XamlRoot of the main window. + Here is a more detailed example of how to display a `ContentDialog` with result handling: @@ -68,6 +69,15 @@ private async Task DisplayDeleteFileDialog() } ``` +--- +> [!NOTE] +> This example dialog task must run on the UI thread. If your app uses XAML markup, the best place to execute it is in the code-behind of your XAML page. If your app uses C# markup, execute it directly below the main UI definition of the page class, similar to a regular event handler. + +--- + +> [!IMPORTANT] +> If you attempt to execute this task from within your Model or ViewModel without properly handling the `XamlRoot` (which belongs to the UI layer), you will encounter an exception. This occurs because UI-related code is being executed on a non-UI thread. + ### [MVVM](#tab/mvvm) If you are using the MVVM pattern, you can use the `AsyncRelayCommand` from the Uno Platform to bind the command to the dialog display method. Here is an example of how to bind the command to the dialog display method in the ViewModel: diff --git a/doc/articles/features/gamepad.md b/doc/articles/features/gamepad.md index 9a2dcab888ce..38b1fed1c858 100644 --- a/doc/articles/features/gamepad.md +++ b/doc/articles/features/gamepad.md @@ -38,7 +38,7 @@ private void GetGamepads() myGamepads.Add(gamepad); } } - } + } } ``` @@ -67,4 +67,4 @@ if (GamepadButtons.A == (reading.Buttons & GamepadButtons.A)) ## See Gamepad in action -* To see this API in action, visit out Gallery and look for Gamepad [here](https://gallery.platform.uno/). +* To see this API in action, [visit out Gallery and look for Gamepad](https://gallery.platform.uno/). diff --git a/doc/articles/features/shapes-and-brushes.md b/doc/articles/features/shapes-and-brushes.md index ccb2c663b38a..f310c9898319 100644 --- a/doc/articles/features/shapes-and-brushes.md +++ b/doc/articles/features/shapes-and-brushes.md @@ -75,18 +75,18 @@ The brush currently has an important limitation on Android, iOS, and macOS: it c - - - - + @@ -106,7 +106,7 @@ Where you can use which brushes | Usage | SolidColorBrush | ImageBrush | GradientBrush | | -------------------------------------------- | --------------- | -------------------- | --------------- | | `Background` property (many controls/panels) | Yes | Yes (except on Wasm) | Yes | -| `BorderBrush` (`Border`, `Panel`) | Yes | No | Yes (Skia, Android), partial (iOS, WASM) [see below] | +| `BorderBrush` (`Border`, `Panel`) | Yes | No | Yes (Skia, Android), partial (iOS, WASM) [see below](#gradient-border-brush-limitations-on-wasm-and-ios) | | `Foreground` (`TextBlock`) | Yes | No | Yes (Wasm only) | | `Fill` (Shapes) | Yes | Yes (except on Wasm) | Yes | | `Stroke` (Shapes) | Yes | No | Yes (Wasm only) | diff --git a/doc/articles/features/using-the-uno-sdk.md b/doc/articles/features/using-the-uno-sdk.md index 892149e286e4..71f0d8a2199c 100644 --- a/doc/articles/features/using-the-uno-sdk.md +++ b/doc/articles/features/using-the-uno-sdk.md @@ -82,7 +82,7 @@ Here are the supported features: | `Svg` | [SVG](xref:Uno.Features.SVG) support for iOS, and Android. This option is not needed when only targeting WebAssembly and WinAppSDK. | | `ThemeService` | Adds the [Uno.Extensions.Core.WinUI package](https://www.nuget.org/packages/Uno.Extensions.Core.WinUI). | | `Toolkit` | Adds support for the [Uno.Toolkit](xref:Toolkit.GettingStarted). | -| `WebView` | Adds support for the [WebView2 control](xref:Uno.Controls.WebView2). +| `WebView` | Adds support for the [WebView2 control](xref:Uno.Controls.WebView2).| ## Implicit Packages @@ -161,11 +161,11 @@ Those properties can be set from `Directory.Build.props` or may be set in the `c Mvvm; SkiaRenderer; - + 6.3.6 9.0.1 8.4.0 - + ``` @@ -245,7 +245,7 @@ As a result, the csproj file is on disk and will show the file as modified in yo Note that we are currently tracking these Visual Studio issues, make sure to upvote them: -- `net8.0-browserwasm` must be first for WebAssembly debugging to work ([Link](https://developercommunity.visualstudio.com/t/net80-must-be-first-for-WebAssembly-pub/10643720)) +- `net8.0-browserwasm` must be first for WebAssembly debugging to work ([Link to the issue on Visual Studio developer community](https://developercommunity.visualstudio.com/t/net80-must-be-first-for-WebAssembly-pub/10643720)) - [WinAppSDK Unpackaged profile cannot be selected properly when a net8.0 mobile target is active](https://developercommunity.visualstudio.com/t/WinAppSDK-Unpackaged-profile-cannot-be-s/10643735) ## Disabling Default Items diff --git a/doc/articles/features/windows-ui-markup-extensions.md b/doc/articles/features/windows-ui-markup-extensions.md index ccda69b15ff3..13d33e35b6a1 100644 --- a/doc/articles/features/windows-ui-markup-extensions.md +++ b/doc/articles/features/windows-ui-markup-extensions.md @@ -102,7 +102,7 @@ public class DynamicBindExtension : MarkupExtension The following XAML will display “Page Tag”: ```xml - [!TIP] -> If you want to use another environment or IDE, see our [general getting started](get-started.md). +> If you want to use another environment or IDE, see our [general getting started](xref:Uno.GetStarted). ## Install Visual Studio with Workloads @@ -27,21 +27,21 @@ To create Uno Platform applications you will need [**Visual Studio 2022 17.9 or > [!NOTE] > If you intend to do Linux development with WSL, make sure to select **.NET Debugging with WSL** in the **Individual components** section. > [!IMPORTANT] -> Uno Platform 5.0 and later [does not support Xamarin projects anymore](xref:Uno.Development.MigratingToUno5). To build Xamarin-based projects in Visual Studio 2022, in Visual Studio's installer `Individual components` tab, search for Xamarin and select `Xamarin` and `Xamarin Remoted Simulator`. See [this section on migrating Xamarin projects](migrating-from-xamarin-to-net6.md) to .NET 6. +> Uno Platform 5.0 and later [does not support Xamarin projects anymore](xref:Uno.Development.MigratingToUno5). To build Xamarin-based projects in Visual Studio 2022, in Visual Studio's installer `Individual components` tab, search for Xamarin and select `Xamarin` and `Xamarin Remoted Simulator`. See [this section on migrating Xamarin projects](xref:Uno.Development.MigratingFromXamarinToNet6) to .NET 6. ## Check your environment -[!include[use-uno-check](includes/use-uno-check-inline-windows-noheader.md)] +[!include[use-uno-check](xref:Uno.uno-check-inline.Windows)] ## Install the Uno Platform Extension -1. Launch Visual Studio 2022, then click `Continue without code`. Click `Extensions` -> `Manage Extensions` from the Menu Bar. +1. Launch Visual Studio 2022, then click `Continue without code`. Click `Extensions` -> `Manage Extensions` from the Menu Bar. - ![Visual Studio - "Extensions" drop-down selecting "Manage Extensions"](Assets/tutorial01/manage-extensions.png) + ![Visual Studio - "Extensions" drop-down selecting "Manage Extensions"](Assets/tutorial01/manage-extensions.png) -2. In the Extension Manager expand the **Online** node and search for `Uno`, install the `Uno Platform` extension or download it from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=unoplatform.uno-platform-addin-2022), then restart Visual Studio. +2. In the Extension Manager expand the **Online** node and search for `Uno`, install the `Uno Platform` extension or download it from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=unoplatform.uno-platform-addin-2022), then restart Visual Studio. - ![Extension Manager - Uno Platform extension](Assets/tutorial01/uno-extensions.PNG) + ![Extension Manager - Uno Platform extension](Assets/tutorial01/uno-extensions.PNG) ## Additional Setup for Windows Subsystem for Linux (WSL) @@ -59,7 +59,7 @@ To setup your environment for WSL: ### WSL -[!include[linux-setup](includes/additional-linux-setup-inline.md)] +[!include[linux-setup](../includes/additional-linux-setup-inline.md)] --- diff --git a/doc/articles/get-started-wizard.md b/doc/articles/get-started-wizard.md index 12be5e8d5874..d51c13eb4fc0 100644 --- a/doc/articles/get-started-wizard.md +++ b/doc/articles/get-started-wizard.md @@ -2,7 +2,7 @@ uid: Uno.GetStarted.Wizard --- - + # Done! Important next steps: Create a simple cross-platform Counter application. diff --git a/doc/articles/get-started.md b/doc/articles/get-started.md index 79879c5dcd9d..47a3c96ea09e 100644 --- a/doc/articles/get-started.md +++ b/doc/articles/get-started.md @@ -1,13 +1,20 @@ --- uid: Uno.GetStarted --- + ## Quick Start -1. Install and run Uno.Check to set up all the required pre-requisites -2. Download the Uno Platform extension for your IDE: +> [!TIP] +> In case your targeted IDE is Visual Studio, you can skip the following steps 1 & 2 as the Visual Studio Extension does already install and run Uno.Check for you! - +1. Install the [.NET SDK](https://dotnet.microsoft.com/en-us/download/dotnet/latest) to get `dotnet` available in your commandline. +2. Install and run [Uno.Check](./external/uno.check/doc/using-uno-check.md) to set up all the required pre-requisites. + a. Detailed [Configuration Options](./external/uno.check/doc/configuring-uno-check.md) for Uno-Check + b. If you run into issues with it, see [Troubleshooting Uno-Check](./external/uno.check/doc/troubleshooting-uno-check.md) +3. Download the Uno Platform extension for your IDE: + +
@@ -65,12 +72,6 @@ If you're developing on Windows, we recommend you use [**Visual Studio 2022**](x If you already use and love **JetBrains Rider** or **Visual Studio Code**, you can also use them to develop Uno Platform applications. Check the support matrix below to see which target platforms they support. -**Choose the IDE you want to use:** - -- [Visual Studio 2022](xref:Uno.GetStarted.vs2022) -- [VS Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) -- [Rider](xref:Uno.GetStarted.Rider) - To help you choose the appropriate IDE, the following table shows the compatibility of different development environments with various target platforms: | | [**Visual Studio**](xref:Uno.GetStarted.vs2022) | [**VS Code**](xref:Uno.GetStarted.vscode) | [**Codespaces / Gitpod**](xref:Uno.GetStarted.vscode) | [**JetBrains Rider**](xref:Uno.GetStarted.Rider) | @@ -85,14 +86,15 @@ To help you choose the appropriate IDE, the following table shows the compatibil - †† You will need to be connected to a Mac using [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) - ††† [WebAssembly debugging](https://youtrack.jetbrains.com/issue/RIDER-103346/Uno-Platform-for-WebAssembly-debugger-support) is not yet supported -# [**macOS**](#tab/macos) +**Choose the IDE you want to use:** -You can use **Visual Studio Code** or **JetBrains Rider**, to build Uno Platform applications on macOS. See the support matrix below for supported target platforms. +- [Visual Studio 2022](xref:Uno.GetStarted.vs2022) +- [VS Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) +- [Rider](xref:Uno.GetStarted.Rider) -**Choose the IDE you want to use:** +# [**macOS**](#tab/macos) -- [Get started with VS Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) -- [Get started with Rider](xref:Uno.GetStarted.Rider) +You can use **Visual Studio Code** or **JetBrains Rider**, to build Uno Platform applications on macOS. See the support matrix below for supported target platforms. To help you choose the appropriate IDE, the following table shows the compatibility of different development environments with various target platforms: @@ -106,15 +108,15 @@ To help you choose the appropriate IDE, the following table shows the compatibil The latest macOS release and Xcode version are required to develop with Uno Platform for iOS targets. If you have older Mac hardware that does not support the latest release of macOS, see the section for [Developing on older Mac hardware](xref:Uno.UI.CommonIssues.Ios#developing-on-older-mac-hardware). -# [**Linux**](#tab/linux) - - You can use either **JetBrains Rider** or **Visual Studio Code** to build Uno Platform applications on Linux. See the support matrix below for supported target platforms. - **Choose the IDE you want to use:** -- [Get started with Visual Studio Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) +- [Get started with VS Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) - [Get started with Rider](xref:Uno.GetStarted.Rider) +# [**Linux**](#tab/linux) + + You can use either **JetBrains Rider** or **Visual Studio Code** to build Uno Platform applications on Linux. See the support matrix below for supported target platforms. + To help you choose the appropriate IDE, the following table shows the compatibility of different development environments with various target platforms: | | [**VS Code**](xref:Uno.GetStarted.vscode) | [**Codespaces / Gitpod**](xref:Uno.GetStarted.vscode) | [**JetBrains Rider**](xref:Uno.GetStarted.Rider) | @@ -129,16 +131,14 @@ To help you choose the appropriate IDE, the following table shows the compatibil - † [WebAssembly debugging](https://youtrack.jetbrains.com/issue/RIDER-103346/Uno-Platform-for-WebAssembly-debugger-support) is not yet supported ---- - -## Questions +**Choose the IDE you want to use:** -For questions about Uno Platform, refer to the [general FAQ](xref:Uno.Development.FAQ) or see the [troubleshooting section](xref:Uno.UI.CommonIssues) for common issues and their solutions. +- [Get started with Visual Studio Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) +- [Get started with Rider](xref:Uno.GetStarted.Rider) -## Next Steps +--- -Choose the IDE to Learn more about: +## See Also -- [Visual Studio 2022](xref:Uno.GetStarted.vs2022) -- [VS Code, Codespaces and GitPod](xref:Uno.GetStarted.vscode) -- [Rider](xref:Uno.GetStarted.Rider) +- Questions about Uno Platform: [FAQ](xref:Uno.Development.FAQ) +- Common issues and their solutions: [Troubleshooting](xref:Uno.UI.CommonIssues). diff --git a/doc/articles/Assets/quick-start/201901-debugger-step-04.png b/doc/articles/getting-started/Assets/quick-start/201901-debugger-step-04.png similarity index 100% rename from doc/articles/Assets/quick-start/201901-debugger-step-04.png rename to doc/articles/getting-started/Assets/quick-start/201901-debugger-step-04.png diff --git a/doc/articles/Assets/quick-start/android-debug.png b/doc/articles/getting-started/Assets/quick-start/android-debug.png similarity index 100% rename from doc/articles/Assets/quick-start/android-debug.png rename to doc/articles/getting-started/Assets/quick-start/android-debug.png diff --git a/doc/articles/Assets/quick-start/desktop-debug-windows.png b/doc/articles/getting-started/Assets/quick-start/desktop-debug-windows.png similarity index 100% rename from doc/articles/Assets/quick-start/desktop-debug-windows.png rename to doc/articles/getting-started/Assets/quick-start/desktop-debug-windows.png diff --git a/doc/articles/Assets/quick-start/desktop-wsl2-debug-windows.png b/doc/articles/getting-started/Assets/quick-start/desktop-wsl2-debug-windows.png similarity index 100% rename from doc/articles/Assets/quick-start/desktop-wsl2-debug-windows.png rename to doc/articles/getting-started/Assets/quick-start/desktop-wsl2-debug-windows.png diff --git a/doc/articles/Assets/quick-start/ios-debug.png b/doc/articles/getting-started/Assets/quick-start/ios-debug.png similarity index 100% rename from doc/articles/Assets/quick-start/ios-debug.png rename to doc/articles/getting-started/Assets/quick-start/ios-debug.png diff --git a/doc/articles/Assets/quick-start/live-wizard-01-choose-name.png b/doc/articles/getting-started/Assets/quick-start/live-wizard-01-choose-name.png similarity index 100% rename from doc/articles/Assets/quick-start/live-wizard-01-choose-name.png rename to doc/articles/getting-started/Assets/quick-start/live-wizard-01-choose-name.png diff --git a/doc/articles/Assets/quick-start/live-wizard-02-select-preset.png b/doc/articles/getting-started/Assets/quick-start/live-wizard-02-select-preset.png similarity index 100% rename from doc/articles/Assets/quick-start/live-wizard-02-select-preset.png rename to doc/articles/getting-started/Assets/quick-start/live-wizard-02-select-preset.png diff --git a/doc/articles/Assets/quick-start/live-wizard-03-create-app.png b/doc/articles/getting-started/Assets/quick-start/live-wizard-03-create-app.png similarity index 100% rename from doc/articles/Assets/quick-start/live-wizard-03-create-app.png rename to doc/articles/getting-started/Assets/quick-start/live-wizard-03-create-app.png diff --git a/doc/articles/Assets/quick-start/rider-configure-new-unoplatform-app.png b/doc/articles/getting-started/Assets/quick-start/rider-configure-new-unoplatform-app.png similarity index 100% rename from doc/articles/Assets/quick-start/rider-configure-new-unoplatform-app.png rename to doc/articles/getting-started/Assets/quick-start/rider-configure-new-unoplatform-app.png diff --git a/doc/articles/Assets/quick-start/rider-folder-structure.png b/doc/articles/getting-started/Assets/quick-start/rider-folder-structure.png similarity index 100% rename from doc/articles/Assets/quick-start/rider-folder-structure.png rename to doc/articles/getting-started/Assets/quick-start/rider-folder-structure.png diff --git a/doc/articles/Assets/quick-start/rider-welcome-screen-new-solution.png b/doc/articles/getting-started/Assets/quick-start/rider-welcome-screen-new-solution.png similarity index 100% rename from doc/articles/Assets/quick-start/rider-welcome-screen-new-solution.png rename to doc/articles/getting-started/Assets/quick-start/rider-welcome-screen-new-solution.png diff --git a/doc/articles/Assets/quick-start/rider_webassembly_change_browser.png b/doc/articles/getting-started/Assets/quick-start/rider_webassembly_change_browser.png similarity index 100% rename from doc/articles/Assets/quick-start/rider_webassembly_change_browser.png rename to doc/articles/getting-started/Assets/quick-start/rider_webassembly_change_browser.png diff --git a/doc/articles/Assets/quick-start/run-android-rider.png b/doc/articles/getting-started/Assets/quick-start/run-android-rider.png similarity index 100% rename from doc/articles/Assets/quick-start/run-android-rider.png rename to doc/articles/getting-started/Assets/quick-start/run-android-rider.png diff --git a/doc/articles/Assets/quick-start/run-catalyst-rider.png b/doc/articles/getting-started/Assets/quick-start/run-catalyst-rider.png similarity index 100% rename from doc/articles/Assets/quick-start/run-catalyst-rider.png rename to doc/articles/getting-started/Assets/quick-start/run-catalyst-rider.png diff --git a/doc/articles/Assets/quick-start/run-desktop-rider.png b/doc/articles/getting-started/Assets/quick-start/run-desktop-rider.png similarity index 100% rename from doc/articles/Assets/quick-start/run-desktop-rider.png rename to doc/articles/getting-started/Assets/quick-start/run-desktop-rider.png diff --git a/doc/articles/Assets/quick-start/run-ios-rider.png b/doc/articles/getting-started/Assets/quick-start/run-ios-rider.png similarity index 100% rename from doc/articles/Assets/quick-start/run-ios-rider.png rename to doc/articles/getting-started/Assets/quick-start/run-ios-rider.png diff --git a/doc/articles/Assets/quick-start/run-wasm-rider.png b/doc/articles/getting-started/Assets/quick-start/run-wasm-rider.png similarity index 100% rename from doc/articles/Assets/quick-start/run-wasm-rider.png rename to doc/articles/getting-started/Assets/quick-start/run-wasm-rider.png diff --git a/doc/articles/Assets/quick-start/run-winappsdk-rider.png b/doc/articles/getting-started/Assets/quick-start/run-winappsdk-rider.png similarity index 100% rename from doc/articles/Assets/quick-start/run-winappsdk-rider.png rename to doc/articles/getting-started/Assets/quick-start/run-winappsdk-rider.png diff --git a/doc/articles/Assets/quick-start/tutorial-screenshot.png b/doc/articles/getting-started/Assets/quick-start/tutorial-screenshot.png similarity index 100% rename from doc/articles/Assets/quick-start/tutorial-screenshot.png rename to doc/articles/getting-started/Assets/quick-start/tutorial-screenshot.png diff --git a/doc/articles/Assets/quick-start/vs-code-android-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-android-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-android-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-android-project.png diff --git a/doc/articles/Assets/quick-start/vs-code-browserwasm-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-browserwasm-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-browserwasm-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-browserwasm-project.png diff --git a/doc/articles/Assets/quick-start/vs-code-chrome-debug.png b/doc/articles/getting-started/Assets/quick-start/vs-code-chrome-debug.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-chrome-debug.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-chrome-debug.png diff --git a/doc/articles/Assets/quick-start/vs-code-debug-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-debug-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-debug-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-debug-project.png diff --git a/doc/articles/Assets/quick-start/vs-code-desktop-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-desktop-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-desktop-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-desktop-project.png diff --git a/doc/articles/Assets/quick-start/vs-code-explore-other-features.png b/doc/articles/getting-started/Assets/quick-start/vs-code-explore-other-features.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-explore-other-features.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-explore-other-features.png diff --git a/doc/articles/Assets/quick-start/vs-code-extension-outputs.png b/doc/articles/getting-started/Assets/quick-start/vs-code-extension-outputs.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-extension-outputs.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-extension-outputs.png diff --git a/doc/articles/Assets/quick-start/vs-code-extension-status.png b/doc/articles/getting-started/Assets/quick-start/vs-code-extension-status.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-extension-status.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-extension-status.png diff --git a/doc/articles/Assets/quick-start/vs-code-ios-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-ios-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-ios-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-ios-project.png diff --git a/doc/articles/Assets/quick-start/vs-code-maccatalyst-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-maccatalyst-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-maccatalyst-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-maccatalyst-project.png diff --git a/doc/articles/Assets/quick-start/vs-code-mobile-debug.png b/doc/articles/getting-started/Assets/quick-start/vs-code-mobile-debug.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-mobile-debug.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-mobile-debug.png diff --git a/doc/articles/Assets/quick-start/vs-code-preferCSharpExtension.png b/doc/articles/getting-started/Assets/quick-start/vs-code-preferCSharpExtension.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-preferCSharpExtension.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-preferCSharpExtension.png diff --git a/doc/articles/Assets/quick-start/vs-code-settings-msbuild.png b/doc/articles/getting-started/Assets/quick-start/vs-code-settings-msbuild.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-settings-msbuild.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-settings-msbuild.png diff --git a/doc/articles/Assets/quick-start/vs-code-useOmniSharp.png b/doc/articles/getting-started/Assets/quick-start/vs-code-useOmniSharp.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-useOmniSharp.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-useOmniSharp.png diff --git a/doc/articles/Assets/quick-start/vs-code-windows-project.png b/doc/articles/getting-started/Assets/quick-start/vs-code-windows-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-code-windows-project.png rename to doc/articles/getting-started/Assets/quick-start/vs-code-windows-project.png diff --git a/doc/articles/Assets/quick-start/vs-install-dotnet-mobile.png b/doc/articles/getting-started/Assets/quick-start/vs-install-dotnet-mobile.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-install-dotnet-mobile.png rename to doc/articles/getting-started/Assets/quick-start/vs-install-dotnet-mobile.png diff --git a/doc/articles/Assets/quick-start/vs-install-dotnet.png b/doc/articles/getting-started/Assets/quick-start/vs-install-dotnet.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-install-dotnet.png rename to doc/articles/getting-started/Assets/quick-start/vs-install-dotnet.png diff --git a/doc/articles/Assets/quick-start/vs-install-uwp-sdks.png b/doc/articles/getting-started/Assets/quick-start/vs-install-uwp-sdks.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-install-uwp-sdks.png rename to doc/articles/getting-started/Assets/quick-start/vs-install-uwp-sdks.png diff --git a/doc/articles/Assets/quick-start/vs-install-uwp.png b/doc/articles/getting-started/Assets/quick-start/vs-install-uwp.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-install-uwp.png rename to doc/articles/getting-started/Assets/quick-start/vs-install-uwp.png diff --git a/doc/articles/Assets/quick-start/vs-install-web.png b/doc/articles/getting-started/Assets/quick-start/vs-install-web.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-install-web.png rename to doc/articles/getting-started/Assets/quick-start/vs-install-web.png diff --git a/doc/articles/Assets/quick-start/vs-install-xamarin.png b/doc/articles/getting-started/Assets/quick-start/vs-install-xamarin.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-install-xamarin.png rename to doc/articles/getting-started/Assets/quick-start/vs-install-xamarin.png diff --git a/doc/articles/Assets/quick-start/vs-mac-build.png b/doc/articles/getting-started/Assets/quick-start/vs-mac-build.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-mac-build.png rename to doc/articles/getting-started/Assets/quick-start/vs-mac-build.png diff --git a/doc/articles/Assets/quick-start/vs-mac-folder-structure.png b/doc/articles/getting-started/Assets/quick-start/vs-mac-folder-structure.png similarity index 100% rename from doc/articles/Assets/quick-start/vs-mac-folder-structure.png rename to doc/articles/getting-started/Assets/quick-start/vs-mac-folder-structure.png diff --git a/doc/articles/Assets/quick-start/vs2022-project-reload.png b/doc/articles/getting-started/Assets/quick-start/vs2022-project-reload.png similarity index 100% rename from doc/articles/Assets/quick-start/vs2022-project-reload.png rename to doc/articles/getting-started/Assets/quick-start/vs2022-project-reload.png diff --git a/doc/articles/Assets/quick-start/vsix-new-project-options.png b/doc/articles/getting-started/Assets/quick-start/vsix-new-project-options.png similarity index 100% rename from doc/articles/Assets/quick-start/vsix-new-project-options.png rename to doc/articles/getting-started/Assets/quick-start/vsix-new-project-options.png diff --git a/doc/articles/Assets/quick-start/vsix-new-project.png b/doc/articles/getting-started/Assets/quick-start/vsix-new-project.png similarity index 100% rename from doc/articles/Assets/quick-start/vsix-new-project.png rename to doc/articles/getting-started/Assets/quick-start/vsix-new-project.png diff --git a/doc/articles/Assets/quick-start/wasm-debugger-step-01.png b/doc/articles/getting-started/Assets/quick-start/wasm-debugger-step-01.png similarity index 100% rename from doc/articles/Assets/quick-start/wasm-debugger-step-01.png rename to doc/articles/getting-started/Assets/quick-start/wasm-debugger-step-01.png diff --git a/doc/articles/Assets/quick-start/wasm-debugger-step-02.png b/doc/articles/getting-started/Assets/quick-start/wasm-debugger-step-02.png similarity index 100% rename from doc/articles/Assets/quick-start/wasm-debugger-step-02.png rename to doc/articles/getting-started/Assets/quick-start/wasm-debugger-step-02.png diff --git a/doc/articles/Assets/quick-start/wasm-debugger-step-03.png b/doc/articles/getting-started/Assets/quick-start/wasm-debugger-step-03.png similarity index 100% rename from doc/articles/Assets/quick-start/wasm-debugger-step-03.png rename to doc/articles/getting-started/Assets/quick-start/wasm-debugger-step-03.png diff --git a/doc/articles/Assets/quick-start/wasm-debugging-iis-express.png b/doc/articles/getting-started/Assets/quick-start/wasm-debugging-iis-express.png similarity index 100% rename from doc/articles/Assets/quick-start/wasm-debugging-iis-express.png rename to doc/articles/getting-started/Assets/quick-start/wasm-debugging-iis-express.png diff --git a/doc/articles/Assets/quick-start/xaml-intellisense.png b/doc/articles/getting-started/Assets/quick-start/xaml-intellisense.png similarity index 100% rename from doc/articles/Assets/quick-start/xaml-intellisense.png rename to doc/articles/getting-started/Assets/quick-start/xaml-intellisense.png diff --git a/doc/articles/Assets/quick-start/xcode-version-warning.jpg b/doc/articles/getting-started/Assets/quick-start/xcode-version-warning.jpg similarity index 100% rename from doc/articles/Assets/quick-start/xcode-version-warning.jpg rename to doc/articles/getting-started/Assets/quick-start/xcode-version-warning.jpg diff --git a/doc/articles/Assets/tutorial01/configure-new-unoplatform-app.PNG b/doc/articles/getting-started/Assets/tutorial01/configure-new-unoplatform-app.PNG similarity index 100% rename from doc/articles/Assets/tutorial01/configure-new-unoplatform-app.PNG rename to doc/articles/getting-started/Assets/tutorial01/configure-new-unoplatform-app.PNG diff --git a/doc/articles/Assets/tutorial01/create-models-folder.png b/doc/articles/getting-started/Assets/tutorial01/create-models-folder.png similarity index 100% rename from doc/articles/Assets/tutorial01/create-models-folder.png rename to doc/articles/getting-started/Assets/tutorial01/create-models-folder.png diff --git a/doc/articles/Assets/tutorial01/install-community-toolkit.PNG b/doc/articles/getting-started/Assets/tutorial01/install-community-toolkit.PNG similarity index 100% rename from doc/articles/Assets/tutorial01/install-community-toolkit.PNG rename to doc/articles/getting-started/Assets/tutorial01/install-community-toolkit.PNG diff --git a/doc/articles/Assets/tutorial01/manage-extensions.png b/doc/articles/getting-started/Assets/tutorial01/manage-extensions.png similarity index 100% rename from doc/articles/Assets/tutorial01/manage-extensions.png rename to doc/articles/getting-started/Assets/tutorial01/manage-extensions.png diff --git a/doc/articles/Assets/tutorial01/newproject1.PNG b/doc/articles/getting-started/Assets/tutorial01/newproject1.PNG similarity index 100% rename from doc/articles/Assets/tutorial01/newproject1.PNG rename to doc/articles/getting-started/Assets/tutorial01/newproject1.PNG diff --git a/doc/articles/Assets/tutorial01/newproject2.PNG b/doc/articles/getting-started/Assets/tutorial01/newproject2.PNG similarity index 100% rename from doc/articles/Assets/tutorial01/newproject2.PNG rename to doc/articles/getting-started/Assets/tutorial01/newproject2.PNG diff --git a/doc/articles/Assets/tutorial01/newproject3.PNG b/doc/articles/getting-started/Assets/tutorial01/newproject3.PNG similarity index 100% rename from doc/articles/Assets/tutorial01/newproject3.PNG rename to doc/articles/getting-started/Assets/tutorial01/newproject3.PNG diff --git a/doc/articles/Assets/tutorial01/uno-extensions.PNG b/doc/articles/getting-started/Assets/tutorial01/uno-extensions.PNG similarity index 100% rename from doc/articles/Assets/tutorial01/uno-extensions.PNG rename to doc/articles/getting-started/Assets/tutorial01/uno-extensions.PNG diff --git a/doc/articles/Assets/tutorial01/vsix-new-project-options.png b/doc/articles/getting-started/Assets/tutorial01/vsix-new-project-options.png similarity index 100% rename from doc/articles/Assets/tutorial01/vsix-new-project-options.png rename to doc/articles/getting-started/Assets/tutorial01/vsix-new-project-options.png diff --git a/doc/articles/Assets/uno-settings-notification.png b/doc/articles/getting-started/Assets/uno-settings-notification.png similarity index 100% rename from doc/articles/Assets/uno-settings-notification.png rename to doc/articles/getting-started/Assets/uno-settings-notification.png diff --git a/doc/articles/get-started-licensing.md b/doc/articles/getting-started/get-started-licensing.md similarity index 100% rename from doc/articles/get-started-licensing.md rename to doc/articles/getting-started/get-started-licensing.md diff --git a/doc/articles/includes/clean-architecture-principles-inline.md b/doc/articles/includes/clean-architecture-principles-inline.md new file mode 100644 index 000000000000..088dbeaeeed0 --- /dev/null +++ b/doc/articles/includes/clean-architecture-principles-inline.md @@ -0,0 +1,2 @@ + +[Clean Architecture principles](https://devblogs.microsoft.com/ise/next-level-clean-architecture-boilerplate) diff --git a/doc/articles/includes/use-uno-check-inline-windows-noheader.md b/doc/articles/includes/use-uno-check-inline-windows-noheader.md index 85c10aa81628..e8f43ec9f746 100644 --- a/doc/articles/includes/use-uno-check-inline-windows-noheader.md +++ b/doc/articles/includes/use-uno-check-inline-windows-noheader.md @@ -1,3 +1,6 @@ +--- +uid: Uno.uno-check-inline.Windows +--- 1. Open a command-line prompt, Windows Terminal if you have it installed, or else Command Prompt or Windows Powershell from the Start menu. 1. Setup uno.check by: diff --git a/doc/articles/toc.yml b/doc/articles/toc.yml index e67251dbc9ee..3a86d70f6a79 100644 --- a/doc/articles/toc.yml +++ b/doc/articles/toc.yml @@ -68,6 +68,8 @@ href: xref:Uno.Development.Troubleshooting - name: Build error codes href: xref:Build.Solution.error-codes + - name: Troubleshooting source generation + href: xref:Uno.Development.Troubleshooting.SourceGeneration - name: Samples & Tutorials topicHref: xref:Uno.SamplesTutorials.Overview @@ -155,21 +157,26 @@ - name: Architecture items: - name: Supported Platforms - href: getting-started/requirements.md - - name: .NET Version Support - href: net-version-support.md + href: xref:Uno.GettingStarted.Requirements + items: + - name: .NET Versions + href: net-version-support.md + - name: Working with Skia Desktop + href: xref:Uno.Skia.Desktop + - name: Working with the Linux Framebuffer + href: features/using-linux-framebuffer.md - name: Philosophy - href: concepts/overview/philosophy-of-uno.md + href: xref:Uno.Overview.Philosophy - name: How Uno Works - href: how-uno-works.md + href: xref:Uno.Development.HowItWorks + - name: Best practices + href: xref:Uno.Development.BestPractices - name: UI Renderers items: - name: Skia Renderer href: xref:uno.features.renderer.skia - name: Native Renderer href: xref:uno.features.renderer.native - - name: Best Practices - href: best-practices-uno.md - name: Authoring items: @@ -209,7 +216,7 @@ - name: How to create a repro sample href: uno-howto-create-a-repro.md - name: 'Debugging C# on WASM' - href: debugging-wasm.md + href: xref:Uno.Development.DebuggingWasm - name: VS Code Advanced Mobile Debugging href: xref:uno.vscode.mobile.advanced.debugging - name: Generic Unhandled Exceptions handler @@ -220,9 +227,9 @@ - name: Embedding items: - name: Uno Platform in WPF - href: guides/uno-islands.md - - name: Native Views - href: native-views.md + href: xref:Uno.Tutorials.UnoIslands + - name: Native Views with Mobile + href: xref:Uno.Development.NativeViews - name: Native Views with Skia href: xref:Uno.Skia.Embedding.Native @@ -325,87 +332,88 @@ - name: Contributing items: - name: Overview - href: uno-development/contributing-intro.md + href: xref:Uno.Contributing.Intro - name: Code of Conduct href: https://github.com/unoplatform/uno/blob/master/CODE_OF_CONDUCT.md - name: Ways to contribute - href: uno-development/ways-to-contribute.md + href: xref:Uno.Contributing.WaysToContribute - name: How Uno works items: - name: Overview - href: uno-development/uno-internals-overview.md + href: xref:Uno.Contributing.Overview - name: Android - href: uno-development/uno-internals-android.md + href: xref:Uno.Contributing.Android - name: Layouting in Android - href: uno-development/Uno-UI-Layouting-Android.md + href: Uno.Contributing.Layouting.Android - name: iOS - href: uno-development/uno-internals-ios.md + href: Uno.Contributing.iOS - name: Layouting in iOS - href: uno-development/Uno-UI-Layouting-iOS.md + href: xref:Uno.Contributing.Layouting.iOS - name: WASM - href: uno-development/uno-internals-wasm.md + href: xref:Uno.Contributing.Wasm - name: macOS - href: uno-development/uno-internals-macos.md + href: xref:Uno.Contributing.macOS - name: DependencyProperty backing generator - href: uno-development/Internal-DependencyProperty-Generator.md + href: xref:Uno.Contributing.DependencyPropertyGenerator - name: x:Bind in Uno Platform - href: uno-development/Uno-UI-xBind-architecture.md + href: xref:Uno.Contributing.xBind - name: ListViewBase - href: uno-development/listviewbase-internals.md + href: xref:Uno.Contributing.ListViewBase - name: ThemeResource - href: uno-development/themeresource-internals.md + href: xref:Uno.Contributing.ThemeResource - name: InteractionTracker internals - href: uno-development/interaction-tracker-internals.md - - name: Building Uno.UI - href: uno-development/building-uno-ui.md - - name: Debugging Uno.UI - href: uno-development/debugging-uno-ui.md - - name: Using Codespaces - href: features/working-with-codespaces.md - - name: Using Gitpod - href: features/working-with-gitpod.md - - name: Inspecting the visual tree - href: uno-development/debugging-inspect-visual-tree.md - - name: Guidelines for code style - href: contributing/guidelines/code-style.md - - name: Using the SamplesApp - href: uno-development/working-with-the-samples-apps.md + href: xref:Uno.Contributing.InteractionTracker + - name: Guidelines for Contributing Documentation + items: + - name: Adding documentation + href: xref:Uno.Contributing.Docs + - name: DocFX + href: xref:Uno.Contributing.docfx + - name: Anchor Links in Documentation + href: xref:Uno.Contributing.Documentation.Anchor-links + - name: Contributing to Uno.UI + topicHref: xref:Uno.Contributing.BuildingUno + items: + - name: Building Uno.UI + href: xref:Uno.Contributing.BuildingUno + - name: Debugging Uno.UI + href: xref:Uno.Contributing.DebuggingUno + - name: Building Uno.UI for macOS using Visual Studio for Mac + href: xref:Uno.Contributing.BuildingUno.macOS + - name: Guidelines for code style + href: xref:Uno.Contributing.CodeStyle + - name: Git + href: xref:Uno.Contributing.Source-Control + items: + - name: Source Control Overview + href: xref:Uno.Contributing.Source-Control + - name: Using Codespaces + href: xref:Uno.Features.Codespaces + - name: Using Gitpod + href: xref:Uno.Features.Gitpod - name: Guidelines for creating tests + href: xref:Uno.Contributing.Tests.CreatingTests items: - name: Overview - href: contributing/guidelines/creating-tests.md + href: xref:Uno.Contributing.Tests.CreatingTests - name: Mocked unit tests (Uno.UI.Tests) - href: uno-development/creating-mocked-tests.md + href: xref:Uno.Contributing.Tests.Creating-mocked-tests.md - name: Platform-runtime unit tests (Uno.UI.RuntimeTests) - href: uno-development/creating-runtime-tests.md + href: xref:Uno.Contributing.Tests.CreateRuntimeTests - name: UI tests with Uno.UITest - href: uno-development/creating-ui-tests.md - - name: Debugging Solution Templates - href: uno-development/debugging-templates.md - - name: Conventional Commits format - href: uno-development/git-conventional-commits.md - - name: Guidelines for pull-requests - href: contributing/guidelines/pull-requests.md - - name: Guidelines for breaking changes - href: contributing/guidelines/breaking-changes.md - - name: Guidelines for updating dependencies - href: contributing/guidelines/updating-dependencies.md - - name: Guidelines for issue triage - href: contributing/guidelines/issue-triage.md + href: xref:Uno.Contributing.Tests.CreateUITests + - name: Testing PowerShell Scripts with Pester + href: Uno.Contributing.Tests.PowerShell-Pester-Tests + - name: Using the SamplesApp + href: xref:Uno.Contributing.SamplesApp + - name: Inspecting the visual tree + href: xref:Uno.Contributing.InspectVisualTree - name: Guidelines for implementing a new WinUI/WinRT feature - href: contributing/guidelines/implementing-a-new-winui-winrt-feature.md - - name: Adding documentation - href: uno-development/doc-on-docs.md - - name: DocFX - href: uno-development/docfx.md - - name: Uno.UI release procedure - href: uno-development/release-procedure.md - - name: Build Artifacts - href: contributing/build-artifacts.md + href: xref:Uno.Contributing.ImplementWinUIWinRT-API - name: Advanced topics items: - name: Adding functionality with API extensions - href: uno-development/api-extensions.md + href: xref:Uno.Contributing.ApiExtensions - name: The WeakEventHelper class href: uno-development/Internal-WeakEventHelper.md - name: Debugging Uno.UI Java code with Android studio @@ -418,6 +426,18 @@ href: uno-development/Uno-UI-XAML-ResourceTrimming.md - name: Hot Reload internals href: xref:Uno.Contributing.Internals.HotReload + - name: Guidelines for updating dependencies + href: xref:Uno.Contributing.UpdatingDependencies + - name: Breaking changes + href: xref:Uno.Contributing.BreakingChanges + - name: Release Procedure + href: xref:Uno.Contributing.ReleaseProcedure + - name: Build Artifacts + href: xref:Uno.Contributing.BuildArtifacts + - name: Guidelines for issue triage + href: xref:Uno.Contributing.IssueTriage + - name: Debugging Solution Templates + href: xref:Uno.Contributing.DebuggingTemplates - name: Why use Uno Platform? href: xref:Uno.Overview.WhyUno - name: FAQ @@ -731,8 +751,8 @@ - name: Templates items: - name: Visual Studio Wizard - href: getting-started/wizard/using-wizard.md + href: Uno.GettingStarted.UsingWizard - name: dotnet new Templates - href: get-started-dotnet-new.md + href: xref:Uno.GetStarted.dotnet-new - name: Get started wizard href: xref:Uno.GetStarted.Wizard diff --git a/doc/articles/Uno-UI-Performance.md b/doc/articles/uno-development/Uno-UI-Performance.md similarity index 100% rename from doc/articles/Uno-UI-Performance.md rename to doc/articles/uno-development/Uno-UI-Performance.md diff --git a/doc/articles/uno-development/Uno-UI-XAML-ResourceTrimming.md b/doc/articles/uno-development/Uno-UI-XAML-ResourceTrimming.md index b73167dadaa5..9f9fdf402a0e 100644 --- a/doc/articles/uno-development/Uno-UI-XAML-ResourceTrimming.md +++ b/doc/articles/uno-development/Uno-UI-XAML-ResourceTrimming.md @@ -4,7 +4,7 @@ uid: Uno.Contributing.XamlResourceTrimming # XAML Resource Trimming -This document provides technical details about the [XAML Resource trimming phase](../features/resources-trimming.md). +This document provides technical details about the [XAML Resource trimming phase](xref:Uno.Features.ResourcesTrimming). ## Technical Details @@ -35,7 +35,7 @@ As of Uno 3.9, the Uno.UI WebAssembly assembly is 7.5MB, trimmed down to 3.1MB f ## Using the `AdditionalLinkerHintAttribute` attribute -In some scenarios (e.g. ExpandoObject), it may be needed to generate linker hints for non-DependencyObject types. +In some scenarios (e.g. [ExpandoObject](https://learn.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject?view=net-9.0)), it may be needed to generate linker hints for non-DependencyObject types. To get a `__LinkerHints` property for an additional type, add the following in AssemblyInfo.cs: diff --git a/doc/articles/android-activities.md b/doc/articles/uno-development/android-activities.md similarity index 100% rename from doc/articles/android-activities.md rename to doc/articles/uno-development/android-activities.md diff --git a/doc/articles/composition.md b/doc/articles/uno-development/composition.md similarity index 100% rename from doc/articles/composition.md rename to doc/articles/uno-development/composition.md diff --git a/doc/articles/uno-development/debugging-inspect-visual-tree.md b/doc/articles/uno-development/debugging-inspect-visual-tree.md index 0b271f3ba3ea..0d9a3cfabec9 100644 --- a/doc/articles/uno-development/debugging-inspect-visual-tree.md +++ b/doc/articles/uno-development/debugging-inspect-visual-tree.md @@ -1,20 +1,24 @@ --- uid: Uno.Contributing.InspectVisualTree --- + + # Inspecting the runtime visual tree of an Uno app Often the first step in debugging a UI bug is to scrutinize the application's visual tree. The visual tree is derived from the app's layout defined in XAML, but there's not a straightforward 1-to-1 mapping from XAML to runtime visual tree, due to templating, view manipulation in code, etc. Also, by definition if you're getting a UI bug then there's a discrepancy between what you expect based on the XAML and code and the behavior you're actually observing. Don't live in suspense – check the visual tree! -Tools for inspecting the visual tree differ by platform. +## Inspection Tools per Platform -## UWP +Tools for inspecting the visual tree differ by platform: -UWP has by far the easiest and most convenient experience for debugging the visual tree. The small black toolbar at the top center of your app during debugging enable buttons to go to the Live Visual Tree view, directly select a visual element for inspection, and show layouting decorations. The complement to the Live Visual Tree is the Live Property Explorer, which allows you to inspect current values for any property of a view, and even change some of them on the fly. +# [UWP and WinUI](#tab/uwp-winui) + +UWP and WinUI having by far the easiest and most convenient experience for debugging the visual tree. The small black toolbar at the top center of your app during debugging enable buttons to go to the Live Visual Tree view, directly select a visual element for inspection, and show layouting decorations. The complement to the Live Visual Tree is the Live Property Explorer, which allows you to inspect current values for any property of a view, and even change some of them on the fly. ![UWP Live Visual Tree](assets/debugging-inspect-visual-tree/UWP-Live-Visual-Tree.jpg) -## Android +# [Android](#tab/android) There are a couple of options for viewing the visual tree of an Uno app running on Android. @@ -26,7 +30,7 @@ The other approach is to use the [Stetho package](https://www.nuget.org/packages Unfortunately neither of these approaches give you an easy way to inspect properties defined on UIElement, FrameworkElement, and other managed types. You can however look at native properties to obtain information like layout size, opacity, etc. -## iOS +# [iOS](#tab/ios) In principle it's possible to use Xcode's 'Debug View Hierarchy' feature on any iOS app, including Uno apps. The steps are the following: @@ -34,12 +38,12 @@ In principle it's possible to use Xcode's 'Debug View Hierarchy' feature on any 2. Create a dummy iOS app (or open an existing one) - you won't actually run this app. 3. Run the app whose layout you wish to inspect. 4. Set the device or simulator you're using as the active device in the upper toolbar. -5. Select Debug -> Attach to Process -> [name of the app] +5. Select Debug -> Attach to Process -> `[name of the app]` 6. Once the debugger has successfully attached, select Debug -> View Debugging -> Capture View Hierarchy. In practice, Xcode is somewhat temperamental, and this approach may fail for some apps. It's recommended to fall back on the breakpoint-based inspection method described below. -## Web +# [Web](#tab/web) For an Uno.WASM app you can simply use the layout inspection tools built into whatever browser you're using. For example, for Chrome, open the 'Developer tools' panel (`F12`) and select the 'Elements' tab, or just right-click any element in the visual tree and choose 'Inspect.' @@ -58,13 +62,15 @@ You can configure Uno to annotate the DOM with the values of common XAML propert **Note:** for performance reasons, if a _release build_ of Uno.UI is used, `AssignDOMXamlProperties` will only display the values of properties as they were when the element was loaded - that is, they may be stale in some cases. If a _debug build_ of Uno.UI is used, this limitation is lifted and the DOM annotation will reflect the most up-to-date values. +--- + ## Retrieving the visual tree through code or at a breakpoint (Android/iOS/WebAssembly/macOS) It's common enough when debugging Uno to be at a breakpoint and want to quickly know exactly where the view is in the visual tree, that we added a helper method. -If you're using a debug build of Uno, this is directly available on UIElement as the `public string ShowLocalVisualTree(int fromHeight)` method (for ease of use in the watch window). If you're using the release version of Uno, the same method is available as an extension in UIKit.UIViewExtensions for iOS or Uno.UI.ViewExtensions for Android. +If you're using a debug build of Uno, this is directly available on UIElement as the `public string ShowLocalVisualTree(int fromHeight)` method (for ease of use in the watch window). If you're using the release version of Uno, the same method is available as an extension in `UIKit.UIViewExtensions` for iOS or `Uno.UI.ViewExtensions` for Android. -The method returns the visual tree from a certain 'height' above the target element as an indented string. So if you call ShowLocalVisualTree(2), you'll get the visual subtree from the target element's grandparent down. If you call ShowLocalVisualTree(100), you'll almost certainly get the entire visual tree starting from the root element. The original target is picked out with an asterisk (*) so you can find it. +The method returns the visual tree from a certain 'height' above the target element as an indented string. So if you call `ShowLocalVisualTree(2)`, you'll get the visual subtree from the target element's grandparent down. If you call `ShowLocalVisualTree(100)`, you'll almost certainly get the entire visual tree starting from the root element. The original target is picked out with an asterisk (*) so you can find it. ![ShowLocalVisualTree() on iOS](assets/debugging-inspect-visual-tree/iOS-ShowLocalVisualTree.jpg) @@ -88,7 +94,7 @@ The advantage of this over `ShowLocalVisualTree` is the ability to customize the > For more examples of control details, check out these source files: > > - [`DebugVTNode\GetDetails()` method in Toolkit](https://github.com/unoplatform/uno.toolkit.ui/blob/main/src/Uno.Toolkit.UI/Helpers/VisualTreeHelperEx.cs) -> - [`DescribeVTNode\GetDetails()` method in Uno](https://github.com/unoplatform/uno/blob/master/src/Uno.UI/Extensions/ViewExtensions.visual-tree.cs) +> - [`DescribeVTNode\GetDetails()` method in Uno](../../../src/Uno.UI/Extensions/ViewExtensions.visual-tree.cs) ```csharp var tree = this.TreeGraph(Describe); diff --git a/doc/articles/debugging-wasm.md b/doc/articles/uno-development/debugging-wasm.md similarity index 89% rename from doc/articles/debugging-wasm.md rename to doc/articles/uno-development/debugging-wasm.md index f53e136a6524..2a078fb6a43f 100644 --- a/doc/articles/debugging-wasm.md +++ b/doc/articles/uno-development/debugging-wasm.md @@ -13,7 +13,7 @@ There are two ways to debug a WebAssembly application: Here’s what you need to do to debug an Uno Platform application in Visual Studio (2022 17.1 or later): -- Install the latest [Uno Platform Visual Studio templates](./get-started-vs-2022.md#install-the-solution-templates) +- Install the latest [Uno Platform Visual Studio Extension](getting-started/get-started-vs-2022.md#install-the-uno-platform-extension) - Have Chrome or Edge (Chromium based) - In the NuGet Package Manager, update `Uno.Wasm.Bootstrap` and `Uno.Wasm.Bootstrap.DevServer` 8.0.0 or later - Ensure that `true` is set in your csproj. It is automatically set [when using the Uno.SDK](xref:Uno.Features.Uno.Sdk). @@ -48,16 +48,16 @@ To debug your application: - Select **MyApp (WebAssembly IIS Express)** as the debugging target - Select **Chrome** or **Microsoft Edge** as the Web Browser - Make sure script debugging is disabled
- ![IIS express settings](Assets/quick-start/wasm-debugging-iis-express.png) + ![IIS express settings](getting-started/Assets/quick-start/wasm-debugging-iis-express.png) - Start the debugging session using CtrlF5 or _Debug_ > _Start Without Debugging_ from the menu, (F5 will work, but the debugging experience won't be in Visual Studio) - Once your application has started, press AltShiftD (in Chrome, on your application's tab) - A new tab will open with the debugger or instructions to activate it -![Debugger - New tab with instructions to activate it](Assets/quick-start/wasm-debugger-step-01.png) +![Debugger - New tab with instructions to activate it](getting-started/Assets/quick-start/wasm-debugger-step-01.png) - You will now get the Chrome DevTools to open listing all the .NET loaded assemblies on the Sources tab:
-![Debugger - Chrome DevTools listing all the .NET loaded assemblies on the Sources tab](Assets/quick-start/wasm-debugger-step-02.png) +![Debugger - Chrome DevTools listing all the .NET loaded assemblies on the Sources tab](getting-started/Assets/quick-start/wasm-debugger-step-02.png) - You may need to refresh the original tab if you want to debug the entry point (Main) of your application.
-![Debugger - The smaller refresh button location in the preview section of the Chrome DevTools](Assets/quick-start/wasm-debugger-step-03.png) +![Debugger - The smaller refresh button location in the preview section of the Chrome DevTools](getting-started/Assets/quick-start/wasm-debugger-step-03.png) > ### Tips for debugging in Chrome > diff --git a/doc/articles/uno-development/docfx.md b/doc/articles/uno-development/docfx.md deleted file mode 100644 index 8d16b8686265..000000000000 --- a/doc/articles/uno-development/docfx.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -uid: Uno.Contributing.DocFx ---- - - - -# The Uno docs website and DocFX - -Uno Platform's docs website uses [DocFX](https://dotnet.github.io/docfx/) to convert Markdown files in the [articles folder](https://github.com/unoplatform/uno/tree/master/doc/articles) into [html files](xref:Uno.Documentation.Intro). - -## Adding to the table of contents - -Normally when you add a new doc file, you also add it to [articles/toc.yml](https://github.com/unoplatform/uno/blob/master/doc/articles/toc.yml). This allows it to show up in the left sidebar Table of Contents on the docs website. - -## DocFX-flavored Markdown - -DocFX supports extended Markdown syntaxes that are treated specially when converting to html. - -### Formatted blockquotes - -You can declare a [specially-styled blockquote](https://dotnet.github.io/docfx/spec/docfx_flavored_markdown.html#note-warningtipimportant) like so: - -```md -> [!NOTE] -> This is a Note, showing how to declare notes. -``` - -This is how it looks when converted to .html: - -> [!NOTE] -> This is a Note, showing how to declare notes. - -Use pre-formatted blockquotes when you want to call special attention to particular information. - -The following note types are supported: - -```md -> [!NOTE] -> ... - -> [!TIP] -> ... - -> [!WARNING] -> ... - -> [!IMPORTANT] -> ... - -> [!CAUTION] -> ... - -``` - -### Tabs - -DocFX can generate tabs. Make sure to follow the [syntax specification](https://dotnet.github.io/docfx/spec/docfx_flavored_markdown.html#tabbed-content) precisely. - -#### Example - -Markdown: - -```md -# [WinUI](#tab/tabid-1) - -`WinUI.Namespace` - -# [Uno Platform](#tab/tabid-2) - -`Uno.Namespace` - ---- -``` - -Html output: - -# [WinUI](#tab/tabid-1) - -`WinUI.Namespace` - -# [Uno Platform](#tab/tabid-2) - -`Uno.Namespace` - ---- - -### TOC checker script - -The [`check_toc` script](https://github.com/unoplatform/uno/blob/master/doc/articles/check_toc.ps1) checks for dead links in the TOC, as well as Markdown files in the 'articles' folder that are not part of the TOC. At the moment it's not part of the CI, but contributors can run it locally and fix any bad or missing links. - - - -## Building docs website locally with DocFX - -Sometimes you may want to run DocFX locally to validate that changes you've made look good in html. To do so you'll first need to generate the 'implemented views' documentation. - -### Run DocFX locally - -To run DocFX locally and check the resulting html: - -1. Open the `Uno.UI-Tools.slnf` solution filter in the `src` folder with Visual Studio. -2. Edit the properties of the `Uno.UwpSyncGenerator` project. Under the 'Debug' tab, set Application arguments to "doc". -3. Set `Uno.UwpSyncGenerator` as startup project and run it. It may fail to generate the full implemented views content; if so, it should still nonetheless generate stubs so that DocFX can run successfully. -4. Navigate to `%USERPROFILE%\.nuget\packages\docfx.console`. If you don't see the DocFX package in your NuGet cache, go back to ``Uno.UI-Tools.slnf`, right-click on the solution and choose 'Restore NuGet Packages.' -5. Open the latest DocFX version and open the `tools` folder. -6. Open a Powershell window in the `tools` folder. -7. Run the following command: `.\docfx "C:\src\Uno.UI\doc\docfx.json" -o C:\src\Uno.UI\docs-local-dist`, replacing `C:\src\Uno.UI` with your local path to the Uno.UI repository. -8. When DocFX runs successfully, it will create the html output at `C:\src\Uno.UI\docs-local-dist\_site`, which you can now view or mount on a local server. - -### Use a local server - -You can use `dotnet-serve` as a simple command-line HTTP server for example. - -1. Install `dotnet-serve` using the following command: `dotnet tool install --global dotnet-serve`. For more info about its usage and options, -[please refer to the documentation](https://github.com/natemcmaster/dotnet-serve). -2. Using the command prompt, navigate to `C:\src\Uno.UI\docs-local-dist\_site` (replacing `C:\src\Uno.UI` with your local path to the Uno.UI repository) and run the following command `dotnet serve -o -S`. This will start a simple server with HTTPS and open the browser directly. - -## Run the documentation generation performance test - -If needed, you can also run a script that will give you a performance summary for the documentation generation. - -To run the script on Windows: - -1. Make sure `crosstargeting_override.props` is not defining UnoTargetFrameworkOverride -2. Open a Developer Command Prompt for Visual Studio (2019 or 2022) -3. Go to the uno\build folder (not the uno\src\build folder) -4. Run the `run-doc-generation.cmd` script; make sure to follow the instructions diff --git a/doc/articles/uno-development/interaction-tracker-internals.md b/doc/articles/uno-development/interaction-tracker-internals.md index 8af44ef1427c..80e0a791d780 100644 --- a/doc/articles/uno-development/interaction-tracker-internals.md +++ b/doc/articles/uno-development/interaction-tracker-internals.md @@ -1,3 +1,6 @@ +--- +uid: Uno.Contributing.InteractionTracker +--- # InteractionTracker internals This document tries to detail and clarify the implementation of InteractionTracker. diff --git a/doc/articles/native-styles.md b/doc/articles/uno-development/native-styles.md similarity index 100% rename from doc/articles/native-styles.md rename to doc/articles/uno-development/native-styles.md diff --git a/doc/articles/native-views.md b/doc/articles/uno-development/native-views.md similarity index 100% rename from doc/articles/native-views.md rename to doc/articles/uno-development/native-views.md diff --git a/doc/articles/supported-libraries.md b/doc/articles/uno-development/supported-libraries.md similarity index 100% rename from doc/articles/supported-libraries.md rename to doc/articles/uno-development/supported-libraries.md diff --git a/doc/articles/uno-toolchain-telemetry.md b/doc/articles/uno-development/uno-toolchain-telemetry.md similarity index 100% rename from doc/articles/uno-toolchain-telemetry.md rename to doc/articles/uno-development/uno-toolchain-telemetry.md diff --git a/doc/index.md b/doc/index.md index 1d97ea1c01c0..b94c5c4fa69d 100644 --- a/doc/index.md +++ b/doc/index.md @@ -66,7 +66,7 @@ uid: front-page

How to contribute to the Uno Platform.

-[Learn more](articles/uno-development/debugging-uno-ui.md) +[Learn more](articles/contributing/guidelines/debugging-uno-ui.md) diff --git a/doc/templates/uno/service/search.js b/doc/templates/uno/service/search.js index 369e27332438..d7ddeece5db7 100644 --- a/doc/templates/uno/service/search.js +++ b/doc/templates/uno/service/search.js @@ -159,7 +159,7 @@ function enableSearch() { * This function posts the message to the worker if the string has at least * three characters. * - * @param worker The search worker used by DocFx (lunr) + * @param worker The search worker used by docfx (lunr) * @param searchQuery The string to post to the worker. */ function postSearchQuery(worker, searchQuery) { diff --git a/doc/templates/uno/styles/docfx.js.map b/doc/templates/uno/styles/docfx.js.map index ebef1a45a99c..71a4c0a3f8a5 100644 --- a/doc/templates/uno/styles/docfx.js.map +++ b/doc/templates/uno/styles/docfx.js.map @@ -1 +1 @@ -{"version":3,"sources":["constant.js","render.js","component/affix.js","component/alerts.js","component/breadcrumb.js","component/footer.js","component/links.js","component/navbar.js","component/sidebar.js","component/tab.js","component/tables.js","service/globalevents.js","service/search.js","service/utility.js"],"names":["active","expanded","filtered","show","hide","collapsed","Object","assign","$","fn","breakWord","workAroundFixedHeaderForAnchors","highlight","enableSearch","renderTables","renderAlerts","updateAlertHeightOnResize","renderLinks","renderSidebar","renderAffix","renderNavbar","renderLogo","updateLogo","updateLogoOnResize","updateTocHeightOnResize","updateSidenavTopOnResize","renderFooter","breakText","renderTabs","contributionDiv","hierarchy","$headers","map","h","join","stack","each","i","e","id","item","name","str","text","replace","href","items","length","frame","tagName","type","siblings","push","buildParent","childrenToAttach","pop","parentFrame","parent","child","topLevel","html","formList","empty","append","is","css","on","scrollspy","data","target","hash","activate","contribution","get","outerHTML","remove","setAlertHeight","maxHeight","Math","max","apply","this","outerHeight","window","addClass","renderBreadcrumb","breadcrumb","innerHTML","needFooter","document","height","scrollTop","resetBottomCss","removeClass","shiftUpBottomCss","fadeIn","fadeOut","attr","links","filter","hostname","location","initializeNavbar","navbar","querySelector","body","classList","contains","let","last_known_scroll_position","ticking","addEventListener","scrollY","requestAnimationFrame","add","unoMenuReq","XMLHttpRequest","$navbar","getElementById","wordpressMenuHasLoaded","open","onload","status","responseText","JSON","parse","trigger","onerror","send","ajaxComplete","event","xhr","settings","url","getElementsByClassName","className","curWidth","innerWidth","headerLogo","mobileLogo","URL","src","deskLogo","loadNavbar","navbarPath","tocPath","find","appendTo","index","lastIndexOf","navrel","substr","currentAbsPath","getAbsolutePath","pathname","isRelativePath","isActive","originalHref","getDirectory","parents","$img","jQuery","imgID","imgClass","imgURL","$svg","removeAttr","replaceWith","sidefilterHeight","setTocHeight","headerHeight","breadcrumbHeight","tocToggleHeight","sidenavPaddingTop","maxHeightToc","width","intViewportHeight","innerHeight","parseInt","setSidenavTop","sidenavTop","sidetocTop","articleMarginTopDesk","articleMarginTopMobile","sideToggleSideToc","footer","sidetoc","loadToc","load","tocrel","currentHref","searchResult","has","toggleClass","val","value","tocLineAnchor","j","anchor","parentNodes","k","parentText","children","toLowerCase","indexOf","top","position","contentAttrs","Tab","defineProperty","prototype","a","getAttribute","split","enumerable","configurable","li","hasAttribute","set","removeAttribute","setAttribute","section","tabIndex","focus","initTabs","container","queryStringTabs","qs","parseQueryString","t","tabs","undefined","elements","querySelectorAll","state","groups","selectedTabs","group","element","independent","firstElementChild","dataTab","tab","nextElementSibling","tabGroup","updateVisibilityAndSelection","handleClick","info","HTMLElement","closest","tabIds","parentElement","preventDefault","setTimeout","originalTop","getBoundingClientRect","_i","_a","selected","arraysIntersect","previousTabId","splice","_b","_c","updateTabsQueryStringParam","MouseEvent","scrollTo","pageYOffset","tabIds_1","tabId","dispatchEvent","CustomEvent","bubbles","anySelected","firstVisibleTab","visible","condition","_d","protocol","host","args","parts","name_1","hasOwnProperty","encodeURIComponent","history","replaceState","title","queryString","match","pl","decode","s","decodeURIComponent","search","urlParams","substring","exec","b","a_1","itemA","b_1","wrap","refresh","article","content","console","error","path","docsUrl","getElementsByTagName","includes","searchParam","slice","decodeURI","anchors","options","placement","icon","block","hljs","highlightBlock","range","lines","Number","found","start","end","isNaN","query","relHref","q","worker","Worker","webWorkerSearch","indexReady","Deferred","onmessage","oEvent","resolve","handleSearchResults","d","promise","done","postSearchQuery","localSearch","lunrIndex","lunr","ref","field","boost","tokenizer","seperator","searchData","searchDataRequest","indexPath","prop","hits","results","forEach","hit","keywords","autoCollapse","collapse","keyword","mark","searchQuery","key","off","postMessage","relativeUrlToAbsoluteUrl","currentUrl","relativeUrl","currentItems","relativeItems","depth","concat","itemHref","itemTitle","itemBrief","words","queryIndex","itemNode","itemTitleNode","itemBriefNode","word","isAbsolutePath","test","classes","level","getList","model","cls","l","breakPlainText","HISTORY_SUPPORT","pushState","ANCHOR_REGEX","scrollIfAnchor","pushToHistory","anchorOffset","rect","first","pageXOffset","scrollToCurrent","offset"],"mappings":"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","file":"docfx.js","sourcesContent":["const active = 'active';\r\nconst expanded = 'in';\r\nconst filtered = 'filtered';\r\nconst show = 'show';\r\nconst hide = 'hide';\r\nconst collapsed = 'collapsed';\r\n","// workaround for gulp-uglify changing order of execution on $.fn func assignments\r\nObject.assign($.fn, { breakWord });\r\n\r\nworkAroundFixedHeaderForAnchors();\r\nhighlight();\r\nenableSearch();\r\n\r\nrenderTables();\r\nrenderAlerts();\r\nupdateAlertHeightOnResize();\r\nrenderLinks();\r\nrenderSidebar();\r\nrenderAffix();\r\n\r\nrenderNavbar();\r\nrenderLogo();\r\nupdateLogo()\r\nupdateLogoOnResize();\r\nupdateTocHeightOnResize();\r\nupdateSidenavTopOnResize();\r\nrenderFooter();\r\nbreakText();\r\nrenderTabs();\r\nupdateLogo();\r\n","//Setup Affix\r\nfunction renderAffix() {\r\n const hierarchy = getHierarchy();\r\n\r\n if (hierarchy && hierarchy.length > 0) {\r\n let html = '
In This Article
'\r\n html += formList(hierarchy, ['nav', 'bs-docs-sidenav']);\r\n\r\n $(\"#affix\").empty().append(html);\r\n\r\n if ($('footer').is(':visible')) {\r\n $(\".sideaffix\").css(\"bottom\", \"70px\");\r\n }\r\n\r\n $('#affix a').on('click', function (e) {\r\n const scrollspy = $('[data-spy=\"scroll\"]').data()['bs.scrollspy'];\r\n const target = e.target.hash;\r\n if (scrollspy && target) {\r\n scrollspy.activate(target);\r\n }\r\n });\r\n\r\n const contribution = $('.contribution');\r\n const contributionDiv = contribution.get(0).outerHTML;\r\n contribution.remove();\r\n $('.sideaffix').append(contributionDiv);\r\n\r\n }\r\n\r\n function getHierarchy() {\r\n // supported headers are h1, h2, h3, and h4\r\n const $headers = $($.map(['h1', 'h2', 'h3', 'h4'], function (h) { return \".article article \" + h; }).join(\", \"));\r\n\r\n // a stack of hierarchy items that are currently being built\r\n const stack = [];\r\n $headers.each(function (i, e) {\r\n if (!e.id) {\r\n return;\r\n }\r\n\r\n const item = {\r\n name: htmlEncode($(e).text()),\r\n href: \"#\" + e.id,\r\n items: []\r\n };\r\n\r\n if (!stack.length) {\r\n stack.push({ type: e.tagName, siblings: [item] });\r\n return;\r\n }\r\n\r\n const frame = stack[stack.length - 1];\r\n if (e.tagName === frame.type) {\r\n frame.siblings.push(item);\r\n } else if (e.tagName[1] > frame.type[1]) {\r\n // we are looking at a child of the last element of frame.siblings.\r\n // push a frame onto the stack. After we've finished building this item's children,\r\n // we'll attach it as a child of the last element\r\n stack.push({ type: e.tagName, siblings: [item] });\r\n } else { // e.tagName[1] < frame.type[1]\r\n // we are looking at a sibling of an ancestor of the current item.\r\n // pop frames from the stack, building items as we go, until we reach the correct level at which to attach this item.\r\n while (e.tagName[1] < stack[stack.length - 1].type[1]) {\r\n buildParent();\r\n }\r\n if (e.tagName === stack[stack.length - 1].type) {\r\n stack[stack.length - 1].siblings.push(item);\r\n } else {\r\n stack.push({ type: e.tagName, siblings: [item] });\r\n }\r\n }\r\n });\r\n while (stack.length > 1) {\r\n buildParent();\r\n }\r\n\r\n function buildParent() {\r\n const childrenToAttach = stack.pop();\r\n const parentFrame = stack[stack.length - 1];\r\n const parent = parentFrame.siblings[parentFrame.siblings.length - 1];\r\n $.each(childrenToAttach.siblings, function (i, child) {\r\n parent.items.push(child);\r\n });\r\n }\r\n if (stack.length > 0) {\r\n\r\n const topLevel = stack.pop().siblings;\r\n if (topLevel.length === 1) { // if there's only one topmost header, dump it\r\n return topLevel[0].items;\r\n }\r\n return topLevel;\r\n }\r\n return undefined;\r\n }\r\n\r\n function htmlEncode(str) {\r\n if (!str) return str;\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''')\r\n .replace(//g, '>');\r\n }\r\n\r\n function htmlDecode(str) {\r\n if (!str) return str;\r\n return str\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/&/g, '&');\r\n }\r\n\r\n function cssEscape(str) {\r\n // see: http://stackoverflow.com/questions/2786538/need-to-escape-a-special-character-in-a-jquery-selector-string#answer-2837646\r\n if (!str) return str;\r\n return str\r\n .replace(/[!\"#$%&'()*+,.\\/:;<=>?@[\\\\\\]^`{|}~]/g, \"\\\\$&\");\r\n }\r\n}\r\n","// Styling for alerts.\r\nfunction setAlertHeight(){\r\n var maxHeight = Math.max.apply(null, $(\".col-md-6 div.alert\").map(function ()\r\n {\r\n return $(this).outerHeight();\r\n }).get());\r\n\r\n $('.alert').css('height', maxHeight);\r\n \r\n}\r\n\r\nfunction updateAlertHeightOnResize() {\r\n $(window).on('resize', function () {\r\n $('.alert').css('height', 'auto');\r\n setAlertHeight();\r\n });\r\n}\r\n\r\nfunction renderAlerts() {\r\n $('.NOTE, .TIP').addClass('alert alert-info');\r\n $('.WARNING').addClass('alert alert-warning');\r\n $('.IMPORTANT, .CAUTION').addClass('alert alert-danger');\r\n setAlertHeight();\r\n\r\n}\r\n","function renderBreadcrumb() {\r\n const breadcrumb = [];\r\n\r\n $('#navbar a.active').each(function (i, e) {\r\n breadcrumb.push({\r\n href: e.href,\r\n name: e.innerHTML\r\n });\r\n })\r\n $('#toc a.active').each(function (i, e) {\r\n breadcrumb.push({\r\n href: e.href,\r\n name: e.innerHTML\r\n });\r\n })\r\n\r\n const html = formList(breadcrumb, 'breadcrumb');\r\n $('#breadcrumb').html(html);\r\n}\r\n","// Show footer\r\nfunction renderFooter() {\r\n initFooter();\r\n $(window).on(\"scroll\", () => showFooterCore());\r\n\r\n function initFooter() {\r\n if (needFooter()) {\r\n shiftUpBottomCss();\r\n $(\"footer\").show();\r\n } else {\r\n resetBottomCss();\r\n $(\"footer\").hide();\r\n }\r\n }\r\n\r\n function showFooterCore() {\r\n if (needFooter()) {\r\n shiftUpBottomCss();\r\n $(\"footer\").fadeIn();\r\n } else {\r\n resetBottomCss();\r\n $(\"footer\").fadeOut();\r\n }\r\n }\r\n\r\n function needFooter() {\r\n const scrollHeight = $(document).height();\r\n const scrollPosition = $(window).height() + $(window).scrollTop();\r\n return (scrollHeight - scrollPosition) < 1;\r\n }\r\n\r\n function resetBottomCss() {\r\n $(\".sidetoc\").removeClass(\"shiftup\");\r\n $(\".sideaffix\").removeClass(\"shiftup\");\r\n }\r\n\r\n function shiftUpBottomCss() {\r\n $(\".sidetoc\").addClass(\"shiftup\");\r\n $(\".sideaffix\").addClass(\"shiftup\");\r\n }\r\n}\r\n","// Open links to different host in a new window.\r\nfunction renderLinks() {\r\n if ($(\"meta[property='docfx:newtab']\").attr(\"content\") === \"true\") {\r\n $(document.links).filter(function () {\r\n return this.hostname !== window.location.hostname;\r\n }).attr('target', '_blank');\r\n }\r\n}\r\n","/**\r\n * Load the navbar from the uno website\r\n */\r\nfunction initializeNavbar() {\r\n\r\n const navbar = document.querySelector(\"header > .navbar\");\r\n if (document.body.classList.contains(\"front-page\")) {\r\n let last_known_scroll_position = 0;\r\n let ticking = false;\r\n\r\n function doSomething(scroll_pos) {\r\n if (scroll_pos >= 100) navbar.classList.add(\"scrolled\");\r\n else navbar.classList.remove(\"scrolled\");\r\n }\r\n\r\n window.addEventListener(\"scroll\", function () {\r\n last_known_scroll_position = window.scrollY;\r\n\r\n if (!ticking) {\r\n window.requestAnimationFrame(function () {\r\n doSomething(last_known_scroll_position);\r\n ticking = false;\r\n });\r\n\r\n ticking = true;\r\n }\r\n });\r\n }\r\n\r\n const unoMenuReq = new XMLHttpRequest();\r\n const unoMenuEndpoint = \"https://platform.uno/wp-json/wp/v2/menu\";\r\n const $navbar = document.getElementById(\"navbar\");\r\n let wordpressMenuHasLoaded = false;\r\n\r\n unoMenuReq.open(\"get\", unoMenuEndpoint, true);\r\n\r\n if (typeof navbar !== \"undefined\") {\r\n unoMenuReq.onload = function () {\r\n if (unoMenuReq.status === 200 && unoMenuReq.responseText) {\r\n $navbar.innerHTML = JSON.parse(\r\n unoMenuReq.responseText\r\n );\r\n wordpressMenuHasLoaded = true;\r\n $(document).trigger(\"wordpressMenuHasLoaded\");\r\n }\r\n };\r\n unoMenuReq.onerror = function (e) {\r\n };\r\n unoMenuReq.send();\r\n }\r\n\r\n $(document).ajaxComplete(function (event, xhr, settings) {\r\n const docFxNavbarHasLoaded = settings.url === \"toc.html\";\r\n\r\n if (docFxNavbarHasLoaded && wordpressMenuHasLoaded) {\r\n const $docfxNavbar = $navbar.getElementsByClassName(\"navbar-nav\");\r\n $docfxNavbar[0].className += \" hidden\";\r\n\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Changes the logo on resize\r\n*/\r\n\r\nfunction updateLogo() {\r\n const curWidth = window.innerWidth;\r\n const headerLogo = document.getElementById('logo');\r\n if (curWidth < 1024) {\r\n const mobileLogo = new URL('UnoLogoSmall.png', headerLogo.src).href;\r\n headerLogo.src = mobileLogo;\r\n } else {\r\n const deskLogo = new URL('uno-logo.svg', headerLogo.src).href;\r\n headerLogo.src = deskLogo;\r\n }\r\n}\r\n\r\nfunction updateLogoOnResize() {\r\n $(window).on('resize', function () {\r\n updateLogo();\r\n });\r\n}\r\n\r\n\r\n// Update href in navbar\r\nfunction renderNavbar() {\r\n const navbar = $('#navbar ul')[0];\r\n if (typeof (navbar) === 'undefined') {\r\n loadNavbar();\r\n } else {\r\n $('#navbar ul a.active').parents('li').addClass(active);\r\n renderBreadcrumb();\r\n }\r\n\r\n function loadNavbar() {\r\n let navbarPath = $(\"meta[property='docfx\\\\:navrel']\").attr(\"content\");\r\n if (!navbarPath) {\r\n return;\r\n }\r\n navbarPath = navbarPath.replace(/\\\\/g, '/');\r\n let tocPath = $(\"meta[property='docfx\\\\:tocrel']\").attr(\"content\") || '';\r\n if (tocPath) tocPath = tocPath.replace(/\\\\/g, '/');\r\n $.get(navbarPath, function (data) {\r\n $(data).find(\"#toc>ul\").appendTo(\"#navbar\");\r\n const index = navbarPath.lastIndexOf('/');\r\n let navrel = '';\r\n if (index > -1) {\r\n navrel = navbarPath.substr(0, index + 1);\r\n }\r\n $('#navbar>ul').addClass('navbar-nav');\r\n\r\n const currentAbsPath = getAbsolutePath(window.location.pathname);\r\n\r\n // set active item\r\n $('#navbar').find('a[href]').each(function (i, e) {\r\n let href = $(e).attr(\"href\");\r\n if (isRelativePath(href)) {\r\n href = navrel + href;\r\n $(e).attr(\"href\", href);\r\n\r\n // TODO: currently only support one level navbar\r\n let isActive = false;\r\n let originalHref = e.name;\r\n if (originalHref) {\r\n originalHref = navrel + originalHref;\r\n if (getDirectory(getAbsolutePath(originalHref)) === getDirectory(getAbsolutePath(tocPath))) {\r\n isActive = true;\r\n }\r\n } else {\r\n if (getAbsolutePath(href) === currentAbsPath) {\r\n\r\n const dropdown = $(e).attr('data-toggle') === \"dropdown\";\r\n\r\n if (!dropdown) {\r\n isActive = true;\r\n }\r\n }\r\n }\r\n if (isActive) {\r\n $(e).addClass(active);\r\n }\r\n }\r\n });\r\n renderNavbar();\r\n });\r\n }\r\n}\r\n\r\nfunction renderLogo() {\r\n // For LOGO SVG\r\n // Replace SVG with inline SVG\r\n // http://stackoverflow.com/questions/11978995/how-to-change-color-of-svg-image-using-css-jquery-svg-image-replacement\r\n $('img.svg').each(function () {\r\n const $img = jQuery(this);\r\n const imgID = $img.attr('id');\r\n const imgClass = $img.attr('class');\r\n const imgURL = $img.attr('src');\r\n\r\n jQuery.get(imgURL, function (data) {\r\n // Get the SVG tag, ignore the rest\r\n let $svg = $(data).find('svg');\r\n\r\n // Add replaced image's ID to the new SVG\r\n if (typeof imgID !== 'undefined') {\r\n $svg = $svg.attr('id', imgID);\r\n }\r\n // Add replaced image's classes to the new SVG\r\n if (typeof imgClass !== 'undefined') {\r\n $svg = $svg.attr('class', imgClass + ' replaced-svg');\r\n }\r\n\r\n // Remove any invalid XML tags as per http://validator.w3.org\r\n $svg = $svg.removeAttr('xmlns:a');\r\n\r\n // Replace image with new SVG\r\n $img.replaceWith($svg);\r\n\r\n }, 'xml');\r\n });\r\n}\r\n","const sidefilterHeight = 94; //94px from sidefilter height\r\n\r\nfunction setTocHeight() {\r\n if($(window).width() < 768) {\r\n let headerHeight = $(\"#header-container\").outerHeight();\r\n let breadcrumbHeight = $(\"#breadcrumb\").outerHeight();\r\n let tocToggleHeight = $(\".btn.toc-toggle.collapse\").outerHeight();\r\n let intViewportHeight = window.innerHeight;\r\n let sidenavPaddingTop = parseInt($(\".sidenav\").css('padding-top'));\r\n let maxHeightToc = intViewportHeight - (headerHeight + breadcrumbHeight + tocToggleHeight + sidefilterHeight + sidenavPaddingTop);\r\n $(\".sidetoc\").css(\"max-height\", maxHeightToc);\r\n } else {\r\n $(\".sidetoc\").css(\"max-height\", \"none\");\r\n }\r\n}\r\n\r\nfunction updateTocHeightOnResize() {\r\n $(window).on('resize', function () {\r\n setTocHeight();\r\n });\r\n}\r\n\r\nfunction setSidenavTop() {\r\n let headerHeight = $(\"#header-container\").outerHeight();\r\n let breadcrumbHeight = $(\"#breadcrumb\").outerHeight();\r\n let tocToggleHeight = $(\".btn.toc-toggle.collapse\").outerHeight();\r\n let sidenavTop = headerHeight + breadcrumbHeight;\r\n let sidefilterTop = headerHeight + breadcrumbHeight;\r\n let sidetocTop = sidefilterTop + sidefilterHeight;\r\n let articleMarginTopDesk = sidenavTop + tocToggleHeight + 30; //30px from .sidenav padding top and bottom\r\n let articleMarginTopMobile = sidenavTop;\r\n $(\".sidenav\").css(\"top\", sidenavTop);\r\n $(\".sidefilter\").css(\"top\", sidenavTop);\r\n $(\".sidetoc\").css(\"top\", sidetocTop);\r\n\r\n if($(window).width() < 768) {\r\n $(\".body-content .article\").attr(\"style\", \"margin-top:\" + (articleMarginTopDesk + 5) + \"px !important\");\r\n } else {\r\n $(\".body-content .article\").attr(\"style\", \"margin-top:\" + (articleMarginTopMobile + 5) + \"px !important\");\r\n }\r\n}\r\n\r\nfunction updateSidenavTopOnResize() {\r\n $(window).on('resize', function () {\r\n setSidenavTop();\r\n });\r\n}\r\n\r\nfunction renderSidebar() {\r\n\r\n const sideToggleSideToc = $('#sidetoggle .sidetoc')[0];\r\n const footer = $('footer');\r\n const sidetoc = $('.sidetoc');\r\n\r\n if (typeof (sideToggleSideToc) === 'undefined') {\r\n loadToc();\r\n } else {\r\n registerTocEvents();\r\n if (footer.is(':visible')) {\r\n sidetoc.addClass('shiftup');\r\n }\r\n\r\n // Scroll to active item\r\n let top = 0;\r\n $('#toc a.active').parents('li').each(function (i, e) {\r\n $(e).addClass(active).addClass(expanded);\r\n $(e).children('a').addClass(active);\r\n top += $(e).position().top;\r\n })\r\n\r\n sidetoc.scrollTop(top - 50);\r\n\r\n if (footer.is(':visible')) {\r\n sidetoc.addClass('shiftup');\r\n }\r\n\r\n if (window.location.href.indexOf(\"articles/intro.html\") > -1 && $(window).width() > 850) {\r\n $('.nav.level1 li:eq(1)').addClass(expanded);\r\n }\r\n\r\n renderBreadcrumb();\r\n setSidenavTop();\r\n setTocHeight();\r\n }\r\n\r\n function registerTocEvents() {\r\n $('.toc .nav > li > .expand-stub').on('click', function (e) {\r\n $(e.target).parent().toggleClass(expanded);\r\n });\r\n $('.toc .nav > li > .expand-stub + a:not([href])').on('click', function (e) {\r\n $(e.target).parent().toggleClass(expanded);\r\n });\r\n $('#toc_filter_input').on('input', function () {\r\n const val = this.value;\r\n if (val === '') {\r\n // Clear 'filtered' class\r\n $('#toc li').removeClass(filtered).removeClass(hide);\r\n return;\r\n }\r\n\r\n // Get leaf nodes\r\n const tocLineAnchor = $('#toc li>a');\r\n\r\n tocLineAnchor.filter(function (i, e) {\r\n return $(e).siblings().length === 0\r\n }).each(function (j, anchor) {\r\n let text = $(anchor).attr('title');\r\n const parent = $(anchor).parent();\r\n const parentNodes = parent.parents('ul>li');\r\n for (let k = 0; k < parentNodes.length; k++) {\r\n let parentText = $(parentNodes[k]).children('a').attr('title');\r\n if (parentText) text = parentText + '.' + text;\r\n }\r\n\r\n if (filterNavItem(text, val)) {\r\n parent.addClass(show);\r\n parent.removeClass(hide);\r\n } else {\r\n parent.addClass(hide);\r\n parent.removeClass(show);\r\n }\r\n });\r\n\r\n tocLineAnchor.filter(function (i, e) {\r\n return $(e).siblings().length > 0\r\n }).each(function (i, anchor) {\r\n const parent = $(anchor).parent();\r\n if (parent.find('li.show').length > 0) {\r\n parent.addClass(show);\r\n parent.addClass(filtered);\r\n parent.removeClass(hide);\r\n } else {\r\n parent.addClass(hide);\r\n parent.removeClass(show);\r\n parent.removeClass(filtered);\r\n }\r\n })\r\n\r\n function filterNavItem(name, text) {\r\n\r\n if (!text) return true;\r\n\r\n return name && name.toLowerCase().indexOf(text.toLowerCase()) > -1;\r\n\r\n }\r\n });\r\n }\r\n\r\n function loadToc() {\r\n let tocPath = $(\"meta[property='docfx\\\\:tocrel']\").attr(\"content\");\r\n\r\n if (!tocPath) {\r\n return;\r\n }\r\n tocPath = tocPath.replace(/\\\\/g, '/');\r\n $('#sidetoc').load(tocPath + \" #sidetoggle > div\", function () {\r\n const index = tocPath.lastIndexOf('/');\r\n let tocrel = '';\r\n\r\n if (index > -1) {\r\n tocrel = tocPath.substr(0, index + 1);\r\n }\r\n\r\n const currentHref = getAbsolutePath(window.location.pathname);\r\n\r\n $('#sidetoc').find('a[href]').each(function (i, e) {\r\n let href = $(e).attr(\"href\");\r\n if (isRelativePath(href)) {\r\n href = tocrel + href;\r\n $(e).attr(\"href\", href);\r\n }\r\n\r\n if (getAbsolutePath(e.href) === currentHref) {\r\n $(e).addClass(active);\r\n }\r\n\r\n $(e).breakWord();\r\n });\r\n\r\n renderSidebar();\r\n const body = $('body');\r\n const searchResult = $('#search-results');\r\n\r\n if (searchResult.length !== 0) {\r\n $('#search').show();\r\n body.trigger(\"searchEvent\");\r\n }\r\n\r\n // if the target of the click isn't the container nor a descendant of the container\r\n body.on('mouseup', function (e) {\r\n if (!searchResult.is(e.target) && searchResult.has(e.target).length === 0) {\r\n searchResult.hide();\r\n }\r\n });\r\n });\r\n }\r\n}\r\n","function renderTabs() {\r\n\r\n const contentAttrs = {\r\n id: 'data-bi-id',\r\n name: 'data-bi-name',\r\n type: 'data-bi-type'\r\n };\r\n\r\n const Tab = (function () {\r\n function Tab(li, a, section) {\r\n this.li = li;\r\n this.a = a;\r\n this.section = section;\r\n }\r\n\r\n Object.defineProperty(Tab.prototype, \"tabIds\", {\r\n get: function () {\r\n return this.a.getAttribute('data-tab').split(' ');\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Object.defineProperty(Tab.prototype, \"condition\", {\r\n get: function () {\r\n return this.a.getAttribute('data-condition');\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Object.defineProperty(Tab.prototype, \"visible\", {\r\n get: function () {\r\n return !this.li.hasAttribute('hidden');\r\n },\r\n set: function (value) {\r\n if (value) {\r\n this.li.removeAttribute('hidden');\r\n this.li.removeAttribute('aria-hidden');\r\n } else {\r\n this.li.setAttribute('hidden', 'hidden');\r\n this.li.setAttribute('aria-hidden', 'true');\r\n }\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Object.defineProperty(Tab.prototype, \"selected\", {\r\n get: function () {\r\n return !this.section.hasAttribute('hidden');\r\n },\r\n set: function (value) {\r\n if (value) {\r\n this.a.setAttribute('aria-selected', 'true');\r\n this.a.tabIndex = 0;\r\n this.section.removeAttribute('hidden');\r\n this.section.removeAttribute('aria-hidden');\r\n } else {\r\n this.a.setAttribute('aria-selected', 'false');\r\n this.a.tabIndex = -1;\r\n this.section.setAttribute('hidden', 'hidden');\r\n this.section.setAttribute('aria-hidden', 'true');\r\n }\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Tab.prototype.focus = function () {\r\n this.a.focus();\r\n };\r\n\r\n return Tab;\r\n\r\n }());\r\n\r\n initTabs(document.body);\r\n\r\n function initTabs(container) {\r\n const queryStringTabs = readTabsQueryStringParam();\r\n const elements = container.querySelectorAll('.tabGroup');\r\n const state = {groups: [], selectedTabs: []};\r\n for (let i = 0; i < elements.length; i++) {\r\n const group = initTabGroup(elements.item(i));\r\n if (!group.independent) {\r\n updateVisibilityAndSelection(group, state);\r\n state.groups.push(group);\r\n }\r\n }\r\n container.addEventListener('click', function (event) {\r\n return handleClick(event, state);\r\n });\r\n if (state.groups.length === 0) {\r\n return state;\r\n }\r\n selectTabs(queryStringTabs, container);\r\n updateTabsQueryStringParam(state);\r\n notifyContentUpdated();\r\n return state;\r\n }\r\n\r\n function initTabGroup(element) {\r\n\r\n const group = {\r\n independent: element.hasAttribute('data-tab-group-independent'),\r\n tabs: []\r\n };\r\n\r\n let li = element.firstElementChild.firstElementChild;\r\n while (li) {\r\n const a = li.firstElementChild;\r\n a.setAttribute(contentAttrs.name, 'tab');\r\n\r\n const dataTab = a.getAttribute('data-tab').replace(/\\+/g, ' ');\r\n a.setAttribute('data-tab', dataTab);\r\n\r\n const section = element.querySelector(\"[id=\\\"\" + a.getAttribute('aria-controls') + \"\\\"]\");\r\n const tab = new Tab(li, a, section);\r\n group.tabs.push(tab);\r\n\r\n li = li.nextElementSibling;\r\n }\r\n\r\n element.setAttribute(contentAttrs.name, 'tab-group');\r\n element.tabGroup = group;\r\n\r\n return group;\r\n }\r\n\r\n function updateVisibilityAndSelection(group, state) {\r\n let anySelected = false;\r\n let firstVisibleTab;\r\n\r\n for (let _i = 0, _a = group.tabs; _i < _a.length; _i++) {\r\n let tab = _a[_i];\r\n tab.visible = tab.condition === null || state.selectedTabs.indexOf(tab.condition) !== -1;\r\n if (tab.visible) {\r\n if (!firstVisibleTab) {\r\n firstVisibleTab = tab;\r\n }\r\n }\r\n tab.selected = tab.visible && arraysIntersect(state.selectedTabs, tab.tabIds);\r\n anySelected = anySelected || tab.selected;\r\n }\r\n\r\n if (!anySelected) {\r\n for (let _b = 0, _c = group.tabs; _b < _c.length; _b++) {\r\n const tabIds = _c[_b].tabIds;\r\n for (let _d = 0, tabIds_1 = tabIds; _d < tabIds_1.length; _d++) {\r\n const tabId = tabIds_1[_d];\r\n const index = state.selectedTabs.indexOf(tabId);\r\n if (index === -1) {\r\n continue;\r\n }\r\n state.selectedTabs.splice(index, 1);\r\n }\r\n }\r\n const tab = firstVisibleTab;\r\n tab.selected = true;\r\n state.selectedTabs.push(tab.tabIds[0]);\r\n }\r\n }\r\n\r\n function getTabInfoFromEvent(event) {\r\n\r\n if (!(event.target instanceof HTMLElement)) {\r\n return null;\r\n }\r\n\r\n const anchor = event.target.closest('a[data-tab]');\r\n\r\n if (anchor === null) {\r\n return null;\r\n }\r\n\r\n const tabIds = anchor.getAttribute('data-tab').split(' ');\r\n const group = anchor.parentElement.parentElement.parentElement.tabGroup;\r\n\r\n if (group === undefined) {\r\n return null;\r\n }\r\n\r\n return {tabIds: tabIds, group: group, anchor: anchor};\r\n }\r\n\r\n function handleClick(event, state) {\r\n const info = getTabInfoFromEvent(event);\r\n\r\n if (info === null) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n info.anchor.href = 'javascript:';\r\n\r\n setTimeout(function () {\r\n return info.anchor.href = '#' + info.anchor.getAttribute('aria-controls');\r\n });\r\n\r\n const tabIds = info.tabIds, group = info.group;\r\n const originalTop = info.anchor.getBoundingClientRect().top;\r\n\r\n if (group.independent) {\r\n for (let _i = 0, _a = group.tabs; _i < _a.length; _i++) {\r\n const tab = _a[_i];\r\n tab.selected = arraysIntersect(tab.tabIds, tabIds);\r\n }\r\n } else {\r\n if (arraysIntersect(state.selectedTabs, tabIds)) {\r\n return;\r\n }\r\n const previousTabId = group.tabs.filter(function (t) {\r\n return t.selected;\r\n })[0].tabIds[0];\r\n state.selectedTabs.splice(state.selectedTabs.indexOf(previousTabId), 1, tabIds[0]);\r\n for (let _b = 0, _c = state.groups; _b < _c.length; _b++) {\r\n const group_1 = _c[_b];\r\n updateVisibilityAndSelection(group_1, state);\r\n }\r\n updateTabsQueryStringParam(state);\r\n }\r\n notifyContentUpdated();\r\n const top = info.anchor.getBoundingClientRect().top;\r\n if (top !== originalTop && event instanceof MouseEvent) {\r\n window.scrollTo(0, window.pageYOffset + top - originalTop);\r\n }\r\n }\r\n\r\n function selectTabs(tabIds) {\r\n for (let _i = 0, tabIds_1 = tabIds; _i < tabIds_1.length; _i++) {\r\n const tabId = tabIds_1[_i];\r\n const a = document.querySelector(\".tabGroup > ul > li > a[data-tab=\\\"\" + tabId + \"\\\"]:not([hidden])\");\r\n\r\n if (a === null) {\r\n return;\r\n }\r\n\r\n a.dispatchEvent(new CustomEvent('click', {bubbles: true}));\r\n }\r\n }\r\n\r\n function readTabsQueryStringParam() {\r\n const qs = parseQueryString();\r\n const t = qs.tabs;\r\n\r\n if (t === undefined || t === '') {\r\n return [];\r\n }\r\n\r\n return t.split(',');\r\n }\r\n\r\n function updateTabsQueryStringParam(state) {\r\n const qs = parseQueryString();\r\n qs.tabs = state.selectedTabs.join();\r\n\r\n const url = location.protocol + \"//\" + location.host + location.pathname + \"?\" + toQueryString(qs) + location.hash;\r\n\r\n if (location.href === url) {\r\n return;\r\n }\r\n\r\n history.replaceState({}, document.title, url);\r\n }\r\n\r\n function toQueryString(args) {\r\n const parts = [];\r\n\r\n for (let name_1 in args) {\r\n if (args.hasOwnProperty(name_1) && args[name_1] !== '' && args[name_1] !== null && args[name_1] !== undefined) {\r\n parts.push(encodeURIComponent(name_1) + '=' + encodeURIComponent(args[name_1]));\r\n }\r\n }\r\n\r\n return parts.join('&');\r\n }\r\n\r\n function parseQueryString(queryString) {\r\n let match;\r\n const pl = /\\+/g;\r\n const search = /([^&=]+)=?([^&]*)/g;\r\n\r\n const decode = function (s) {\r\n return decodeURIComponent(s.replace(pl, ' '));\r\n };\r\n\r\n if (queryString === undefined) {\r\n queryString = '';\r\n }\r\n\r\n queryString = queryString.substring(1);\r\n const urlParams = {};\r\n\r\n while (match = search.exec(queryString)) {\r\n urlParams[decode(match[1])] = decode(match[2]);\r\n }\r\n\r\n return urlParams;\r\n }\r\n\r\n function arraysIntersect(a, b) {\r\n for (let _i = 0, a_1 = a; _i < a_1.length; _i++) {\r\n const itemA = a_1[_i];\r\n\r\n for (let _a = 0, b_1 = b; _a < b_1.length; _a++) {\r\n const itemB = b_1[_a];\r\n if (itemA === itemB) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function notifyContentUpdated() {\r\n // Dispatch this event when needed\r\n // window.dispatchEvent(new CustomEvent('content-update'));\r\n }\r\n}\r\n","/**\r\n * Styling for tables in conceptual documents using Bootstrap.\r\n * See http://getbootstrap.com/css/#tables\r\n */\r\nfunction renderTables() {\r\n $('table').addClass('table table-bordered table-striped table-condensed').wrap('
');\r\n}\r\n","window.refresh = function (article) {\r\n\r\n // Update markup result\r\n if (typeof article == 'undefined' || typeof article.content == 'undefined') {\r\n console.error(\"Null Argument\");\r\n }\r\n\r\n $(\"article.content\").html(article.content);\r\n\r\n highlight();\r\n renderTables();\r\n renderAlerts();\r\n renderAffix();\r\n renderTabs();\r\n}\r\n\r\n$(document).on('wordpressMenuHasLoaded', function () {\r\n const path = window.location.pathname;\r\n const docsUrl = '/docs/articles/';\r\n const wpNavBar = document.getElementById('menu-menu-principal');\r\n const items = wpNavBar.getElementsByTagName('a');\r\n\r\n for (let i = 0; i < items.length; i++) {\r\n\r\n if (items[i].href.includes(docsUrl) && path.includes(docsUrl) && !items[i].href.includes('#')) {\r\n $(items[i]).addClass('activepath');\r\n }\r\n }\r\n\r\n const queryString = window.location.search;\r\n\r\n if (queryString) {\r\n const queryStringComponents = queryString.split('=');\r\n const searchParam = queryStringComponents.slice(-1)[0];\r\n $('#search-query').val(decodeURI(searchParam));\r\n }\r\n\r\n});\r\n\r\n\r\n// Enable anchors for headings.\r\n(function () {\r\n anchors.options = {\r\n placement: 'right',\r\n visible: 'hover',\r\n icon: '#'\r\n };\r\n anchors.add('article h2:not(.no-anchor), article h3:not(.no-anchor), article h4:not(.no-anchor)');\r\n})();\r\n","// Enable highlight.js\r\nfunction highlight() {\r\n\r\n $('pre code').each(function (i, block) {\r\n hljs.highlightBlock(block);\r\n });\r\n\r\n $('pre code[highlight-lines]').each(function (i, block) {\r\n if (block.innerHTML === \"\") return;\r\n const lines = block.innerHTML.split('\\n');\r\n\r\n const queryString = block.getAttribute('highlight-lines');\r\n if (!queryString) return;\r\n\r\n let rangesString = queryString.split(',');\r\n let ranges = rangesString.map(Number);\r\n\r\n for (let range of ranges) {\r\n const found = range.match(/^(\\d+)\\-(\\d+)?$/);\r\n let start = 0;\r\n let end = 0;\r\n if (found) {\r\n // consider region as `{startlinenumber}-{endlinenumber}`, in which {endlinenumber} is optional\r\n start = +found[1];\r\n end = +found[2];\r\n if (isNaN(end) || end > lines.length) {\r\n end = lines.length;\r\n }\r\n } else {\r\n // consider region as a sigine line number\r\n if (isNaN(range)) continue;\r\n start = +range;\r\n end = start;\r\n }\r\n if (start <= 0 || end <= 0 || start > end || start > lines.length) {\r\n // skip current region if invalid\r\n continue;\r\n }\r\n lines[start - 1] = '' + lines[start - 1];\r\n lines[end - 1] = lines[end - 1] + '';\r\n }\r\n\r\n block.innerHTML = lines.join('\\n');\r\n });\r\n}\r\n\r\n// Support full-text-search\r\nfunction enableSearch() {\r\n let query;\r\n const relHref = $(\"meta[property='docfx\\\\:rel']\").attr(\"content\");\r\n\r\n if (typeof relHref === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n const worker = new Worker(relHref + 'styles/search-worker.js');\r\n if (!worker && !window.worker) {\r\n localSearch();\r\n } else {\r\n webWorkerSearch(worker);\r\n }\r\n renderSearchBox();\r\n highlightKeywords();\r\n addSearchEvent();\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n\r\n //Adjust the position of search box in navbar\r\n function renderSearchBox() {\r\n autoCollapse();\r\n\r\n $(window).on('resize', () => autoCollapse());\r\n\r\n $(document).on('click', '.navbar-collapse.in', function (e) {\r\n if ($(e.target).is('a')) {\r\n $(this).collapse(hide);\r\n }\r\n });\r\n\r\n function autoCollapse() {\r\n const navbar = $('#autocollapse');\r\n if (navbar.height() === null) {\r\n setTimeout(autoCollapse, 300);\r\n }\r\n navbar.removeClass(collapsed);\r\n if (navbar.height() > 60) {\r\n navbar.addClass(collapsed);\r\n }\r\n }\r\n }\r\n\r\n // Search factory\r\n function localSearch() {\r\n const lunrIndex = lunr(function () {\r\n this.ref('href');\r\n this.field('title', {boost: 50});\r\n this.field('keywords', {boost: 20});\r\n });\r\n lunr.tokenizer.seperator = /[\\s\\-\\.]+/;\r\n let searchData = {};\r\n const searchDataRequest = new XMLHttpRequest();\r\n\r\n const indexPath = relHref + \"index.json\";\r\n if (indexPath) {\r\n searchDataRequest.open('GET', indexPath);\r\n searchDataRequest.onload = function () {\r\n if (this.status !== 200) {\r\n return;\r\n }\r\n searchData = JSON.parse(this.responseText);\r\n for (let prop in searchData) {\r\n if (searchData.hasOwnProperty(prop)) {\r\n lunrIndex.add(searchData[prop]);\r\n }\r\n }\r\n }\r\n searchDataRequest.send();\r\n }\r\n\r\n $(\"body\").on(\"queryReady\", function () {\r\n const hits = lunrIndex.search(query);\r\n const results = [];\r\n hits.forEach(function (hit) {\r\n const item = searchData[hit.ref];\r\n results.push({'href': item.href, 'title': item.title, 'keywords': item.keywords});\r\n });\r\n handleSearchResults(results);\r\n });\r\n }\r\n\r\n function webWorkerSearch(worker) {\r\n const indexReady = $.Deferred();\r\n worker.onmessage = function (oEvent) {\r\n switch (oEvent.data.e) {\r\n case 'index-ready':\r\n indexReady.resolve();\r\n break;\r\n case 'query-ready':\r\n const hits = oEvent.data.d;\r\n handleSearchResults(hits);\r\n break;\r\n }\r\n }\r\n\r\n indexReady.promise().done(function () {\r\n\r\n $(\"body\").on(\"query-ready\", function () {\r\n postSearchQuery(worker, query);\r\n });\r\n\r\n postSearchQuery(worker, query);\r\n\r\n });\r\n }\r\n\r\n /**\r\n * This function posts the message to the worker if the string has at least\r\n * three characters.\r\n *\r\n * @param worker The search worker used by DocFx (lunr)\r\n * @param searchQuery The string to post to the worker.\r\n */\r\n function postSearchQuery(worker, searchQuery) {\r\n if (searchQuery && (searchQuery.length >= 3)) {\r\n worker.postMessage({q: `${searchQuery}*`});\r\n } else {\r\n worker.postMessage({q: ''});\r\n }\r\n }\r\n\r\n /**\r\n * Highlight the searching keywords\r\n */\r\n function highlightKeywords() {\r\n const q = url('?q');\r\n if (q != null) {\r\n const keywords = q.split(\"%20\");\r\n keywords.forEach(function (keyword) {\r\n if (keyword !== \"\") {\r\n $('.data-searchable *').mark(keyword);\r\n $('article *').mark(keyword);\r\n }\r\n });\r\n }\r\n }\r\n\r\n function addSearchEvent() {\r\n $('body').on(\"searchEvent\", function () {\r\n $('#search-results>.sr-items').html('

No results found

');\r\n\r\n const searchQuery = $('#search-query');\r\n\r\n searchQuery.on('input', function (e) {\r\n return e.key !== 'Enter';\r\n });\r\n\r\n searchQuery.on(\"keyup\", function (e) {\r\n $('#search-results').show();\r\n query = `${e.target.value}`;\r\n $(\"body\").trigger(\"query-ready\");\r\n $('#search-results>.search-list').text('Search Results for \"' + query + '\"');\r\n }).off(\"keydown\");\r\n });\r\n }\r\n\r\n function relativeUrlToAbsoluteUrl(currentUrl, relativeUrl) {\r\n const currentItems = currentUrl.split(/\\/+/);\r\n const relativeItems = relativeUrl.split(/\\/+/);\r\n let depth = currentItems.length - 1;\r\n const items = [];\r\n for (let i = 0; i < relativeItems.length; i++) {\r\n if (relativeItems[i] === '..') {\r\n depth--;\r\n } else if (relativeItems[i] !== '.') {\r\n items.push(relativeItems[i]);\r\n }\r\n }\r\n return currentItems.slice(0, depth).concat(items).join('/');\r\n }\r\n\r\n function extractContentBrief(content) {\r\n const briefOffset = 50;\r\n const words = query.split(/\\s+/g);\r\n const queryIndex = content.indexOf(words[0]);\r\n\r\n if (queryIndex > briefOffset) {\r\n return \"...\" + content.slice(queryIndex - briefOffset, queryIndex + briefOffset) + \"...\";\r\n } else if (queryIndex <= briefOffset) {\r\n return content.slice(0, queryIndex + briefOffset) + \"...\";\r\n }\r\n }\r\n\r\n function handleSearchResults(hits) {\r\n if (hits.length === 0) {\r\n $('#search-results>.sr-items').html('

No results found

');\r\n } else {\r\n $('#search-results>.sr-items').empty().append(\r\n hits.slice(0, 20).map(function (hit) {\r\n const currentUrl = window.location.href;\r\n\r\n const itemRawHref = relativeUrlToAbsoluteUrl(currentUrl, relHref + hit.href);\r\n const itemHref = relHref + hit.href + \"?q=\" + query;\r\n const itemTitle = hit.title;\r\n const itemBrief = extractContentBrief(hit.keywords);\r\n\r\n const itemNode = $('').attr('class', 'sr-item').attr('href', itemHref);\r\n const itemTitleNode = $('
').attr('class', 'item-title').text(itemTitle);\r\n const itemBriefNode = $('
').attr('class', 'item-brief').text(itemBrief);\r\n itemNode.append(itemTitleNode).append(itemBriefNode);\r\n\r\n return itemNode;\r\n })\r\n );\r\n query.split(/\\s+/).forEach(function (word) {\r\n if (word !== '') {\r\n word = word.replace(/\\*/g, '');\r\n $('#search-results>.sr-items *').mark(word);\r\n }\r\n });\r\n }\r\n }\r\n}\r\n","function getAbsolutePath(href) {\r\n // Use anchor to normalize href\r\n const anchor = $('')[0];\r\n // Ignore protocal, remove search and query\r\n return anchor.host + anchor.pathname;\r\n}\r\n\r\nfunction isRelativePath(href) {\r\n if (href === undefined || href === '' || href[0] === '/') {\r\n return false;\r\n }\r\n return !isAbsolutePath(href);\r\n}\r\n\r\nfunction isAbsolutePath(href) {\r\n return (/^(?:[a-z]+:)?\\/\\//i).test(href);\r\n}\r\n\r\nfunction getDirectory(href) {\r\n if (!href) {\r\n return '';\r\n }\r\n\r\n const index = href.lastIndexOf('/');\r\n\r\n if (index === -1) {\r\n return '';\r\n }\r\n\r\n if (index > -1) {\r\n return href.substr(0, index);\r\n }\r\n}\r\n\r\nfunction formList(item, classes) {\r\n let level = 1;\r\n const model = {\r\n items: item\r\n };\r\n\r\n const cls = [].concat(classes).join(\" \");\r\n return getList(model, cls);\r\n\r\n function getList(model, cls) {\r\n\r\n if (!model || !model.items) {\r\n return null;\r\n }\r\n\r\n const l = model.items.length;\r\n\r\n if (l === 0) {\r\n return null;\r\n }\r\n\r\n let html = '
    ';\r\n level++;\r\n\r\n for (let i = 0; i < l; i++) {\r\n const item = model.items[i];\r\n const href = item.href;\r\n const name = item.name;\r\n\r\n if (!name) {\r\n continue;\r\n }\r\n\r\n html += href ? '
  • ' + name + '' : '
  • ' + name;\r\n html += getList(item, cls) || '';\r\n html += '
  • ';\r\n }\r\n\r\n html += '
';\r\n return html;\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Add into long word.\r\n * @param {String} text - The word to break. It should be in plain text without HTML tags.\r\n */\r\nfunction breakPlainText(text) {\r\n if (!text) return text;\r\n return text.replace(/([a-z])([A-Z])|(\\.)(\\w)/g, '$1$3$2$4')\r\n}\r\n\r\n/**\r\n * Add into long word. The jQuery element should contain no html tags.\r\n * If the jQuery element contains tags, this function will not change the element.\r\n */\r\nfunction breakWord() {\r\n if (this.html() === this.text()) {\r\n this.html(function (index, text) {\r\n return breakPlainText(text);\r\n })\r\n }\r\n\r\n return this;\r\n}\r\n\r\n/**\r\n * adjusted from https://stackoverflow.com/a/13067009/1523776\r\n */\r\nfunction workAroundFixedHeaderForAnchors() {\r\n const HISTORY_SUPPORT = !!(history && history.pushState);\r\n const ANCHOR_REGEX = /^#[^ ]+$/;\r\n\r\n function getFixedOffset() {\r\n return $('header').first().height();\r\n }\r\n\r\n /**\r\n * If the provided href is an anchor which resolves to an element on the\r\n * page, scroll to it.\r\n * @param {String} href destination\r\n * @param {Boolean} pushToHistory push to history\r\n * @return {Boolean} - Was the href an anchor.\r\n */\r\n function scrollIfAnchor(href, pushToHistory) {\r\n let match, rect, anchorOffset;\r\n\r\n if (!ANCHOR_REGEX.test(href)) {\r\n return false;\r\n }\r\n\r\n match = document.getElementById(href.slice(1));\r\n\r\n if (match) {\r\n rect = match.getBoundingClientRect();\r\n anchorOffset = window.pageYOffset + rect.top - getFixedOffset();\r\n window.scrollTo(window.pageXOffset, anchorOffset);\r\n\r\n // Add the state to history as-per normal anchor links\r\n if (HISTORY_SUPPORT && pushToHistory) {\r\n history.pushState({}, document.title, location.pathname + href);\r\n }\r\n }\r\n\r\n return !!match;\r\n }\r\n\r\n /**\r\n * Attempt to scroll to the current location's hash.\r\n */\r\n function scrollToCurrent() {\r\n scrollIfAnchor(window.location.hash, false);\r\n }\r\n\r\n $(window).on('hashchange', () => scrollToCurrent());\r\n // Exclude tabbed content case\r\n scrollToCurrent();\r\n\r\n $(document).on('ready', function () {\r\n $('body').scrollspy({offset: 150});\r\n });\r\n}\r\n\r\nfunction breakText() {\r\n $(\".xref\").addClass(\"text-break\");\r\n const texts = $(\".text-break\");\r\n texts.each(function () {\r\n $(this).breakWord();\r\n });\r\n}\r\n"]} \ No newline at end of file +{"version":3,"sources":["constant.js","render.js","component/affix.js","component/alerts.js","component/breadcrumb.js","component/footer.js","component/links.js","component/navbar.js","component/sidebar.js","component/tab.js","component/tables.js","service/globalevents.js","service/search.js","service/utility.js"],"names":["active","expanded","filtered","show","hide","collapsed","Object","assign","$","fn","breakWord","workAroundFixedHeaderForAnchors","highlight","enableSearch","renderTables","renderAlerts","updateAlertHeightOnResize","renderLinks","renderSidebar","renderAffix","renderNavbar","renderLogo","updateLogo","updateLogoOnResize","updateTocHeightOnResize","updateSidenavTopOnResize","renderFooter","breakText","renderTabs","contributionDiv","hierarchy","$headers","map","h","join","stack","each","i","e","id","item","name","str","text","replace","href","items","length","frame","tagName","type","siblings","push","buildParent","childrenToAttach","pop","parentFrame","parent","child","topLevel","html","formList","empty","append","is","css","on","scrollspy","data","target","hash","activate","contribution","get","outerHTML","remove","setAlertHeight","maxHeight","Math","max","apply","this","outerHeight","window","addClass","renderBreadcrumb","breadcrumb","innerHTML","needFooter","document","height","scrollTop","resetBottomCss","removeClass","shiftUpBottomCss","fadeIn","fadeOut","attr","links","filter","hostname","location","initializeNavbar","navbar","querySelector","body","classList","contains","let","last_known_scroll_position","ticking","addEventListener","scrollY","requestAnimationFrame","add","unoMenuReq","XMLHttpRequest","$navbar","getElementById","wordpressMenuHasLoaded","open","onload","status","responseText","JSON","parse","trigger","onerror","send","ajaxComplete","event","xhr","settings","url","getElementsByClassName","className","curWidth","innerWidth","headerLogo","mobileLogo","URL","src","deskLogo","loadNavbar","navbarPath","tocPath","find","appendTo","index","lastIndexOf","navrel","substr","currentAbsPath","getAbsolutePath","pathname","isRelativePath","isActive","originalHref","getDirectory","parents","$img","jQuery","imgID","imgClass","imgURL","$svg","removeAttr","replaceWith","sidefilterHeight","setTocHeight","headerHeight","breadcrumbHeight","tocToggleHeight","sidenavPaddingTop","maxHeightToc","width","intViewportHeight","innerHeight","parseInt","setSidenavTop","sidenavTop","sidetocTop","articleMarginTopDesk","articleMarginTopMobile","sideToggleSideToc","footer","sidetoc","loadToc","load","tocrel","currentHref","searchResult","has","toggleClass","val","value","tocLineAnchor","j","anchor","parentNodes","k","parentText","children","toLowerCase","indexOf","top","position","contentAttrs","Tab","defineProperty","prototype","a","getAttribute","split","enumerable","configurable","li","hasAttribute","set","removeAttribute","setAttribute","section","tabIndex","focus","initTabs","container","queryStringTabs","qs","parseQueryString","t","tabs","undefined","elements","querySelectorAll","state","groups","selectedTabs","group","element","independent","firstElementChild","dataTab","tab","nextElementSibling","tabGroup","updateVisibilityAndSelection","handleClick","info","HTMLElement","closest","tabIds","parentElement","preventDefault","setTimeout","originalTop","getBoundingClientRect","_i","_a","selected","arraysIntersect","previousTabId","splice","_b","_c","updateTabsQueryStringParam","MouseEvent","scrollTo","pageYOffset","tabIds_1","tabId","dispatchEvent","CustomEvent","bubbles","anySelected","firstVisibleTab","visible","condition","_d","protocol","host","args","parts","name_1","hasOwnProperty","encodeURIComponent","history","replaceState","title","queryString","match","pl","decode","s","decodeURIComponent","search","urlParams","substring","exec","b","a_1","itemA","b_1","wrap","refresh","article","content","console","error","path","docsUrl","getElementsByTagName","includes","searchParam","slice","decodeURI","anchors","options","placement","icon","block","hljs","highlightBlock","range","lines","Number","found","start","end","isNaN","query","relHref","q","worker","Worker","webWorkerSearch","indexReady","Deferred","onmessage","oEvent","resolve","handleSearchResults","d","promise","done","postSearchQuery","localSearch","lunrIndex","lunr","ref","field","boost","tokenizer","seperator","searchData","searchDataRequest","indexPath","prop","hits","results","forEach","hit","keywords","autoCollapse","collapse","keyword","mark","searchQuery","key","off","postMessage","relativeUrlToAbsoluteUrl","currentUrl","relativeUrl","currentItems","relativeItems","depth","concat","itemHref","itemTitle","itemBrief","words","queryIndex","itemNode","itemTitleNode","itemBriefNode","word","isAbsolutePath","test","classes","level","getList","model","cls","l","breakPlainText","HISTORY_SUPPORT","pushState","ANCHOR_REGEX","scrollIfAnchor","pushToHistory","anchorOffset","rect","first","pageXOffset","scrollToCurrent","offset"],"mappings":"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","file":"docfx.js","sourcesContent":["const active = 'active';\r\nconst expanded = 'in';\r\nconst filtered = 'filtered';\r\nconst show = 'show';\r\nconst hide = 'hide';\r\nconst collapsed = 'collapsed';\r\n","// workaround for gulp-uglify changing order of execution on $.fn func assignments\r\nObject.assign($.fn, { breakWord });\r\n\r\nworkAroundFixedHeaderForAnchors();\r\nhighlight();\r\nenableSearch();\r\n\r\nrenderTables();\r\nrenderAlerts();\r\nupdateAlertHeightOnResize();\r\nrenderLinks();\r\nrenderSidebar();\r\nrenderAffix();\r\n\r\nrenderNavbar();\r\nrenderLogo();\r\nupdateLogo()\r\nupdateLogoOnResize();\r\nupdateTocHeightOnResize();\r\nupdateSidenavTopOnResize();\r\nrenderFooter();\r\nbreakText();\r\nrenderTabs();\r\nupdateLogo();\r\n","//Setup Affix\r\nfunction renderAffix() {\r\n const hierarchy = getHierarchy();\r\n\r\n if (hierarchy && hierarchy.length > 0) {\r\n let html = '
In This Article
'\r\n html += formList(hierarchy, ['nav', 'bs-docs-sidenav']);\r\n\r\n $(\"#affix\").empty().append(html);\r\n\r\n if ($('footer').is(':visible')) {\r\n $(\".sideaffix\").css(\"bottom\", \"70px\");\r\n }\r\n\r\n $('#affix a').on('click', function (e) {\r\n const scrollspy = $('[data-spy=\"scroll\"]').data()['bs.scrollspy'];\r\n const target = e.target.hash;\r\n if (scrollspy && target) {\r\n scrollspy.activate(target);\r\n }\r\n });\r\n\r\n const contribution = $('.contribution');\r\n const contributionDiv = contribution.get(0).outerHTML;\r\n contribution.remove();\r\n $('.sideaffix').append(contributionDiv);\r\n\r\n }\r\n\r\n function getHierarchy() {\r\n // supported headers are h1, h2, h3, and h4\r\n const $headers = $($.map(['h1', 'h2', 'h3', 'h4'], function (h) { return \".article article \" + h; }).join(\", \"));\r\n\r\n // a stack of hierarchy items that are currently being built\r\n const stack = [];\r\n $headers.each(function (i, e) {\r\n if (!e.id) {\r\n return;\r\n }\r\n\r\n const item = {\r\n name: htmlEncode($(e).text()),\r\n href: \"#\" + e.id,\r\n items: []\r\n };\r\n\r\n if (!stack.length) {\r\n stack.push({ type: e.tagName, siblings: [item] });\r\n return;\r\n }\r\n\r\n const frame = stack[stack.length - 1];\r\n if (e.tagName === frame.type) {\r\n frame.siblings.push(item);\r\n } else if (e.tagName[1] > frame.type[1]) {\r\n // we are looking at a child of the last element of frame.siblings.\r\n // push a frame onto the stack. After we've finished building this item's children,\r\n // we'll attach it as a child of the last element\r\n stack.push({ type: e.tagName, siblings: [item] });\r\n } else { // e.tagName[1] < frame.type[1]\r\n // we are looking at a sibling of an ancestor of the current item.\r\n // pop frames from the stack, building items as we go, until we reach the correct level at which to attach this item.\r\n while (e.tagName[1] < stack[stack.length - 1].type[1]) {\r\n buildParent();\r\n }\r\n if (e.tagName === stack[stack.length - 1].type) {\r\n stack[stack.length - 1].siblings.push(item);\r\n } else {\r\n stack.push({ type: e.tagName, siblings: [item] });\r\n }\r\n }\r\n });\r\n while (stack.length > 1) {\r\n buildParent();\r\n }\r\n\r\n function buildParent() {\r\n const childrenToAttach = stack.pop();\r\n const parentFrame = stack[stack.length - 1];\r\n const parent = parentFrame.siblings[parentFrame.siblings.length - 1];\r\n $.each(childrenToAttach.siblings, function (i, child) {\r\n parent.items.push(child);\r\n });\r\n }\r\n if (stack.length > 0) {\r\n\r\n const topLevel = stack.pop().siblings;\r\n if (topLevel.length === 1) { // if there's only one topmost header, dump it\r\n return topLevel[0].items;\r\n }\r\n return topLevel;\r\n }\r\n return undefined;\r\n }\r\n\r\n function htmlEncode(str) {\r\n if (!str) return str;\r\n return str\r\n .replace(/&/g, '&')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''')\r\n .replace(//g, '>');\r\n }\r\n\r\n function htmlDecode(str) {\r\n if (!str) return str;\r\n return str\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/&/g, '&');\r\n }\r\n\r\n function cssEscape(str) {\r\n // see: http://stackoverflow.com/questions/2786538/need-to-escape-a-special-character-in-a-jquery-selector-string#answer-2837646\r\n if (!str) return str;\r\n return str\r\n .replace(/[!\"#$%&'()*+,.\\/:;<=>?@[\\\\\\]^`{|}~]/g, \"\\\\$&\");\r\n }\r\n}\r\n","// Styling for alerts.\r\nfunction setAlertHeight(){\r\n var maxHeight = Math.max.apply(null, $(\".col-md-6 div.alert\").map(function ()\r\n {\r\n return $(this).outerHeight();\r\n }).get());\r\n\r\n $('.alert').css('height', maxHeight);\r\n \r\n}\r\n\r\nfunction updateAlertHeightOnResize() {\r\n $(window).on('resize', function () {\r\n $('.alert').css('height', 'auto');\r\n setAlertHeight();\r\n });\r\n}\r\n\r\nfunction renderAlerts() {\r\n $('.NOTE, .TIP').addClass('alert alert-info');\r\n $('.WARNING').addClass('alert alert-warning');\r\n $('.IMPORTANT, .CAUTION').addClass('alert alert-danger');\r\n setAlertHeight();\r\n\r\n}\r\n","function renderBreadcrumb() {\r\n const breadcrumb = [];\r\n\r\n $('#navbar a.active').each(function (i, e) {\r\n breadcrumb.push({\r\n href: e.href,\r\n name: e.innerHTML\r\n });\r\n })\r\n $('#toc a.active').each(function (i, e) {\r\n breadcrumb.push({\r\n href: e.href,\r\n name: e.innerHTML\r\n });\r\n })\r\n\r\n const html = formList(breadcrumb, 'breadcrumb');\r\n $('#breadcrumb').html(html);\r\n}\r\n","// Show footer\r\nfunction renderFooter() {\r\n initFooter();\r\n $(window).on(\"scroll\", () => showFooterCore());\r\n\r\n function initFooter() {\r\n if (needFooter()) {\r\n shiftUpBottomCss();\r\n $(\"footer\").show();\r\n } else {\r\n resetBottomCss();\r\n $(\"footer\").hide();\r\n }\r\n }\r\n\r\n function showFooterCore() {\r\n if (needFooter()) {\r\n shiftUpBottomCss();\r\n $(\"footer\").fadeIn();\r\n } else {\r\n resetBottomCss();\r\n $(\"footer\").fadeOut();\r\n }\r\n }\r\n\r\n function needFooter() {\r\n const scrollHeight = $(document).height();\r\n const scrollPosition = $(window).height() + $(window).scrollTop();\r\n return (scrollHeight - scrollPosition) < 1;\r\n }\r\n\r\n function resetBottomCss() {\r\n $(\".sidetoc\").removeClass(\"shiftup\");\r\n $(\".sideaffix\").removeClass(\"shiftup\");\r\n }\r\n\r\n function shiftUpBottomCss() {\r\n $(\".sidetoc\").addClass(\"shiftup\");\r\n $(\".sideaffix\").addClass(\"shiftup\");\r\n }\r\n}\r\n","// Open links to different host in a new window.\r\nfunction renderLinks() {\r\n if ($(\"meta[property='docfx:newtab']\").attr(\"content\") === \"true\") {\r\n $(document.links).filter(function () {\r\n return this.hostname !== window.location.hostname;\r\n }).attr('target', '_blank');\r\n }\r\n}\r\n","/**\r\n * Load the navbar from the uno website\r\n */\r\nfunction initializeNavbar() {\r\n\r\n const navbar = document.querySelector(\"header > .navbar\");\r\n if (document.body.classList.contains(\"front-page\")) {\r\n let last_known_scroll_position = 0;\r\n let ticking = false;\r\n\r\n function doSomething(scroll_pos) {\r\n if (scroll_pos >= 100) navbar.classList.add(\"scrolled\");\r\n else navbar.classList.remove(\"scrolled\");\r\n }\r\n\r\n window.addEventListener(\"scroll\", function () {\r\n last_known_scroll_position = window.scrollY;\r\n\r\n if (!ticking) {\r\n window.requestAnimationFrame(function () {\r\n doSomething(last_known_scroll_position);\r\n ticking = false;\r\n });\r\n\r\n ticking = true;\r\n }\r\n });\r\n }\r\n\r\n const unoMenuReq = new XMLHttpRequest();\r\n const unoMenuEndpoint = \"https://platform.uno/wp-json/wp/v2/menu\";\r\n const $navbar = document.getElementById(\"navbar\");\r\n let wordpressMenuHasLoaded = false;\r\n\r\n unoMenuReq.open(\"get\", unoMenuEndpoint, true);\r\n\r\n if (typeof navbar !== \"undefined\") {\r\n unoMenuReq.onload = function () {\r\n if (unoMenuReq.status === 200 && unoMenuReq.responseText) {\r\n $navbar.innerHTML = JSON.parse(\r\n unoMenuReq.responseText\r\n );\r\n wordpressMenuHasLoaded = true;\r\n $(document).trigger(\"wordpressMenuHasLoaded\");\r\n }\r\n };\r\n unoMenuReq.onerror = function (e) {\r\n };\r\n unoMenuReq.send();\r\n }\r\n\r\n $(document).ajaxComplete(function (event, xhr, settings) {\r\n const docFxNavbarHasLoaded = settings.url === \"toc.html\";\r\n\r\n if (docFxNavbarHasLoaded && wordpressMenuHasLoaded) {\r\n const $docfxNavbar = $navbar.getElementsByClassName(\"navbar-nav\");\r\n $docfxNavbar[0].className += \" hidden\";\r\n\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Changes the logo on resize\r\n*/\r\n\r\nfunction updateLogo() {\r\n const curWidth = window.innerWidth;\r\n const headerLogo = document.getElementById('logo');\r\n if (curWidth < 1024) {\r\n const mobileLogo = new URL('UnoLogoSmall.png', headerLogo.src).href;\r\n headerLogo.src = mobileLogo;\r\n } else {\r\n const deskLogo = new URL('uno-logo.svg', headerLogo.src).href;\r\n headerLogo.src = deskLogo;\r\n }\r\n}\r\n\r\nfunction updateLogoOnResize() {\r\n $(window).on('resize', function () {\r\n updateLogo();\r\n });\r\n}\r\n\r\n\r\n// Update href in navbar\r\nfunction renderNavbar() {\r\n const navbar = $('#navbar ul')[0];\r\n if (typeof (navbar) === 'undefined') {\r\n loadNavbar();\r\n } else {\r\n $('#navbar ul a.active').parents('li').addClass(active);\r\n renderBreadcrumb();\r\n }\r\n\r\n function loadNavbar() {\r\n let navbarPath = $(\"meta[property='docfx\\\\:navrel']\").attr(\"content\");\r\n if (!navbarPath) {\r\n return;\r\n }\r\n navbarPath = navbarPath.replace(/\\\\/g, '/');\r\n let tocPath = $(\"meta[property='docfx\\\\:tocrel']\").attr(\"content\") || '';\r\n if (tocPath) tocPath = tocPath.replace(/\\\\/g, '/');\r\n $.get(navbarPath, function (data) {\r\n $(data).find(\"#toc>ul\").appendTo(\"#navbar\");\r\n const index = navbarPath.lastIndexOf('/');\r\n let navrel = '';\r\n if (index > -1) {\r\n navrel = navbarPath.substr(0, index + 1);\r\n }\r\n $('#navbar>ul').addClass('navbar-nav');\r\n\r\n const currentAbsPath = getAbsolutePath(window.location.pathname);\r\n\r\n // set active item\r\n $('#navbar').find('a[href]').each(function (i, e) {\r\n let href = $(e).attr(\"href\");\r\n if (isRelativePath(href)) {\r\n href = navrel + href;\r\n $(e).attr(\"href\", href);\r\n\r\n // TODO: currently only support one level navbar\r\n let isActive = false;\r\n let originalHref = e.name;\r\n if (originalHref) {\r\n originalHref = navrel + originalHref;\r\n if (getDirectory(getAbsolutePath(originalHref)) === getDirectory(getAbsolutePath(tocPath))) {\r\n isActive = true;\r\n }\r\n } else {\r\n if (getAbsolutePath(href) === currentAbsPath) {\r\n\r\n const dropdown = $(e).attr('data-toggle') === \"dropdown\";\r\n\r\n if (!dropdown) {\r\n isActive = true;\r\n }\r\n }\r\n }\r\n if (isActive) {\r\n $(e).addClass(active);\r\n }\r\n }\r\n });\r\n renderNavbar();\r\n });\r\n }\r\n}\r\n\r\nfunction renderLogo() {\r\n // For LOGO SVG\r\n // Replace SVG with inline SVG\r\n // http://stackoverflow.com/questions/11978995/how-to-change-color-of-svg-image-using-css-jquery-svg-image-replacement\r\n $('img.svg').each(function () {\r\n const $img = jQuery(this);\r\n const imgID = $img.attr('id');\r\n const imgClass = $img.attr('class');\r\n const imgURL = $img.attr('src');\r\n\r\n jQuery.get(imgURL, function (data) {\r\n // Get the SVG tag, ignore the rest\r\n let $svg = $(data).find('svg');\r\n\r\n // Add replaced image's ID to the new SVG\r\n if (typeof imgID !== 'undefined') {\r\n $svg = $svg.attr('id', imgID);\r\n }\r\n // Add replaced image's classes to the new SVG\r\n if (typeof imgClass !== 'undefined') {\r\n $svg = $svg.attr('class', imgClass + ' replaced-svg');\r\n }\r\n\r\n // Remove any invalid XML tags as per http://validator.w3.org\r\n $svg = $svg.removeAttr('xmlns:a');\r\n\r\n // Replace image with new SVG\r\n $img.replaceWith($svg);\r\n\r\n }, 'xml');\r\n });\r\n}\r\n","const sidefilterHeight = 94; //94px from sidefilter height\r\n\r\nfunction setTocHeight() {\r\n if($(window).width() < 768) {\r\n let headerHeight = $(\"#header-container\").outerHeight();\r\n let breadcrumbHeight = $(\"#breadcrumb\").outerHeight();\r\n let tocToggleHeight = $(\".btn.toc-toggle.collapse\").outerHeight();\r\n let intViewportHeight = window.innerHeight;\r\n let sidenavPaddingTop = parseInt($(\".sidenav\").css('padding-top'));\r\n let maxHeightToc = intViewportHeight - (headerHeight + breadcrumbHeight + tocToggleHeight + sidefilterHeight + sidenavPaddingTop);\r\n $(\".sidetoc\").css(\"max-height\", maxHeightToc);\r\n } else {\r\n $(\".sidetoc\").css(\"max-height\", \"none\");\r\n }\r\n}\r\n\r\nfunction updateTocHeightOnResize() {\r\n $(window).on('resize', function () {\r\n setTocHeight();\r\n });\r\n}\r\n\r\nfunction setSidenavTop() {\r\n let headerHeight = $(\"#header-container\").outerHeight();\r\n let breadcrumbHeight = $(\"#breadcrumb\").outerHeight();\r\n let tocToggleHeight = $(\".btn.toc-toggle.collapse\").outerHeight();\r\n let sidenavTop = headerHeight + breadcrumbHeight;\r\n let sidefilterTop = headerHeight + breadcrumbHeight;\r\n let sidetocTop = sidefilterTop + sidefilterHeight;\r\n let articleMarginTopDesk = sidenavTop + tocToggleHeight + 30; //30px from .sidenav padding top and bottom\r\n let articleMarginTopMobile = sidenavTop;\r\n $(\".sidenav\").css(\"top\", sidenavTop);\r\n $(\".sidefilter\").css(\"top\", sidenavTop);\r\n $(\".sidetoc\").css(\"top\", sidetocTop);\r\n\r\n if($(window).width() < 768) {\r\n $(\".body-content .article\").attr(\"style\", \"margin-top:\" + (articleMarginTopDesk + 5) + \"px !important\");\r\n } else {\r\n $(\".body-content .article\").attr(\"style\", \"margin-top:\" + (articleMarginTopMobile + 5) + \"px !important\");\r\n }\r\n}\r\n\r\nfunction updateSidenavTopOnResize() {\r\n $(window).on('resize', function () {\r\n setSidenavTop();\r\n });\r\n}\r\n\r\nfunction renderSidebar() {\r\n\r\n const sideToggleSideToc = $('#sidetoggle .sidetoc')[0];\r\n const footer = $('footer');\r\n const sidetoc = $('.sidetoc');\r\n\r\n if (typeof (sideToggleSideToc) === 'undefined') {\r\n loadToc();\r\n } else {\r\n registerTocEvents();\r\n if (footer.is(':visible')) {\r\n sidetoc.addClass('shiftup');\r\n }\r\n\r\n // Scroll to active item\r\n let top = 0;\r\n $('#toc a.active').parents('li').each(function (i, e) {\r\n $(e).addClass(active).addClass(expanded);\r\n $(e).children('a').addClass(active);\r\n top += $(e).position().top;\r\n })\r\n\r\n sidetoc.scrollTop(top - 50);\r\n\r\n if (footer.is(':visible')) {\r\n sidetoc.addClass('shiftup');\r\n }\r\n\r\n if (window.location.href.indexOf(\"articles/intro.html\") > -1 && $(window).width() > 850) {\r\n $('.nav.level1 li:eq(1)').addClass(expanded);\r\n }\r\n\r\n renderBreadcrumb();\r\n setSidenavTop();\r\n setTocHeight();\r\n }\r\n\r\n function registerTocEvents() {\r\n $('.toc .nav > li > .expand-stub').on('click', function (e) {\r\n $(e.target).parent().toggleClass(expanded);\r\n });\r\n $('.toc .nav > li > .expand-stub + a:not([href])').on('click', function (e) {\r\n $(e.target).parent().toggleClass(expanded);\r\n });\r\n $('#toc_filter_input').on('input', function () {\r\n const val = this.value;\r\n if (val === '') {\r\n // Clear 'filtered' class\r\n $('#toc li').removeClass(filtered).removeClass(hide);\r\n return;\r\n }\r\n\r\n // Get leaf nodes\r\n const tocLineAnchor = $('#toc li>a');\r\n\r\n tocLineAnchor.filter(function (i, e) {\r\n return $(e).siblings().length === 0\r\n }).each(function (j, anchor) {\r\n let text = $(anchor).attr('title');\r\n const parent = $(anchor).parent();\r\n const parentNodes = parent.parents('ul>li');\r\n for (let k = 0; k < parentNodes.length; k++) {\r\n let parentText = $(parentNodes[k]).children('a').attr('title');\r\n if (parentText) text = parentText + '.' + text;\r\n }\r\n\r\n if (filterNavItem(text, val)) {\r\n parent.addClass(show);\r\n parent.removeClass(hide);\r\n } else {\r\n parent.addClass(hide);\r\n parent.removeClass(show);\r\n }\r\n });\r\n\r\n tocLineAnchor.filter(function (i, e) {\r\n return $(e).siblings().length > 0\r\n }).each(function (i, anchor) {\r\n const parent = $(anchor).parent();\r\n if (parent.find('li.show').length > 0) {\r\n parent.addClass(show);\r\n parent.addClass(filtered);\r\n parent.removeClass(hide);\r\n } else {\r\n parent.addClass(hide);\r\n parent.removeClass(show);\r\n parent.removeClass(filtered);\r\n }\r\n })\r\n\r\n function filterNavItem(name, text) {\r\n\r\n if (!text) return true;\r\n\r\n return name && name.toLowerCase().indexOf(text.toLowerCase()) > -1;\r\n\r\n }\r\n });\r\n }\r\n\r\n function loadToc() {\r\n let tocPath = $(\"meta[property='docfx\\\\:tocrel']\").attr(\"content\");\r\n\r\n if (!tocPath) {\r\n return;\r\n }\r\n tocPath = tocPath.replace(/\\\\/g, '/');\r\n $('#sidetoc').load(tocPath + \" #sidetoggle > div\", function () {\r\n const index = tocPath.lastIndexOf('/');\r\n let tocrel = '';\r\n\r\n if (index > -1) {\r\n tocrel = tocPath.substr(0, index + 1);\r\n }\r\n\r\n const currentHref = getAbsolutePath(window.location.pathname);\r\n\r\n $('#sidetoc').find('a[href]').each(function (i, e) {\r\n let href = $(e).attr(\"href\");\r\n if (isRelativePath(href)) {\r\n href = tocrel + href;\r\n $(e).attr(\"href\", href);\r\n }\r\n\r\n if (getAbsolutePath(e.href) === currentHref) {\r\n $(e).addClass(active);\r\n }\r\n\r\n $(e).breakWord();\r\n });\r\n\r\n renderSidebar();\r\n const body = $('body');\r\n const searchResult = $('#search-results');\r\n\r\n if (searchResult.length !== 0) {\r\n $('#search').show();\r\n body.trigger(\"searchEvent\");\r\n }\r\n\r\n // if the target of the click isn't the container nor a descendant of the container\r\n body.on('mouseup', function (e) {\r\n if (!searchResult.is(e.target) && searchResult.has(e.target).length === 0) {\r\n searchResult.hide();\r\n }\r\n });\r\n });\r\n }\r\n}\r\n","function renderTabs() {\r\n\r\n const contentAttrs = {\r\n id: 'data-bi-id',\r\n name: 'data-bi-name',\r\n type: 'data-bi-type'\r\n };\r\n\r\n const Tab = (function () {\r\n function Tab(li, a, section) {\r\n this.li = li;\r\n this.a = a;\r\n this.section = section;\r\n }\r\n\r\n Object.defineProperty(Tab.prototype, \"tabIds\", {\r\n get: function () {\r\n return this.a.getAttribute('data-tab').split(' ');\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Object.defineProperty(Tab.prototype, \"condition\", {\r\n get: function () {\r\n return this.a.getAttribute('data-condition');\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Object.defineProperty(Tab.prototype, \"visible\", {\r\n get: function () {\r\n return !this.li.hasAttribute('hidden');\r\n },\r\n set: function (value) {\r\n if (value) {\r\n this.li.removeAttribute('hidden');\r\n this.li.removeAttribute('aria-hidden');\r\n } else {\r\n this.li.setAttribute('hidden', 'hidden');\r\n this.li.setAttribute('aria-hidden', 'true');\r\n }\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Object.defineProperty(Tab.prototype, \"selected\", {\r\n get: function () {\r\n return !this.section.hasAttribute('hidden');\r\n },\r\n set: function (value) {\r\n if (value) {\r\n this.a.setAttribute('aria-selected', 'true');\r\n this.a.tabIndex = 0;\r\n this.section.removeAttribute('hidden');\r\n this.section.removeAttribute('aria-hidden');\r\n } else {\r\n this.a.setAttribute('aria-selected', 'false');\r\n this.a.tabIndex = -1;\r\n this.section.setAttribute('hidden', 'hidden');\r\n this.section.setAttribute('aria-hidden', 'true');\r\n }\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n\r\n Tab.prototype.focus = function () {\r\n this.a.focus();\r\n };\r\n\r\n return Tab;\r\n\r\n }());\r\n\r\n initTabs(document.body);\r\n\r\n function initTabs(container) {\r\n const queryStringTabs = readTabsQueryStringParam();\r\n const elements = container.querySelectorAll('.tabGroup');\r\n const state = {groups: [], selectedTabs: []};\r\n for (let i = 0; i < elements.length; i++) {\r\n const group = initTabGroup(elements.item(i));\r\n if (!group.independent) {\r\n updateVisibilityAndSelection(group, state);\r\n state.groups.push(group);\r\n }\r\n }\r\n container.addEventListener('click', function (event) {\r\n return handleClick(event, state);\r\n });\r\n if (state.groups.length === 0) {\r\n return state;\r\n }\r\n selectTabs(queryStringTabs, container);\r\n updateTabsQueryStringParam(state);\r\n notifyContentUpdated();\r\n return state;\r\n }\r\n\r\n function initTabGroup(element) {\r\n\r\n const group = {\r\n independent: element.hasAttribute('data-tab-group-independent'),\r\n tabs: []\r\n };\r\n\r\n let li = element.firstElementChild.firstElementChild;\r\n while (li) {\r\n const a = li.firstElementChild;\r\n a.setAttribute(contentAttrs.name, 'tab');\r\n\r\n const dataTab = a.getAttribute('data-tab').replace(/\\+/g, ' ');\r\n a.setAttribute('data-tab', dataTab);\r\n\r\n const section = element.querySelector(\"[id=\\\"\" + a.getAttribute('aria-controls') + \"\\\"]\");\r\n const tab = new Tab(li, a, section);\r\n group.tabs.push(tab);\r\n\r\n li = li.nextElementSibling;\r\n }\r\n\r\n element.setAttribute(contentAttrs.name, 'tab-group');\r\n element.tabGroup = group;\r\n\r\n return group;\r\n }\r\n\r\n function updateVisibilityAndSelection(group, state) {\r\n let anySelected = false;\r\n let firstVisibleTab;\r\n\r\n for (let _i = 0, _a = group.tabs; _i < _a.length; _i++) {\r\n let tab = _a[_i];\r\n tab.visible = tab.condition === null || state.selectedTabs.indexOf(tab.condition) !== -1;\r\n if (tab.visible) {\r\n if (!firstVisibleTab) {\r\n firstVisibleTab = tab;\r\n }\r\n }\r\n tab.selected = tab.visible && arraysIntersect(state.selectedTabs, tab.tabIds);\r\n anySelected = anySelected || tab.selected;\r\n }\r\n\r\n if (!anySelected) {\r\n for (let _b = 0, _c = group.tabs; _b < _c.length; _b++) {\r\n const tabIds = _c[_b].tabIds;\r\n for (let _d = 0, tabIds_1 = tabIds; _d < tabIds_1.length; _d++) {\r\n const tabId = tabIds_1[_d];\r\n const index = state.selectedTabs.indexOf(tabId);\r\n if (index === -1) {\r\n continue;\r\n }\r\n state.selectedTabs.splice(index, 1);\r\n }\r\n }\r\n const tab = firstVisibleTab;\r\n tab.selected = true;\r\n state.selectedTabs.push(tab.tabIds[0]);\r\n }\r\n }\r\n\r\n function getTabInfoFromEvent(event) {\r\n\r\n if (!(event.target instanceof HTMLElement)) {\r\n return null;\r\n }\r\n\r\n const anchor = event.target.closest('a[data-tab]');\r\n\r\n if (anchor === null) {\r\n return null;\r\n }\r\n\r\n const tabIds = anchor.getAttribute('data-tab').split(' ');\r\n const group = anchor.parentElement.parentElement.parentElement.tabGroup;\r\n\r\n if (group === undefined) {\r\n return null;\r\n }\r\n\r\n return {tabIds: tabIds, group: group, anchor: anchor};\r\n }\r\n\r\n function handleClick(event, state) {\r\n const info = getTabInfoFromEvent(event);\r\n\r\n if (info === null) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n info.anchor.href = 'javascript:';\r\n\r\n setTimeout(function () {\r\n return info.anchor.href = '#' + info.anchor.getAttribute('aria-controls');\r\n });\r\n\r\n const tabIds = info.tabIds, group = info.group;\r\n const originalTop = info.anchor.getBoundingClientRect().top;\r\n\r\n if (group.independent) {\r\n for (let _i = 0, _a = group.tabs; _i < _a.length; _i++) {\r\n const tab = _a[_i];\r\n tab.selected = arraysIntersect(tab.tabIds, tabIds);\r\n }\r\n } else {\r\n if (arraysIntersect(state.selectedTabs, tabIds)) {\r\n return;\r\n }\r\n const previousTabId = group.tabs.filter(function (t) {\r\n return t.selected;\r\n })[0].tabIds[0];\r\n state.selectedTabs.splice(state.selectedTabs.indexOf(previousTabId), 1, tabIds[0]);\r\n for (let _b = 0, _c = state.groups; _b < _c.length; _b++) {\r\n const group_1 = _c[_b];\r\n updateVisibilityAndSelection(group_1, state);\r\n }\r\n updateTabsQueryStringParam(state);\r\n }\r\n notifyContentUpdated();\r\n const top = info.anchor.getBoundingClientRect().top;\r\n if (top !== originalTop && event instanceof MouseEvent) {\r\n window.scrollTo(0, window.pageYOffset + top - originalTop);\r\n }\r\n }\r\n\r\n function selectTabs(tabIds) {\r\n for (let _i = 0, tabIds_1 = tabIds; _i < tabIds_1.length; _i++) {\r\n const tabId = tabIds_1[_i];\r\n const a = document.querySelector(\".tabGroup > ul > li > a[data-tab=\\\"\" + tabId + \"\\\"]:not([hidden])\");\r\n\r\n if (a === null) {\r\n return;\r\n }\r\n\r\n a.dispatchEvent(new CustomEvent('click', {bubbles: true}));\r\n }\r\n }\r\n\r\n function readTabsQueryStringParam() {\r\n const qs = parseQueryString();\r\n const t = qs.tabs;\r\n\r\n if (t === undefined || t === '') {\r\n return [];\r\n }\r\n\r\n return t.split(',');\r\n }\r\n\r\n function updateTabsQueryStringParam(state) {\r\n const qs = parseQueryString();\r\n qs.tabs = state.selectedTabs.join();\r\n\r\n const url = location.protocol + \"//\" + location.host + location.pathname + \"?\" + toQueryString(qs) + location.hash;\r\n\r\n if (location.href === url) {\r\n return;\r\n }\r\n\r\n history.replaceState({}, document.title, url);\r\n }\r\n\r\n function toQueryString(args) {\r\n const parts = [];\r\n\r\n for (let name_1 in args) {\r\n if (args.hasOwnProperty(name_1) && args[name_1] !== '' && args[name_1] !== null && args[name_1] !== undefined) {\r\n parts.push(encodeURIComponent(name_1) + '=' + encodeURIComponent(args[name_1]));\r\n }\r\n }\r\n\r\n return parts.join('&');\r\n }\r\n\r\n function parseQueryString(queryString) {\r\n let match;\r\n const pl = /\\+/g;\r\n const search = /([^&=]+)=?([^&]*)/g;\r\n\r\n const decode = function (s) {\r\n return decodeURIComponent(s.replace(pl, ' '));\r\n };\r\n\r\n if (queryString === undefined) {\r\n queryString = '';\r\n }\r\n\r\n queryString = queryString.substring(1);\r\n const urlParams = {};\r\n\r\n while (match = search.exec(queryString)) {\r\n urlParams[decode(match[1])] = decode(match[2]);\r\n }\r\n\r\n return urlParams;\r\n }\r\n\r\n function arraysIntersect(a, b) {\r\n for (let _i = 0, a_1 = a; _i < a_1.length; _i++) {\r\n const itemA = a_1[_i];\r\n\r\n for (let _a = 0, b_1 = b; _a < b_1.length; _a++) {\r\n const itemB = b_1[_a];\r\n if (itemA === itemB) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n function notifyContentUpdated() {\r\n // Dispatch this event when needed\r\n // window.dispatchEvent(new CustomEvent('content-update'));\r\n }\r\n}\r\n","/**\r\n * Styling for tables in conceptual documents using Bootstrap.\r\n * See http://getbootstrap.com/css/#tables\r\n */\r\nfunction renderTables() {\r\n $('table').addClass('table table-bordered table-striped table-condensed').wrap('
');\r\n}\r\n","window.refresh = function (article) {\r\n\r\n // Update markup result\r\n if (typeof article == 'undefined' || typeof article.content == 'undefined') {\r\n console.error(\"Null Argument\");\r\n }\r\n\r\n $(\"article.content\").html(article.content);\r\n\r\n highlight();\r\n renderTables();\r\n renderAlerts();\r\n renderAffix();\r\n renderTabs();\r\n}\r\n\r\n$(document).on('wordpressMenuHasLoaded', function () {\r\n const path = window.location.pathname;\r\n const docsUrl = '/docs/articles/';\r\n const wpNavBar = document.getElementById('menu-menu-principal');\r\n const items = wpNavBar.getElementsByTagName('a');\r\n\r\n for (let i = 0; i < items.length; i++) {\r\n\r\n if (items[i].href.includes(docsUrl) && path.includes(docsUrl) && !items[i].href.includes('#')) {\r\n $(items[i]).addClass('activepath');\r\n }\r\n }\r\n\r\n const queryString = window.location.search;\r\n\r\n if (queryString) {\r\n const queryStringComponents = queryString.split('=');\r\n const searchParam = queryStringComponents.slice(-1)[0];\r\n $('#search-query').val(decodeURI(searchParam));\r\n }\r\n\r\n});\r\n\r\n\r\n// Enable anchors for headings.\r\n(function () {\r\n anchors.options = {\r\n placement: 'right',\r\n visible: 'hover',\r\n icon: '#'\r\n };\r\n anchors.add('article h2:not(.no-anchor), article h3:not(.no-anchor), article h4:not(.no-anchor)');\r\n})();\r\n","// Enable highlight.js\r\nfunction highlight() {\r\n\r\n $('pre code').each(function (i, block) {\r\n hljs.highlightBlock(block);\r\n });\r\n\r\n $('pre code[highlight-lines]').each(function (i, block) {\r\n if (block.innerHTML === \"\") return;\r\n const lines = block.innerHTML.split('\\n');\r\n\r\n const queryString = block.getAttribute('highlight-lines');\r\n if (!queryString) return;\r\n\r\n let rangesString = queryString.split(',');\r\n let ranges = rangesString.map(Number);\r\n\r\n for (let range of ranges) {\r\n const found = range.match(/^(\\d+)\\-(\\d+)?$/);\r\n let start = 0;\r\n let end = 0;\r\n if (found) {\r\n // consider region as `{startlinenumber}-{endlinenumber}`, in which {endlinenumber} is optional\r\n start = +found[1];\r\n end = +found[2];\r\n if (isNaN(end) || end > lines.length) {\r\n end = lines.length;\r\n }\r\n } else {\r\n // consider region as a sigine line number\r\n if (isNaN(range)) continue;\r\n start = +range;\r\n end = start;\r\n }\r\n if (start <= 0 || end <= 0 || start > end || start > lines.length) {\r\n // skip current region if invalid\r\n continue;\r\n }\r\n lines[start - 1] = '' + lines[start - 1];\r\n lines[end - 1] = lines[end - 1] + '';\r\n }\r\n\r\n block.innerHTML = lines.join('\\n');\r\n });\r\n}\r\n\r\n// Support full-text-search\r\nfunction enableSearch() {\r\n let query;\r\n const relHref = $(\"meta[property='docfx\\\\:rel']\").attr(\"content\");\r\n\r\n if (typeof relHref === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n const worker = new Worker(relHref + 'styles/search-worker.js');\r\n if (!worker && !window.worker) {\r\n localSearch();\r\n } else {\r\n webWorkerSearch(worker);\r\n }\r\n renderSearchBox();\r\n highlightKeywords();\r\n addSearchEvent();\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n\r\n //Adjust the position of search box in navbar\r\n function renderSearchBox() {\r\n autoCollapse();\r\n\r\n $(window).on('resize', () => autoCollapse());\r\n\r\n $(document).on('click', '.navbar-collapse.in', function (e) {\r\n if ($(e.target).is('a')) {\r\n $(this).collapse(hide);\r\n }\r\n });\r\n\r\n function autoCollapse() {\r\n const navbar = $('#autocollapse');\r\n if (navbar.height() === null) {\r\n setTimeout(autoCollapse, 300);\r\n }\r\n navbar.removeClass(collapsed);\r\n if (navbar.height() > 60) {\r\n navbar.addClass(collapsed);\r\n }\r\n }\r\n }\r\n\r\n // Search factory\r\n function localSearch() {\r\n const lunrIndex = lunr(function () {\r\n this.ref('href');\r\n this.field('title', {boost: 50});\r\n this.field('keywords', {boost: 20});\r\n });\r\n lunr.tokenizer.seperator = /[\\s\\-\\.]+/;\r\n let searchData = {};\r\n const searchDataRequest = new XMLHttpRequest();\r\n\r\n const indexPath = relHref + \"index.json\";\r\n if (indexPath) {\r\n searchDataRequest.open('GET', indexPath);\r\n searchDataRequest.onload = function () {\r\n if (this.status !== 200) {\r\n return;\r\n }\r\n searchData = JSON.parse(this.responseText);\r\n for (let prop in searchData) {\r\n if (searchData.hasOwnProperty(prop)) {\r\n lunrIndex.add(searchData[prop]);\r\n }\r\n }\r\n }\r\n searchDataRequest.send();\r\n }\r\n\r\n $(\"body\").on(\"queryReady\", function () {\r\n const hits = lunrIndex.search(query);\r\n const results = [];\r\n hits.forEach(function (hit) {\r\n const item = searchData[hit.ref];\r\n results.push({'href': item.href, 'title': item.title, 'keywords': item.keywords});\r\n });\r\n handleSearchResults(results);\r\n });\r\n }\r\n\r\n function webWorkerSearch(worker) {\r\n const indexReady = $.Deferred();\r\n worker.onmessage = function (oEvent) {\r\n switch (oEvent.data.e) {\r\n case 'index-ready':\r\n indexReady.resolve();\r\n break;\r\n case 'query-ready':\r\n const hits = oEvent.data.d;\r\n handleSearchResults(hits);\r\n break;\r\n }\r\n }\r\n\r\n indexReady.promise().done(function () {\r\n\r\n $(\"body\").on(\"query-ready\", function () {\r\n postSearchQuery(worker, query);\r\n });\r\n\r\n postSearchQuery(worker, query);\r\n\r\n });\r\n }\r\n\r\n /**\r\n * This function posts the message to the worker if the string has at least\r\n * three characters.\r\n *\r\n * @param worker The search worker used by docfx (lunr)\r\n * @param searchQuery The string to post to the worker.\r\n */\r\n function postSearchQuery(worker, searchQuery) {\r\n if (searchQuery && (searchQuery.length >= 3)) {\r\n worker.postMessage({q: `${searchQuery}*`});\r\n } else {\r\n worker.postMessage({q: ''});\r\n }\r\n }\r\n\r\n /**\r\n * Highlight the searching keywords\r\n */\r\n function highlightKeywords() {\r\n const q = url('?q');\r\n if (q != null) {\r\n const keywords = q.split(\"%20\");\r\n keywords.forEach(function (keyword) {\r\n if (keyword !== \"\") {\r\n $('.data-searchable *').mark(keyword);\r\n $('article *').mark(keyword);\r\n }\r\n });\r\n }\r\n }\r\n\r\n function addSearchEvent() {\r\n $('body').on(\"searchEvent\", function () {\r\n $('#search-results>.sr-items').html('

No results found

');\r\n\r\n const searchQuery = $('#search-query');\r\n\r\n searchQuery.on('input', function (e) {\r\n return e.key !== 'Enter';\r\n });\r\n\r\n searchQuery.on(\"keyup\", function (e) {\r\n $('#search-results').show();\r\n query = `${e.target.value}`;\r\n $(\"body\").trigger(\"query-ready\");\r\n $('#search-results>.search-list').text('Search Results for \"' + query + '\"');\r\n }).off(\"keydown\");\r\n });\r\n }\r\n\r\n function relativeUrlToAbsoluteUrl(currentUrl, relativeUrl) {\r\n const currentItems = currentUrl.split(/\\/+/);\r\n const relativeItems = relativeUrl.split(/\\/+/);\r\n let depth = currentItems.length - 1;\r\n const items = [];\r\n for (let i = 0; i < relativeItems.length; i++) {\r\n if (relativeItems[i] === '..') {\r\n depth--;\r\n } else if (relativeItems[i] !== '.') {\r\n items.push(relativeItems[i]);\r\n }\r\n }\r\n return currentItems.slice(0, depth).concat(items).join('/');\r\n }\r\n\r\n function extractContentBrief(content) {\r\n const briefOffset = 50;\r\n const words = query.split(/\\s+/g);\r\n const queryIndex = content.indexOf(words[0]);\r\n\r\n if (queryIndex > briefOffset) {\r\n return \"...\" + content.slice(queryIndex - briefOffset, queryIndex + briefOffset) + \"...\";\r\n } else if (queryIndex <= briefOffset) {\r\n return content.slice(0, queryIndex + briefOffset) + \"...\";\r\n }\r\n }\r\n\r\n function handleSearchResults(hits) {\r\n if (hits.length === 0) {\r\n $('#search-results>.sr-items').html('

No results found

');\r\n } else {\r\n $('#search-results>.sr-items').empty().append(\r\n hits.slice(0, 20).map(function (hit) {\r\n const currentUrl = window.location.href;\r\n\r\n const itemRawHref = relativeUrlToAbsoluteUrl(currentUrl, relHref + hit.href);\r\n const itemHref = relHref + hit.href + \"?q=\" + query;\r\n const itemTitle = hit.title;\r\n const itemBrief = extractContentBrief(hit.keywords);\r\n\r\n const itemNode = $('').attr('class', 'sr-item').attr('href', itemHref);\r\n const itemTitleNode = $('
').attr('class', 'item-title').text(itemTitle);\r\n const itemBriefNode = $('
').attr('class', 'item-brief').text(itemBrief);\r\n itemNode.append(itemTitleNode).append(itemBriefNode);\r\n\r\n return itemNode;\r\n })\r\n );\r\n query.split(/\\s+/).forEach(function (word) {\r\n if (word !== '') {\r\n word = word.replace(/\\*/g, '');\r\n $('#search-results>.sr-items *').mark(word);\r\n }\r\n });\r\n }\r\n }\r\n}\r\n","function getAbsolutePath(href) {\r\n // Use anchor to normalize href\r\n const anchor = $('')[0];\r\n // Ignore protocal, remove search and query\r\n return anchor.host + anchor.pathname;\r\n}\r\n\r\nfunction isRelativePath(href) {\r\n if (href === undefined || href === '' || href[0] === '/') {\r\n return false;\r\n }\r\n return !isAbsolutePath(href);\r\n}\r\n\r\nfunction isAbsolutePath(href) {\r\n return (/^(?:[a-z]+:)?\\/\\//i).test(href);\r\n}\r\n\r\nfunction getDirectory(href) {\r\n if (!href) {\r\n return '';\r\n }\r\n\r\n const index = href.lastIndexOf('/');\r\n\r\n if (index === -1) {\r\n return '';\r\n }\r\n\r\n if (index > -1) {\r\n return href.substr(0, index);\r\n }\r\n}\r\n\r\nfunction formList(item, classes) {\r\n let level = 1;\r\n const model = {\r\n items: item\r\n };\r\n\r\n const cls = [].concat(classes).join(\" \");\r\n return getList(model, cls);\r\n\r\n function getList(model, cls) {\r\n\r\n if (!model || !model.items) {\r\n return null;\r\n }\r\n\r\n const l = model.items.length;\r\n\r\n if (l === 0) {\r\n return null;\r\n }\r\n\r\n let html = '
    ';\r\n level++;\r\n\r\n for (let i = 0; i < l; i++) {\r\n const item = model.items[i];\r\n const href = item.href;\r\n const name = item.name;\r\n\r\n if (!name) {\r\n continue;\r\n }\r\n\r\n html += href ? '
  • ' + name + '' : '
  • ' + name;\r\n html += getList(item, cls) || '';\r\n html += '
  • ';\r\n }\r\n\r\n html += '
';\r\n return html;\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Add into long word.\r\n * @param {String} text - The word to break. It should be in plain text without HTML tags.\r\n */\r\nfunction breakPlainText(text) {\r\n if (!text) return text;\r\n return text.replace(/([a-z])([A-Z])|(\\.)(\\w)/g, '$1$3$2$4')\r\n}\r\n\r\n/**\r\n * Add into long word. The jQuery element should contain no html tags.\r\n * If the jQuery element contains tags, this function will not change the element.\r\n */\r\nfunction breakWord() {\r\n if (this.html() === this.text()) {\r\n this.html(function (index, text) {\r\n return breakPlainText(text);\r\n })\r\n }\r\n\r\n return this;\r\n}\r\n\r\n/**\r\n * adjusted from https://stackoverflow.com/a/13067009/1523776\r\n */\r\nfunction workAroundFixedHeaderForAnchors() {\r\n const HISTORY_SUPPORT = !!(history && history.pushState);\r\n const ANCHOR_REGEX = /^#[^ ]+$/;\r\n\r\n function getFixedOffset() {\r\n return $('header').first().height();\r\n }\r\n\r\n /**\r\n * If the provided href is an anchor which resolves to an element on the\r\n * page, scroll to it.\r\n * @param {String} href destination\r\n * @param {Boolean} pushToHistory push to history\r\n * @return {Boolean} - Was the href an anchor.\r\n */\r\n function scrollIfAnchor(href, pushToHistory) {\r\n let match, rect, anchorOffset;\r\n\r\n if (!ANCHOR_REGEX.test(href)) {\r\n return false;\r\n }\r\n\r\n match = document.getElementById(href.slice(1));\r\n\r\n if (match) {\r\n rect = match.getBoundingClientRect();\r\n anchorOffset = window.pageYOffset + rect.top - getFixedOffset();\r\n window.scrollTo(window.pageXOffset, anchorOffset);\r\n\r\n // Add the state to history as-per normal anchor links\r\n if (HISTORY_SUPPORT && pushToHistory) {\r\n history.pushState({}, document.title, location.pathname + href);\r\n }\r\n }\r\n\r\n return !!match;\r\n }\r\n\r\n /**\r\n * Attempt to scroll to the current location's hash.\r\n */\r\n function scrollToCurrent() {\r\n scrollIfAnchor(window.location.hash, false);\r\n }\r\n\r\n $(window).on('hashchange', () => scrollToCurrent());\r\n // Exclude tabbed content case\r\n scrollToCurrent();\r\n\r\n $(document).on('ready', function () {\r\n $('body').scrollspy({offset: 150});\r\n });\r\n}\r\n\r\nfunction breakText() {\r\n $(\".xref\").addClass(\"text-break\");\r\n const texts = $(\".text-break\");\r\n texts.each(function () {\r\n $(this).breakWord();\r\n });\r\n}\r\n"]} \ No newline at end of file