├── .editorconfig ├── .gitattribute ├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ └── gh-page.yml ├── .gitignore ├── .gitmodules ├── Conceptual.html.liquid ├── ContentTemplate ├── Conceptual.mta.json.js ├── Home.html.primary.js ├── Home.html.primary.tmpl ├── Home.mta.json.js ├── NetDelegate.html.primary.js ├── NetDelegate.html.primary.tmpl ├── NetDelegate.mta.json.js ├── NetDelegate.mta.json.tmpl ├── NetEnum.html.primary.js ├── NetEnum.html.primary.tmpl ├── NetEnum.mta.json.js ├── NetEnum.mta.json.tmpl ├── NetMember.html.primary.js ├── NetMember.html.primary.tmpl ├── NetMember.mta.json.js ├── NetMember.mta.json.tmpl ├── NetNamespace.html.primary.js ├── NetNamespace.html.primary.tmpl ├── NetNamespace.mta.json.js ├── NetNamespace.mta.json.tmpl ├── NetType.html.primary.js ├── NetType.html.primary.tmpl ├── NetType.mta.json.js ├── NetType.mta.json.tmpl ├── chrome.common.js ├── common.js ├── content.common.js ├── op.common.js ├── partials │ └── dotnet │ │ ├── additionalNotes.tmpl.partial │ │ ├── additionalNotesWithBigHeader.tmpl.partial │ │ ├── additionalRequirements.tmpl.partial │ │ ├── attribute.tmpl.partial │ │ ├── clsCompliantAlternative.tmpl.partial │ │ ├── deprecated.tmpl.partial │ │ ├── derivedClass.tmpl.partial │ │ ├── examples.tmpl.partial │ │ ├── implement.tmpl.partial │ │ ├── inheritance.tmpl.partial │ │ ├── member.tmpl.partial │ │ ├── memberCommon.tmpl.partial │ │ ├── moniker.tmpl.partial │ │ ├── monikerBoilerplate.tmpl.partial │ │ ├── monikerOverloadMember.tmpl.partial │ │ ├── name-summary-td.tmpl.partial │ │ ├── overloadMember.tmpl.partial │ │ ├── parameters.tmpl.partial │ │ ├── remarks.tmpl.partial │ │ ├── returns.tmpl.partial │ │ ├── security.tmpl.partial │ │ ├── seeAlso.tmpl.partial │ │ ├── summary.tmpl.partial │ │ ├── syntax.tmpl.partial │ │ ├── transform.js │ │ ├── typeContent.tmpl.partial │ │ ├── typeFooter.tmpl.partial │ │ ├── typeHeader.tmpl.partial │ │ ├── typeMember.tmpl.partial │ │ ├── typeParameters.tmpl.partial │ │ ├── uwpProperties.tmpl.partial │ │ ├── xref-fullName-title.tmpl │ │ ├── xref-fullName.tmpl │ │ ├── xref-name-summary-tr.tmpl │ │ ├── xref-name-summary.tmpl │ │ ├── xref-name-with-title.tmpl │ │ ├── xref-name.tmpl │ │ └── xref-summary.tmpl ├── schemas │ ├── Home.schema.json │ ├── Menu.schema.json │ ├── Metadata.schema.json │ ├── NetDelegate.schema.json │ ├── NetEnum.schema.json │ ├── NetMember.schema.json │ ├── NetNamespace.schema.json │ └── NetType.schema.json ├── shared.js ├── toc.json.js └── token.json ├── Home.html.liquid ├── LICENSE ├── README.md ├── Reference.html.liquid ├── _includes ├── footer.liquid ├── header.liquid ├── main.liquid ├── metabar.liquid └── toc.liquid ├── build ├── build.js ├── diff.js └── start.js ├── dist ├── docfx.css ├── docfx.js ├── glyphicons-halflings-regular-ACNUA6UY.ttf ├── glyphicons-halflings-regular-JOUF32XT.woff ├── glyphicons-halflings-regular-PIHUWCJO.eot ├── glyphicons-halflings-regular-QXYEM3FU.svg └── glyphicons-halflings-regular-W4DYDFZM.woff2 ├── package-lock.json ├── package.json ├── samples ├── codesnippet │ └── Rtf │ │ ├── Hyperlink │ │ └── RtfDocumentProcessor.cs │ │ ├── RtfBuildStep.cs │ │ └── RtfDocumentProcessor.cs ├── docfx.json ├── dotnet │ └── CatLibrary │ │ ├── CatLibrary.cs │ │ └── CatLibrary.csproj ├── index.yml ├── menu.yml ├── spec │ ├── docfx_build_manifest_file.md │ ├── docfx_design_spec.md │ ├── docfx_document_schema.md │ ├── docfx_flavored_markdown.md │ ├── docfx_incremental.md │ ├── images │ │ ├── docfx_workflow.png │ │ ├── docfx_workflow.vsdx │ │ ├── docfx_workflow_highlevel.png │ │ └── sdp_workflow.png │ ├── metadata_dotnet_spec.md │ ├── metadata_format_spec.md │ ├── sdp_design_spec.md │ ├── toc.md │ └── triple_slash_comments_spec.md ├── toc.yml └── tutorial │ ├── advanced_support_hyperlink.md │ ├── artifacts │ └── docfx.zip │ ├── docfx.exe_user_manual.md │ ├── getting-started.md │ ├── howto_add_a_customized_post_processor.md │ ├── howto_build_your_own_type_of_documentation_with_custom_plug-in.md │ ├── howto_create_custom_template.md │ ├── howto_customize_docfx_flavored_markdown.md │ ├── howto_filter_out_unwanted_apis_attributes.md │ ├── images │ ├── simple_web_page.png │ ├── toc_web_page.png │ └── web_page_with_extra_property.png │ ├── incrementalbuild │ ├── advanced_cache_file_structure.md │ ├── advanced_report_dependency.md │ ├── customize_a_post_processor_to_be_incremental.md │ ├── customize_a_processor_to_support_incremental.md │ ├── images │ │ ├── incrementalbuildframework.png │ │ └── incrementalpostprocessingframework.png │ ├── intro_incremental_build.md │ ├── intro_incremental_post_processing.md │ └── toc.yml │ ├── intro_default_template.md │ ├── intro_markdown_lite.md │ ├── intro_overwrite_files.md │ ├── intro_rest_api_documentation.md │ ├── intro_template.md │ ├── intro_toc.md │ ├── links_and_cross_references.md │ ├── toc.yml │ ├── universalreference │ ├── gen_doc_for_js.md │ ├── gen_doc_for_ts.md │ ├── intro_multiple_langs_support.md │ └── toc.yml │ ├── validate_your_markdown_files.md │ └── walkthrough │ ├── TOC.md │ ├── advanced_walkthrough.md │ ├── artifacts │ ├── walkthrough1.zip │ ├── walkthrough2.zip │ └── walkthrough3.zip │ ├── images │ ├── uid.png │ ├── walkthrough2_step3.png │ ├── walkthrough2_step4.png │ ├── walkthrough2_step5.png │ ├── walkthrough3.png │ ├── walkthrough_api.png │ ├── walkthrough_homepage.png │ ├── walkthrough_simple_homepage.png │ └── walkthrough_step5.png │ ├── walkthrough_create_a_docfx_project.md │ ├── walkthrough_create_a_docfx_project_2.md │ ├── walkthrough_generate_pdf.md │ └── walkthrough_overview.md ├── src ├── docfx.scss ├── docfx.ts ├── scripts │ ├── anchor.ts │ ├── highlight.ts │ ├── markdown.ts │ ├── nav.tsx │ ├── theme.ts │ ├── toc.tsx │ └── utility.ts └── styles │ ├── article.scss │ ├── dotnet.scss │ ├── home.scss │ ├── layout.scss │ ├── markdown.scss │ ├── nav.scss │ └── toc.scss ├── template.yml ├── tests └── screenshots │ └── expected │ ├── -1152-648-dark.png │ ├── -1152-648-light.png │ ├── -1920-1080-dark.png │ ├── -1920-1080-light.png │ ├── -375-812-dark.png │ ├── -375-812-light.png │ ├── -768-600-dark.png │ ├── -768-600-light.png │ ├── tutorial-getting-started--1152-648-dark.png │ ├── tutorial-getting-started--1152-648-light.png │ ├── tutorial-getting-started--1920-1080-dark.png │ ├── tutorial-getting-started--1920-1080-light.png │ ├── tutorial-getting-started--375-812-dark.png │ ├── tutorial-getting-started--375-812-light.png │ ├── tutorial-getting-started--768-600-dark.png │ ├── tutorial-getting-started--768-600-light.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1152-648-dark.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1152-648-light.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1920-1080-dark.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1920-1080-light.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--375-812-dark.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--375-812-light.png │ ├── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--768-600-dark.png │ └── tutorial-walkthrough-walkthrough_create_a_docfx_project_2--768-600-light.png └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | charset = utf-8 9 | indent_style = space 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 13 | 14 | [*.{json,js,yml,scss,liquid}] 15 | indent_size = 2 16 | 17 | [*.{md,yml}] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.gitattribute: -------------------------------------------------------------------------------- 1 | # Normalize line ending to LF on checkin 2 | * text=auto 3 | 4 | *.sh text eol=lf -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | build: 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest, windows-latest] 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | fetch-depth: 0 20 | submodules: true 21 | - uses: actions/setup-dotnet@v1 22 | with: 23 | dotnet-version: '6.0.x' 24 | - run: yarn 25 | - run: yarn build 26 | #- run: yarn diff 27 | # if: ${{ matrix.os == 'windows-latest' }} 28 | - uses: actions/upload-artifact@v2 29 | if: ${{ failure() }} 30 | with: 31 | name: screenshots-${{ matrix.os }} 32 | path: tests/screenshots 33 | -------------------------------------------------------------------------------- /.github/workflows/gh-page.yml: -------------------------------------------------------------------------------- 1 | name: gh-pages 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | gh-pages: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | fetch-depth: 0 14 | submodules: true 15 | - uses: actions/setup-dotnet@v1 16 | with: 17 | dotnet-version: '6.0.x' 18 | 19 | - run: yarn 20 | - run: yarn build 21 | env: 22 | DOCFX__SECRETS__GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | 24 | - uses: peaceiris/actions-gh-pages@v3 25 | with: 26 | github_token: ${{ secrets.GITHUB_TOKEN }} 27 | publish_dir: samples/_site 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | 3 | .vs 4 | .vscode 5 | bin 6 | obj 7 | _site 8 | api 9 | debug 10 | node_modules 11 | tests/screenshots/actual 12 | tests/screenshots/diff 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "extern/docfx"] 2 | path = extern/docfx 3 | url = https://github.com/dotnet/docfx 4 | -------------------------------------------------------------------------------- /Conceptual.html.liquid: -------------------------------------------------------------------------------- 1 | {%- assign layout = 'conceptual' -%} 2 | {%- assign pageType = 'conceptual' -%} 3 | {%- assign heading1 = page.rawTitle -%} 4 | 5 | {%- include main -%} -------------------------------------------------------------------------------- /ContentTemplate/Conceptual.mta.json.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. 2 | 3 | var chromeCommon = require('./chrome.common.js') 4 | 5 | exports.transform = function (model) { 6 | model.toc_rel = model._tocRel; 7 | model.layout = model.layout || "Conceptual"; 8 | delete model.conceptual; 9 | 10 | var contrib = model._op_gitContributorInformation; 11 | if (contrib && contrib.author) { 12 | contrib.contributors = contrib.contributors || []; 13 | contrib.contributors.unshift(contrib.author); 14 | } 15 | 16 | chromeCommon.makeGitHubRepoLink(model); 17 | 18 | return { 19 | content: JSON.stringify(model) 20 | } 21 | } -------------------------------------------------------------------------------- /ContentTemplate/Home.html.primary.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. 2 | 3 | exports.transform = function (model) { 4 | 5 | if (model.hero && model.hero.actions && model.hero.actions.length > 0) { 6 | model.hero.actions[0].first = true; 7 | } 8 | 9 | return model; 10 | } -------------------------------------------------------------------------------- /ContentTemplate/Home.html.primary.tmpl: -------------------------------------------------------------------------------- 1 | {{#hero}} 2 |
3 |
4 |

{{title}}

5 |
{{{description}}}
6 |
7 | {{#actions}} 8 | {{#first}} 9 | {{name}} 10 | {{/first}} 11 | {{^first}} 12 | {{name}} 13 | {{/first}} 14 | {{/actions}} 15 |
16 |
17 |
18 | {{/hero}} 19 | 20 | {{#quickstart}} 21 |
22 |
23 |

{{title}}

24 |
25 | {{{content}}} 26 |
27 |
28 |
29 | {{/quickstart}} 30 | 31 | {{#highlights.0}} 32 |
33 |
34 | {{/highlights.0}} 35 | {{#highlights}} 36 |
37 |

{{title}}

38 |
{{{content}}}
39 |
40 | {{/highlights}} 41 | {{#highlights.0}} 42 |
43 |
44 | {{/highlights.0}} 45 | -------------------------------------------------------------------------------- /ContentTemplate/Home.mta.json.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. 2 | 3 | var chromeCommon = require('./chrome.common.js') 4 | 5 | exports.transform = function (model) { 6 | model.layout = "Home"; 7 | Object.assign(model, model.metadata); 8 | 9 | chromeCommon.makeGitHubRepoLink(model); 10 | 11 | return { 12 | content: JSON.stringify(model) 13 | } 14 | } -------------------------------------------------------------------------------- /ContentTemplate/NetDelegate.html.primary.js: -------------------------------------------------------------------------------- 1 | var contentCommon = require('./content.common.js'); 2 | var dotnet = require('./partials/dotnet/transform.js'); 3 | 4 | exports.transform = function (model) { 5 | model._op_templateFilename = 'NetDelegate'; 6 | model.title = 7 | contentCommon.breakText(model.name.replace(//g, '>')) + 8 | ' ' + 9 | model.__global.delegateInSubtitle; 10 | 11 | dotnet.updateAssemblies(model); 12 | dotnet.updatePackages(model); 13 | dotnet.setRootName(model); 14 | dotnet.createChildHtmlIds(model); 15 | 16 | dotnet.updateParameters(model); 17 | dotnet.updateTypeParameters(model); 18 | dotnet.updateReturns(model); 19 | dotnet.updateMonikerizedProperties(model); 20 | dotnet.updateUWPProperties(model); 21 | dotnet.updateAdditionalRequirements(model); 22 | dotnet.updateEditButton(model); 23 | 24 | if (model.extensionMethods) { 25 | model.extensionMethodsInfo = dotnet.getTypeChildrenInfo(model, model.extensionMethods); 26 | } 27 | 28 | return model; 29 | }; 30 | -------------------------------------------------------------------------------- /ContentTemplate/NetDelegate.html.primary.tmpl: -------------------------------------------------------------------------------- 1 |

{{{title}}}

2 | 3 | {{>partials/reference-metadata}} 4 | 5 | {{>partials/dotnet/typeHeader}} 6 | {{>partials/dotnet/monikerBoilerplate}} 7 | {{>partials/dotnet/deprecated}} 8 | {{>partials/dotnet/clsCompliantAlternative}} 9 | {{>partials/dotnet/summary}} 10 | {{>partials/docOutline}} 11 | 12 | {{>partials/dotnet/syntax}} 13 | 14 | {{>partials/dotnet/typeParameters}} 15 | {{>partials/dotnet/parameters}} 16 | {{>partials/dotnet/returns}} 17 | {{>partials/dotnet/inheritance}} 18 | {{>partials/dotnet/attribute}} 19 | {{>partials/dotnet/uwpProperties}} 20 | {{>partials/dotnet/additionalRequirements}} 21 | {{>partials/dotnet/typeContent}} 22 | 23 | {{#extensionMethodsInfo}} 24 |

{{__global.extensionMethodsInSubtitle}}

25 | 26 | {{#extensionMethods}} 27 | 30 | {{>partials/dotnet/typeMember}} 31 | 32 | {{/extensionMethods}} 33 |
34 | {{/extensionMethodsInfo}} 35 | 36 | {{>partials/dotnet/moniker}} 37 | 38 | {{>partials/dotnet/typeFooter}} 39 | -------------------------------------------------------------------------------- /ContentTemplate/NetDelegate.mta.json.js: -------------------------------------------------------------------------------- 1 | var opCommon = require('./op.common.js'); 2 | var chromeCommon = require('./chrome.common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | chromeCommon.preProcessSDPMetadata(model); 7 | model.layout = 'Reference'; 8 | model._op_layout = model.layout; 9 | model.page_type = 'dotnet'; 10 | model.page_kind = 'delegate'; 11 | 12 | model['ms.assetid'] = model['ms.assetid'] || opCommon.getAssetId(model); 13 | 14 | dotnet.updateTitleForMeta(model, model.__global.delegateInSubtitle); 15 | 16 | chromeCommon.makeTitle(model); 17 | model.description = model.description || chromeCommon.replaceXrefTags(model.summary); 18 | chromeCommon.makeDescription(model); 19 | if (!model.description) { 20 | model.description = model.__global.descriptionAPIDefault 21 | .replace('{name}', model.fullName) 22 | .replace('{namespace}', model.namespace); 23 | } 24 | chromeCommon.makeCanonicalUrl(model); 25 | 26 | model.dev_langs = model.devLangs; 27 | 28 | model.toc_asset_id = model.toc_asset_id || model._tocPath; 29 | model.toc_rel = model.toc_rel || model._tocRel; 30 | if (typeof templateUtility !== 'undefined' && model.breadcrumb_path && model._path) { 31 | model.breadcrumb_path = templateUtility.resolveSourceRelativePath( 32 | model.breadcrumb_path, 33 | model._path 34 | ); 35 | } 36 | 37 | // Clean up unused predefined properties 38 | var resetKeys = [ 39 | 'altCompliant', 40 | 'assembliesWithMoniker', 41 | 'attributeMonikers', 42 | 'attributesWithMoniker', 43 | 'capabilities', 44 | 'commentId', 45 | 'devLangs', 46 | 'examples', 47 | 'extensionMethods', 48 | 'fullName', 49 | 'inheritances', 50 | 'isDeprecated', 51 | 'isInternalOnly', 52 | 'isNotClsCompliant', 53 | 'langs', 54 | 'name', 55 | 'namesWithMoniker', 56 | 'nameWithType', 57 | 'obsoleteMessagesWithMoniker', 58 | 'osRequirements', 59 | 'packagesWithMoniker', 60 | 'parameters', 61 | 'remarks', 62 | 'returnsWithMoniker', 63 | 'sdkRequirements', 64 | 'seeAlso', 65 | 'source', 66 | 'summary', 67 | 'syntaxWithMoniker', 68 | 'typeParameters', 69 | 'uid', 70 | 'uwpRequirements' 71 | ]; 72 | 73 | model = opCommon.resetKeysAndSystemAttributes(model, resetKeys, true); 74 | 75 | opCommon.resolvePdfUrlTemplate(model); 76 | 77 | chromeCommon.processMetadata(model); 78 | 79 | return { 80 | content: JSON.stringify(model) 81 | }; 82 | }; 83 | -------------------------------------------------------------------------------- /ContentTemplate/NetDelegate.mta.json.tmpl: -------------------------------------------------------------------------------- 1 | {{{content}}} -------------------------------------------------------------------------------- /ContentTemplate/NetEnum.html.primary.js: -------------------------------------------------------------------------------- 1 | var contentCommon = require('./content.common.js'); 2 | var common = require('./common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | model._op_templateFilename = 'NetEnum'; 7 | dotnet.updateTitle(model, true, model.__global.enumInSubtitle); 8 | 9 | dotnet.updateAssemblies(model); 10 | dotnet.updatePackages(model); 11 | dotnet.setRootName(model); 12 | dotnet.createChildHtmlIds(model); 13 | dotnet.updateMonikerizedProperties(model); 14 | dotnet.updateUWPProperties(model); 15 | dotnet.updateAdditionalRequirements(model); 16 | 17 | dotnet.updateEditButton(model); 18 | 19 | updateChildren(model); 20 | 21 | if (model.isFlags && !model.summary) { 22 | model.summary = ' '; 23 | } 24 | return model; 25 | }; 26 | 27 | function updateChildren(model) { 28 | if (model.fields) { 29 | model.fieldsInfo = dotnet.getTypeChildrenInfo(model, model.fields); 30 | for (var i = 0; i < model.fields.length; i++) { 31 | if (!model.fields[i].literalValue) { 32 | model.fields[i].literalValue = null; 33 | } 34 | if (!model.fields[i].summary) { 35 | model.fields[i].summary = null; 36 | } 37 | model.fields[i].htmlId = common.getHtmlId(model.fields[i].uid); 38 | } 39 | } 40 | } 41 | 42 | function getBookmarks(model, ignoreChildren) { 43 | if (!model) return null; 44 | var bookmarks = {}; 45 | 46 | if (typeof ignoreChildren === 'undefined' || ignoreChildren === false) { 47 | if (model.fields) { 48 | model.fields.forEach(function (item) { 49 | bookmarks[item.uid] = common.getHtmlId(item.uid); 50 | }); 51 | } 52 | } 53 | 54 | // Reference's first level bookmark should have no anchor 55 | bookmarks[model.uid] = ''; 56 | return bookmarks; 57 | } 58 | 59 | exports.getOptions = function (model) { 60 | return { bookmarks: getBookmarks(model) }; 61 | }; 62 | -------------------------------------------------------------------------------- /ContentTemplate/NetEnum.html.primary.tmpl: -------------------------------------------------------------------------------- 1 |

{{{title}}}

2 | 3 | {{>partials/reference-metadata}} 4 | 5 | 6 | {{>partials/dotnet/typeHeader}} 7 | {{>partials/dotnet/monikerBoilerplate}} 8 | {{>partials/dotnet/deprecated}} 9 | {{>partials/dotnet/summary}} 10 | {{>partials/docOutline}} 11 | 12 | {{>partials/dotnet/syntax}} 13 | {{>partials/dotnet/inheritance}} 14 | {{>partials/dotnet/attribute}} 15 | {{>partials/dotnet/uwpProperties}} 16 | {{>partials/dotnet/additionalRequirements}} 17 | 18 | {{#fieldsInfo}} 19 |

{{__global.fieldsInSubtitle}}

20 | 21 | {{#fields}} 22 | 25 | 30 | 31 | 32 | 33 | {{/fields}} 34 |
26 | {{#name}} 27 | {{name}} 28 | {{/name}} 29 | {{literalValue}}{{{summary}}}
35 | {{/fieldsInfo}} 36 | 37 | {{>partials/dotnet/typeContent}} 38 | 39 | {{>partials/dotnet/moniker}} 40 | 41 | {{>partials/dotnet/typeFooter}} 42 | -------------------------------------------------------------------------------- /ContentTemplate/NetEnum.mta.json.js: -------------------------------------------------------------------------------- 1 | var opCommon = require('./op.common.js'); 2 | var chromeCommon = require('./chrome.common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | chromeCommon.preProcessSDPMetadata(model); 7 | model.layout = 'Reference'; 8 | model._op_layout = model.layout; 9 | model.page_type = 'dotnet'; 10 | model.page_kind = 'enum'; 11 | 12 | model['ms.assetid'] = model['ms.assetid'] || opCommon.getAssetId(model); 13 | 14 | dotnet.updateTitleForMeta(model, model.__global.enumInSubtitle); 15 | 16 | chromeCommon.makeTitle(model); 17 | model.description = model.description || chromeCommon.replaceXrefTags(model.summary); 18 | chromeCommon.makeDescription(model); 19 | if (!model.description) { 20 | model.description = model.__global.descriptionAPIDefault 21 | .replace('{name}', model.fullName) 22 | .replace('{namespace}', model.namespace); 23 | } 24 | chromeCommon.makeCanonicalUrl(model); 25 | 26 | model.dev_langs = model.devLangs; 27 | 28 | model.toc_asset_id = model.toc_asset_id || model._tocPath; 29 | model.toc_rel = model.toc_rel || model._tocRel; 30 | if (typeof templateUtility !== 'undefined' && model.breadcrumb_path && model._path) { 31 | model.breadcrumb_path = templateUtility.resolveSourceRelativePath( 32 | model.breadcrumb_path, 33 | model._path 34 | ); 35 | } 36 | 37 | // Clean up unused predefined properties 38 | var resetKeys = [ 39 | 'assembliesWithMoniker', 40 | 'attributeMonikers', 41 | 'attributesWithMoniker', 42 | 'capabilities', 43 | 'commentId', 44 | 'devLangs', 45 | 'examples', 46 | 'fields', 47 | 'fullName', 48 | 'inheritancesWithMoniker', 49 | 'isFlags', 50 | 'isDeprecated', 51 | 'isInternalOnly', 52 | 'langs', 53 | 'name', 54 | 'nameWithType', 55 | 'obsoleteMessagesWithMoniker', 56 | 'osRequirements', 57 | 'packagesWithMoniker', 58 | 'remarks', 59 | 'sdkRequirements', 60 | 'seeAlso', 61 | 'source', 62 | 'summary', 63 | 'syntaxWithMoniker', 64 | 'uid', 65 | 'uwpRequirements', 66 | 'xamlSyntax' 67 | ]; 68 | 69 | model = opCommon.resetKeysAndSystemAttributes(model, resetKeys, true); 70 | 71 | opCommon.resolvePdfUrlTemplate(model); 72 | 73 | chromeCommon.processMetadata(model); 74 | 75 | return { 76 | content: JSON.stringify(model) 77 | }; 78 | }; 79 | -------------------------------------------------------------------------------- /ContentTemplate/NetEnum.mta.json.tmpl: -------------------------------------------------------------------------------- 1 | {{{content}}} -------------------------------------------------------------------------------- /ContentTemplate/NetMember.html.primary.js: -------------------------------------------------------------------------------- 1 | var contentCommon = require('./content.common.js'); 2 | var opCommon = require('./op.common.js'); 3 | var common = require('./common.js'); 4 | var dotnet = require('./partials/dotnet/transform.js'); 5 | 6 | exports.transform = function (model) { 7 | model._op_templateFilename = 'NetMember'; 8 | model.isOverload = model.uid && model.members.length > 1; 9 | 10 | dotnet.updateMemberTitle(model, true); 11 | 12 | model.returnLabel = model.__global.returns; 13 | if (model.type === 'field') { 14 | model.returnLabel = model.__global.fieldValue; 15 | } else if (model.type === 'property' || model.type === 'attachedproperty') { 16 | model.returnLabel = model.__global.propertyValue; 17 | } else if (model.type === 'event') { 18 | model.returnLabel = model.__global.eventType; 19 | } 20 | 21 | updateChildren(model); 22 | dotnet.updateAssemblies(model); 23 | dotnet.updatePackages(model); 24 | 25 | dotnet.updateReturns(model); 26 | return model; 27 | }; 28 | 29 | exports.getOptions = function (model) { 30 | var bookmarks = {}; 31 | 32 | if (model.uid && model.members.length > 0) { 33 | model.members.forEach(function (item) { 34 | bookmarks[item.uid] = common.getHtmlId(item.uid); 35 | }); 36 | 37 | bookmarks[model.uid] = ''; 38 | } 39 | 40 | return { 41 | bookmarks: bookmarks 42 | }; 43 | }; 44 | 45 | function updateChildren(model) { 46 | if (model.members && model.members.length > 0) { 47 | model.membersInfo = dotnet.getTypeChildrenInfo(model, model.members); 48 | for (var k = 0; k < model.members.length; k++) { 49 | if (!model.members[k].examples) { 50 | model.members[k].examples = null; 51 | } 52 | 53 | if (!model.members[k].remarks) { 54 | model.members[k].remarks = null; 55 | } 56 | 57 | if (!model.members[k].seeAlso) { 58 | model.members[k].seeAlso = null; 59 | } 60 | 61 | if (!model.members[k].summary) { 62 | model.members[k].summary = null; 63 | } 64 | 65 | if (model.members[k].attributes && model.members[k].attributes.length > 0) { 66 | model.members[k].hasAttributes = true; 67 | } 68 | 69 | model.members[k].htmlId = common.getHtmlId(model.members[k].uid); 70 | 71 | dotnet.updateMonikerizedProperties(model.members[k]); 72 | dotnet.updateParameters(model.members[k]); 73 | dotnet.updateTypeParameters(model.members[k]); 74 | dotnet.updateExceptions(model.members[k]); 75 | dotnet.updatePermissions(model.members[k]); 76 | dotnet.updateReturns(model.members[k]); 77 | 78 | dotnet.setThreadSafety(model.members[k]); 79 | dotnet.updateEditButton(model.members[k]); 80 | dotnet.updateUWPProperties(model.members[k], model.__global.win10_introducedIn); 81 | dotnet.updateAdditionalRequirements(model.members[k]); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /ContentTemplate/NetMember.html.primary.tmpl: -------------------------------------------------------------------------------- 1 | {{^isOverload}} 2 | {{#members.0}} 3 | 4 | {{/members.0}} 5 | {{/isOverload}} 6 | 7 |

{{{title}}}

8 | 9 | {{>partials/reference-metadata}} 10 | 11 | {{>partials/dotnet/typeHeader}} 12 | {{>partials/dotnet/monikerBoilerplate}} 13 | 14 | {{#isOverload}} 15 | {{>partials/dotnet/summary}} 16 | {{/isOverload}} 17 | 18 | {{>partials/docOutline}} 19 | 20 | {{#isOverload}} 21 |

{{__global.overloads}}

22 | 23 | 24 | {{#members}} 25 | 28 | 31 | 34 | 35 | {{/members}} 36 |
29 | 30 | 32 | 33 |
37 | 38 | {{>partials/dotnet/typeContent}} 39 | 40 | {{#members}} 41 | {{>partials/dotnet/overloadMember}} 42 | {{/members}} 43 | 44 | {{/isOverload}} 45 | 46 | {{^isOverload}} 47 | {{#members}} 48 | {{>partials/dotnet/member}} 49 | {{/members}} 50 | {{/isOverload}} 51 | 52 | {{#threadSafety}} 53 |

{{__global.threadSafety}}

54 | {{{customizedContent}}} 55 | {{/threadSafety}} 56 | -------------------------------------------------------------------------------- /ContentTemplate/NetMember.mta.json.js: -------------------------------------------------------------------------------- 1 | var opCommon = require('./op.common.js'); 2 | var chromeCommon = require('./chrome.common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | chromeCommon.preProcessSDPMetadata(model); 7 | model.layout = 'Reference'; 8 | model._op_layout = model.layout; 9 | model.page_type = 'dotnet'; 10 | model.page_kind = model.type.toLowerCase(); 11 | 12 | model['ms.assetid'] = model['ms.assetid'] || opCommon.getAssetId(model); 13 | model['ms.assetid'] = model['ms.assetid'] || opCommon.getAssetId(model.members[0]); 14 | 15 | dotnet.updateMemberTitle(model, false); 16 | dotnet.addNamespaceToTitle(model); 17 | 18 | chromeCommon.makeTitle(model); 19 | model.description = model.description || chromeCommon.replaceXrefTags(model.summary); 20 | model.description = model.description || chromeCommon.replaceXrefTags(model.members[0].summary); 21 | 22 | chromeCommon.makeDescription(model); 23 | if (!model.description) { 24 | model.description = model.__global.descriptionAPIDefault 25 | .replace('{name}', model.fullName) 26 | .replace('{namespace}', model.namespace); 27 | } 28 | 29 | chromeCommon.makeCanonicalUrl(model); 30 | model.dev_langs = model.devLangs; 31 | 32 | model.toc_asset_id = model.toc_asset_id || model._tocPath; 33 | model.toc_rel = model.toc_rel || model._tocRel; 34 | if (typeof templateUtility !== 'undefined' && model.breadcrumb_path && model._path) { 35 | model.breadcrumb_path = templateUtility.resolveSourceRelativePath( 36 | model.breadcrumb_path, 37 | model._path 38 | ); 39 | } 40 | 41 | // Clean up unused predefined properties 42 | var resetKeys = [ 43 | 'assembliesWithMoniker', 44 | 'capabilities', 45 | 'commentId', 46 | 'crossInheritdocsUid', 47 | 'devLangs', 48 | 'examples', 49 | 'fullName', 50 | 'langs', 51 | 'members', 52 | 'name', 53 | 'namesWithMoniker', 54 | 'nameWithType', 55 | 'remarks', 56 | 'obsoleteMessagesWithMoniker', 57 | 'osRequirements', 58 | 'packagesWithMoniker', 59 | 'sdkRequirements', 60 | 'seeAlso', 61 | 'summary', 62 | 'threadSafety', 63 | 'type', 64 | 'uid', 65 | 'uwpProperties', 66 | 'xamlMemberSyntax' 67 | ]; 68 | 69 | model = opCommon.resetKeysAndSystemAttributes(model, resetKeys, true); 70 | 71 | opCommon.resolvePdfUrlTemplate(model); 72 | 73 | chromeCommon.processMetadata(model); 74 | 75 | return { 76 | content: JSON.stringify(model) 77 | }; 78 | }; 79 | -------------------------------------------------------------------------------- /ContentTemplate/NetMember.mta.json.tmpl: -------------------------------------------------------------------------------- 1 | {{{content}}} -------------------------------------------------------------------------------- /ContentTemplate/NetNamespace.html.primary.js: -------------------------------------------------------------------------------- 1 | var contentCommon = require('./content.common.js'); 2 | var common = require('./common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | model._op_templateFilename = 'NetNamespace'; 7 | dotnet.updateTitle(model, true, model.__global.namespace); 8 | createChildId(model); 9 | 10 | dotnet.updateEditButton(model); 11 | 12 | return model; 13 | }; 14 | 15 | function createChildId(model) { 16 | if (model.classes) { 17 | model.classes = model.classes.map(mapUidToObject); 18 | model.classesInfo = dotnet.getTypeChildrenInfo(model, model.classes); 19 | } 20 | 21 | if (model.structs) { 22 | model.structs = model.structs.map(mapUidToObject); 23 | model.structsInfo = dotnet.getTypeChildrenInfo(model, model.structs); 24 | } 25 | 26 | if (model.interfaces) { 27 | model.interfaces = model.interfaces.map(mapUidToObject); 28 | model.interfacesInfo = dotnet.getTypeChildrenInfo(model, model.interfaces); 29 | } 30 | 31 | if (model.enums) { 32 | model.enums = model.enums.map(mapUidToObject); 33 | model.enumsInfo = dotnet.getTypeChildrenInfo(model, model.enums); 34 | } 35 | 36 | if (model.delegates) { 37 | model.delegates = model.delegates.map(mapUidToObject); 38 | model.delegatesInfo = dotnet.getTypeChildrenInfo(model, model.delegates); 39 | } 40 | } 41 | 42 | function mapUidToObject(item) { 43 | return { 44 | uid: item.uid, 45 | id: common.getHtmlId(item.uid), 46 | monikers: item.monikers 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /ContentTemplate/NetNamespace.html.primary.tmpl: -------------------------------------------------------------------------------- 1 |

{{{title}}}

2 | 3 | {{>partials/reference-metadata}} 4 | 5 | {{>partials/dotnet/monikerBoilerplate}} 6 | {{>partials/dotnet/summary}} 7 | {{>partials/docOutline}} 8 | 9 | {{#classesInfo}} 10 |

14 | {{__global.classesInSubtitle}} 15 |

16 | 17 | {{#classes}} 18 | 19 | {{/classes}} 20 |
21 | {{/classesInfo}} 22 | 23 | {{#structsInfo}} 24 |

28 | {{__global.structsInSubtitle}} 29 |

30 | 31 | {{#structs}} 32 | 33 | {{/structs}} 34 |
35 | {{/structsInfo}} 36 | 37 | {{#interfacesInfo}} 38 |

42 | {{__global.interfacesInSubtitle}} 43 |

44 | 45 | {{#interfaces}} 46 | 47 | {{/interfaces}} 48 |
49 | {{/interfacesInfo}} 50 | 51 | {{#enumsInfo}} 52 |

56 | {{__global.enumsInSubtitle}} 57 |

58 | 59 | {{#enums}} 60 | 61 | {{/enums}} 62 |
63 | {{/enumsInfo}} 64 | 65 | {{#delegatesInfo}} 66 |

70 | {{__global.delegatesInSubtitle}} 71 |

72 | 73 | {{#delegates}} 74 | 75 | {{/delegates}} 76 |
77 | {{/delegatesInfo}} 78 | 79 | {{>partials/dotnet/examples}} 80 | {{>partials/dotnet/remarks}} 81 | {{>partials/dotnet/seeAlso}} 82 | -------------------------------------------------------------------------------- /ContentTemplate/NetNamespace.mta.json.js: -------------------------------------------------------------------------------- 1 | var opCommon = require('./op.common.js'); 2 | var chromeCommon = require('./chrome.common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | chromeCommon.preProcessSDPMetadata(model); 7 | model.layout = 'Reference'; 8 | model._op_layout = model.layout; 9 | model.page_type = 'dotnet'; 10 | model.page_kind = 'namespace'; 11 | 12 | model['ms.assetid'] = model['ms.assetid'] || opCommon.getAssetId(model); 13 | 14 | dotnet.updateTitleForMeta(model, model.__global.namespace); 15 | 16 | chromeCommon.makeTitle(model); 17 | model.description = model.description || chromeCommon.replaceXrefTags(model.summary); 18 | chromeCommon.makeDescription(model); 19 | 20 | if (!model.description) { 21 | model.description = model.__global.descriptionNamespaceDefault.replace( 22 | '{namespace}', 23 | model.fullName 24 | ); 25 | } 26 | 27 | chromeCommon.makeCanonicalUrl(model); 28 | 29 | model.dev_langs = model.devLangs; 30 | 31 | model.toc_asset_id = model.toc_asset_id || model._tocPath; 32 | model.toc_rel = model.toc_rel || model._tocRel; 33 | if (typeof templateUtility !== 'undefined' && model.breadcrumb_path && model._path) { 34 | model.breadcrumb_path = templateUtility.resolveSourceRelativePath( 35 | model.breadcrumb_path, 36 | model._path 37 | ); 38 | } 39 | 40 | // Clean up unused predefined properties 41 | var resetKeys = [ 42 | 'commentId', 43 | 'name', 44 | 'fullName', 45 | 'classes', 46 | 'devLangs', 47 | 'structs', 48 | 'interfaces', 49 | 'enums', 50 | 'delegates', 51 | 'langs', 52 | 'remarks', 53 | 'examples', 54 | 'seeAlso', 55 | 'source', 56 | 'summary', 57 | 'uid' 58 | ]; 59 | 60 | model = opCommon.resetKeysAndSystemAttributes(model, resetKeys, true); 61 | 62 | opCommon.resolvePdfUrlTemplate(model); 63 | 64 | chromeCommon.processMetadata(model); 65 | 66 | return { 67 | content: JSON.stringify(model) 68 | }; 69 | }; 70 | -------------------------------------------------------------------------------- /ContentTemplate/NetNamespace.mta.json.tmpl: -------------------------------------------------------------------------------- 1 | {{{content}}} -------------------------------------------------------------------------------- /ContentTemplate/NetType.html.primary.js: -------------------------------------------------------------------------------- 1 | var contentCommon = require('./content.common.js'); 2 | var dotnet = require('./partials/dotnet/transform.js'); 3 | 4 | exports.transform = function (model) { 5 | model._op_templateFilename = 'NetType'; 6 | dotnet.updateTitle(model, true, model.__global[model.type]); 7 | 8 | dotnet.updateDerivedClasses(model); 9 | dotnet.updateAssemblies(model); 10 | dotnet.updatePackages(model); 11 | dotnet.setRootName(model); 12 | dotnet.setThreadSafety(model); 13 | dotnet.createChildHtmlIds(model); 14 | dotnet.updatePermissions(model); 15 | 16 | updateChildren(model); 17 | dotnet.updateTypeParameters(model); 18 | dotnet.updateMonikerizedProperties(model); 19 | dotnet.updateUWPProperties(model); 20 | dotnet.updateAdditionalRequirements(model); 21 | dotnet.updateEditButton(model); 22 | 23 | return model; 24 | }; 25 | 26 | function updateChildren(model) { 27 | if (model.constructors) { 28 | model.constructorsInfo = dotnet.getTypeChildrenInfo(model, model.constructors); 29 | } 30 | 31 | if (model.fields) { 32 | model.fieldsInfo = dotnet.getTypeChildrenInfo(model, model.fields); 33 | } 34 | 35 | if (model.methods) { 36 | model.methodsInfo = dotnet.getTypeChildrenInfo(model, model.methods); 37 | } 38 | 39 | if (model.properties) { 40 | model.propertiesInfo = dotnet.getTypeChildrenInfo(model, model.properties); 41 | } 42 | 43 | if (model.attachedProperties) { 44 | model.attachedPropertiesInfo = dotnet.getTypeChildrenInfo(model, model.attachedProperties); 45 | } 46 | 47 | if (model.operators) { 48 | model.operatorsInfo = dotnet.getTypeChildrenInfo(model, model.operators); 49 | } 50 | 51 | if (model.events) { 52 | model.eventsInfo = dotnet.getTypeChildrenInfo(model, model.events); 53 | } 54 | 55 | if (model.attachedEvents) { 56 | model.attachedEventsInfo = dotnet.getTypeChildrenInfo(model, model.attachedEvents); 57 | } 58 | 59 | if (model.eiis) { 60 | model.eiisInfo = dotnet.getTypeChildrenInfo(model, model.eiis); 61 | } 62 | 63 | if (model.extensionMethods) { 64 | model.extensionMethodsInfo = dotnet.getTypeChildrenInfo(model, model.extensionMethods); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ContentTemplate/NetType.mta.json.js: -------------------------------------------------------------------------------- 1 | var opCommon = require('./op.common.js'); 2 | var chromeCommon = require('./chrome.common.js'); 3 | var dotnet = require('./partials/dotnet/transform.js'); 4 | 5 | exports.transform = function (model) { 6 | chromeCommon.preProcessSDPMetadata(model); 7 | model.layout = 'Reference'; 8 | model._op_layout = model.layout; 9 | model.page_type = 'dotnet'; 10 | model.page_kind = model.type; 11 | 12 | model['ms.assetid'] = model['ms.assetid'] || opCommon.getAssetId(model); 13 | 14 | dotnet.updateTitleForMeta(model, model.__global[model.type]); 15 | 16 | chromeCommon.makeTitle(model); 17 | model.description = model.description || chromeCommon.replaceXrefTags(model.summary); 18 | chromeCommon.makeDescription(model); 19 | if (!model.description) { 20 | model.description = model.__global.descriptionAPIDefault 21 | .replace('{name}', model.fullName) 22 | .replace('{namespace}', model.namespace); 23 | } 24 | chromeCommon.makeCanonicalUrl(model); 25 | 26 | model.dev_langs = model.devLangs; 27 | 28 | model.toc_asset_id = model.toc_asset_id || model._tocPath; 29 | model.toc_rel = model.toc_rel || model._tocRel; 30 | if (typeof templateUtility !== 'undefined' && model.breadcrumb_path && model._path) { 31 | model.breadcrumb_path = templateUtility.resolveSourceRelativePath( 32 | model.breadcrumb_path, 33 | model._path 34 | ); 35 | } 36 | 37 | // Clean up unused predefined properties 38 | var resetKeys = [ 39 | 'additionalNotes', 40 | 'altCompliant', 41 | 'assembliesWithMoniker', 42 | 'attachedEvents', 43 | 'attachedProperties', 44 | 'attributeMonikers', 45 | 'attributesWithMoniker', 46 | 'capabilities', 47 | 'commentId', 48 | 'constructors', 49 | 'crossInheritdocsUid', 50 | 'derivedClassesWithMoniker', 51 | 'devLangs', 52 | 'eiis', 53 | 'events', 54 | 'examples', 55 | 'extensionMethods', 56 | 'fields', 57 | 'fullName', 58 | 'implementsMonikers', 59 | 'implementsWithMoniker', 60 | 'inheritancesWithMoniker', 61 | 'isDeprecated', 62 | 'isInternalOnly', 63 | 'isNotClsCompliant', 64 | 'langs', 65 | 'methods', 66 | 'name', 67 | 'nameWithType', 68 | 'obsoleteMessagesWithMoniker', 69 | 'operators', 70 | 'osRequirements', 71 | 'packagesWithMoniker', 72 | 'permissions', 73 | 'properties', 74 | 'remarks', 75 | 'sdkRequirements', 76 | 'seeAlso', 77 | 'source', 78 | 'summary', 79 | 'syntaxWithMoniker', 80 | 'threadSafety', 81 | 'type', 82 | 'typeParameters', 83 | 'uid', 84 | 'uwpRequirements', 85 | 'xamlSyntax' 86 | ]; 87 | 88 | model = opCommon.resetKeysAndSystemAttributes(model, resetKeys, true); 89 | 90 | opCommon.resolvePdfUrlTemplate(model); 91 | 92 | chromeCommon.processMetadata(model); 93 | 94 | return { 95 | content: JSON.stringify(model) 96 | }; 97 | }; 98 | -------------------------------------------------------------------------------- /ContentTemplate/NetType.mta.json.tmpl: -------------------------------------------------------------------------------- 1 | {{{content}}} -------------------------------------------------------------------------------- /ContentTemplate/chrome.common.js: -------------------------------------------------------------------------------- 1 | var shared = require('./shared.js'); 2 | 3 | function preProcessSDPMetadata(model) { 4 | var prop = null, 5 | propName = null, 6 | propNameValue = null; 7 | 8 | if (model.metadata) { 9 | for (prop in model.metadata) { 10 | propName = prop.toString(); 11 | if (shared.isString(propName)) { 12 | propNameValue = model.metadata[propName]; 13 | if (propNameValue !== undefined && propNameValue !== null) { 14 | model[propName] = propNameValue; 15 | } 16 | } 17 | } 18 | model.metadata = undefined; 19 | } 20 | 21 | makeGitHubRepoLink(model); 22 | } 23 | 24 | function makeGitHubRepoLink(model) { 25 | if (model.original_content_git_url) { 26 | var match = model.original_content_git_url.match(/github.com\/(.*?)\/(.*?)\//) 27 | if (match && match[1] && match[2]) { 28 | model._githubOwner = match[1] 29 | model._githubName = match[2] 30 | } 31 | } 32 | } 33 | 34 | exports.makeGitHubRepoLink = makeGitHubRepoLink; 35 | exports.makeCanonicalUrl = () => { }; 36 | exports.makeDescription = () => { }; 37 | exports.makeTitle = () => { }; 38 | exports.replaceXrefTags = () => { }; 39 | exports.preProcessSDPMetadata = preProcessSDPMetadata; 40 | exports.processMetadata = () => { }; 41 | exports.processCommunityContributionMetadata = () => { }; 42 | exports.buildEditLink = shared.buildEditLink; 43 | exports.createHtmlId = shared.createHtmlId; 44 | exports.isArray = shared.isArray; 45 | exports.isBool = shared.isBool; 46 | exports.isObject = shared.isObject; 47 | exports.isString = shared.isString; 48 | -------------------------------------------------------------------------------- /ContentTemplate/common.js: -------------------------------------------------------------------------------- 1 | var shared = require('./shared.js'); 2 | 3 | exports.getHtmlId = shared.createHtmlId; 4 | -------------------------------------------------------------------------------- /ContentTemplate/content.common.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | var shared = require('./shared.js'); 3 | 4 | var breakTextRegexDots = /([A-Z]\.|[a-z]\.)([A-Z]|[a-z])/g; 5 | var breakTextRegexCase = /([a-z])([A-Z]+[a-z])/g; 6 | var breakTextReplace = '$1$2'; 7 | 8 | function breakText(str, dotsOnly) { 9 | if (!str || str.length === 0) { 10 | return str; 11 | } 12 | str = str.replace(breakTextRegexDots, breakTextReplace); 13 | if (dotsOnly) { 14 | return str; 15 | } 16 | return str.replace(breakTextRegexCase, breakTextReplace); 17 | } 18 | 19 | exports.breakText = breakText; 20 | exports.createHtmlId = shared.createHtmlId; 21 | -------------------------------------------------------------------------------- /ContentTemplate/op.common.js: -------------------------------------------------------------------------------- 1 | exports.getAssetId = () => { } 2 | exports.resetKeysAndSystemAttributes = model => model 3 | exports.resolvePdfUrlTemplate = () => { } 4 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/additionalNotes.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#additionalNotes}} 2 | {{#implementer}} 3 |

{{__global.notesToImplementers}}

4 | {{{implementer}}} 5 | {{/implementer}} 6 | 7 | {{#inheritor}} 8 |

{{__global.notesToInheritors}}

9 | {{{inheritor}}} 10 | {{/inheritor}} 11 | 12 | {{#caller}} 13 |

{{__global.notesToCallers}}

14 | {{{caller}}} 15 | {{/caller}} 16 | {{/additionalNotes}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/additionalNotesWithBigHeader.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#additionalNotes}} 2 | {{#implementer}} 3 |

{{__global.notesToImplementers}}

4 | {{{implementer}}} 5 | {{/implementer}} 6 | 7 | {{#inheritor}} 8 |

{{__global.notesToInheritors}}

9 | {{{inheritor}}} 10 | {{/inheritor}} 11 | 12 | {{#caller}} 13 |

{{__global.notesToCallers}}

14 | {{{caller}}} 15 | {{/caller}} 16 | {{/additionalNotes}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/additionalRequirements.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#displayAdditionalRequirements}} 2 |

{{__global.additionalFeaturesAndRequirements}}

3 | 4 | {{#sdkRequirements}} 5 | 6 | 7 | 12 | 13 | {{/sdkRequirements}} 14 | 15 | {{#osRequirements}} 16 | 17 | 18 | 23 | 24 | {{/osRequirements}} 25 |
{{__global.softwareDevelopmentKit}} 8 |
9 | {{name}} 10 |
11 |
{{__global.minimumSupportedOS}} 19 |
20 | {{name}} ({{minVersion}}) 21 |
22 |
26 | {{/displayAdditionalRequirements}} 27 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/attribute.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#hasAttributesWithMoniker}} 2 |
3 |
{{__global.attributes}}
4 |
5 |
6 | {{#attributesWithMoniker}} 7 | {{^valuePerLanguage}} 8 | 9 | 10 | {{/valuePerLanguage}} 11 | {{#valuePerLanguage}} 12 | 13 | 14 | 15 | {{/valuePerLanguage}} 16 | {{/attributesWithMoniker}} 17 |
18 |
19 |
20 | {{/hasAttributesWithMoniker}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/clsCompliantAlternative.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#isNotClsCompliant}} 2 |
3 | {{{__global.important}}} 4 |

{{__global.clsCompliant}}

5 | {{#altCompliant}} 6 |
7 |
{{__global.clsCompliantAlt}}
8 |
9 | 10 |
11 |
12 | {{/altCompliant}} 13 |
14 | {{/isNotClsCompliant}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/deprecated.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#obsoleteMessagesWithMoniker}} 2 |
3 | 6 |
{{{__global.caution}}}
7 | {{^value}} 8 |

{{__global.deprecated}}

9 | {{/value}} 10 | {{#value}} 11 | {{{.}}} 12 | {{/value}} 13 |
14 | {{/obsoleteMessagesWithMoniker}} 15 | 16 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/derivedClass.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#hasDerivedClassesWithMoniker}} 2 |
3 |
{{__global.derived}}
4 |
5 | {{#derivedClassesWithMoniker}} 6 |
7 | 8 | {{#value}} 9 | 10 | {{/value}} 11 | 12 |
13 | {{/derivedClassesWithMoniker}} 14 | {{#hiddenDerivedClassesWithMoniker.0}} 15 | {{#hiddenDerivedClassesWithMoniker}} 16 | 23 | {{/hiddenDerivedClassesWithMoniker}} 24 |
{{{__global.loadMore}}}
25 | {{/hiddenDerivedClassesWithMoniker.0}} 26 |
27 |
28 | {{/hasDerivedClassesWithMoniker}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/examples.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#examples}} 2 |

{{__global.examples}}

3 | {{{examples}}} 4 | {{/examples}} 5 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/implement.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#hasImplementsWithMoniker}} 2 |
3 |
{{__global.implements}}
4 |
5 | {{#implementsWithMoniker}} 6 | {{^valuePerLanguage}} 7 | 8 | {{{ value }}} 9 | 10 | {{/valuePerLanguage}} 11 | {{#valuePerLanguage}} 12 | 13 | {{{ value }}} 14 | 15 | {{/valuePerLanguage}} 16 | {{/implementsWithMoniker}} 17 |
18 |
19 |
20 | {{/hasImplementsWithMoniker}} 21 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/inheritance.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#hasInheritancesWithMonikers}} 2 | {{#inheritancesWithMoniker}} 3 |
4 |
{{__global.inheritance}}
5 |
6 |
7 | {{^hasPerLanguageInheritancesWithMonikers}} 8 | {{#values}} 9 |
{{{ . }}}
10 | {{/values}} 11 | {{/hasPerLanguageInheritancesWithMonikers}} 12 | {{#hasPerLanguageInheritancesWithMonikers}} 13 | {{#valuesPerLanguage}} 14 | {{{value}}} 15 | {{/valuesPerLanguage}} 16 | {{/hasPerLanguageInheritancesWithMonikers}} 17 | {{#rootName}} {{{rootName}}} {{/rootName}} 18 |
19 |
20 |
21 | {{/inheritancesWithMoniker}} 22 | {{/hasInheritancesWithMonikers}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/member.tmpl.partial: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{>partials/dotnet/deprecated}} 4 | {{>partials/dotnet/clsCompliantAlternative}} 5 | {{>partials/dotnet/summary}} 6 | {{>partials/dotnet/syntax}} 7 | {{>partials/dotnet/typeParameters}} 8 | {{>partials/dotnet/parameters}} 9 | {{>partials/dotnet/returns}} 10 | {{>partials/dotnet/memberCommon}} 11 | {{>partials/dotnet/uwpProperties}} 12 | {{>partials/dotnet/additionalRequirements}} 13 | 14 | {{#examples}} 15 |

{{__global.examples}}

16 | {{{.}}} 17 | {{/examples}} 18 | 19 | {{#remarks}} 20 |

{{__global.remarks}}

21 | {{{.}}} 22 | {{/remarks}} 23 | 24 | {{>partials/dotnet/additionalNotesWithBigHeader}} 25 | 26 | {{#hasPermissions}} 27 |

{{__global.security}}

28 | {{>partials/dotnet/security}} 29 | {{/hasPermissions}} 30 | 31 | {{>partials/dotnet/moniker}} 32 | 33 | {{#threadSafety}} 34 |

{{__global.threadSafety}}

35 | {{{threadSafety}}} 36 | {{/threadSafety}} 37 | 38 | {{#seeAlso}} 39 |

{{__global.seeAlso}}

40 | {{{ . }}} 41 | {{/seeAlso}} 42 | 43 |
-------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/memberCommon.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#hasImplements}} 2 |

{{__global.implements}}

3 |
4 |
5 | {{#implements}} 6 | {{{.}}} 7 | {{/implements}} 8 |
9 |
10 | {{/hasImplements}} 11 | {{#hasImplementsWithMoniker}} 12 |

{{__global.implements}}

13 |
14 |
15 | {{#implementsWithMoniker}} 16 | {{^valuePerLanguage}} 17 | 18 | {{{value}}} 19 | 20 | {{/valuePerLanguage}} 21 | {{#valuePerLanguage}} 22 | 23 | {{{value}}} 24 | 25 | {{/valuePerLanguage}} 26 | {{/implementsWithMoniker}} 27 |
28 |
29 | {{/hasImplementsWithMoniker}} 30 | 31 | {{>partials/dotnet/attribute}} 32 | 33 | {{#hasExceptions}} 34 |

{{__global.exceptions}}

35 | {{#exceptions}} 36 |
37 |
38 | {{{type}}} 39 |
40 | {{{description}}} 41 |
42 | {{/exceptions}} 43 | {{/hasExceptions}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/moniker.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{! this partial template contains h2 tags with static id, so please only use it once in one page.}} 2 | {{#monikers.0}} 3 |

{{__global.appliesTo}}

4 |
5 | 6 | 7 | 8 |
9 |
10 | {{/monikers.0}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/monikerBoilerplate.tmpl.partial: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/monikerOverloadMember.tmpl.partial: -------------------------------------------------------------------------------- 1 |
2 |

{{__global.appliesTo}}

3 |
4 | 5 | 6 |
7 | 8 | 9 | 10 |
11 |
12 |
13 |
-------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/name-summary-td.tmpl.partial: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{name}} 4 | 5 | 6 | {{#summary}} 7 | 8 | {{#isInternalOnly}} 9 |

{{__global.internalUseOnly}}

10 | {{/isInternalOnly}} 11 | {{#obsoleteMessagesWithMoniker}} 12 |
13 | {{__global.obsolete}} 14 |
15 | {{/obsoleteMessagesWithMoniker}} 16 | {{{summary}}} 17 | 18 | {{/summary}} 19 | {{^summary}} 20 | {{#crossInheritdocsUid}} 21 | 22 | {{/crossInheritdocsUid}} 23 | {{/summary}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/overloadMember.tmpl.partial: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

5 | {{name}} 6 |

7 |
8 | 9 |
10 | {{>partials/dotnet/deprecated}} 11 | {{>partials/dotnet/clsCompliantAlternative}} 12 | {{>partials/dotnet/summary}} 13 | {{>partials/dotnet/syntax}} 14 | {{>partials/dotnet/typeParameters}} 15 | {{>partials/dotnet/parameters}} 16 | {{>partials/dotnet/returns}} 17 | {{>partials/dotnet/memberCommon}} 18 | {{>partials/dotnet/uwpProperties}} 19 | {{>partials/dotnet/additionalRequirements}} 20 | 21 | {{#examples}} 22 |

{{__global.examples}}

23 | {{{.}}} 24 | {{/examples}} 25 | 26 | {{#remarks}} 27 |

{{__global.remarks}}

28 | {{{.}}} 29 | {{/remarks}} 30 | 31 | {{>partials/dotnet/additionalNotes}} 32 | 33 | {{#hasPermissions}} 34 |

{{__global.security}}

35 | {{>partials/dotnet/security}} 36 | {{/hasPermissions}} 37 | 38 | {{#threadSafety}} 39 |

{{__global.threadSafety}}

40 | {{{threadSafety}}} 41 | {{/threadSafety}} 42 | 43 | {{#seeAlso}} 44 |

{{__global.seeAlso}}

45 | {{{ . }}} 46 | {{/seeAlso}} 47 | {{>partials/dotnet/monikerOverloadMember}} 48 |
49 | 50 |
-------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/parameters.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#parameters.0}} 2 |

{{__global.parameters}}

3 | {{/parameters.0}} 4 | {{#parameters}} 5 |
6 |
7 |
8 | {{^namesWithMoniker}}{{name}}{{/namesWithMoniker}} 9 | {{#namesWithMoniker}}{{value}}{{/namesWithMoniker}} 10 |
11 |
12 | {{^typePerLanguage}}{{{type}}}{{/typePerLanguage}} 13 | {{#typePerLanguage}}{{{value}}}{{/typePerLanguage}} 14 |
15 |
16 | {{{description}}} 17 |
18 | {{/parameters}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/remarks.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#remarks}} 2 |

{{__global.remarks}}

3 | {{{remarks}}} 4 | {{/remarks}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/returns.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#returnsWithMoniker}} 2 | {{#returnLabel}} 3 |

{{returnLabel}}

4 | {{/returnLabel}} 5 | 6 | {{^returnLabel}} 7 |

{{__global.returnValue}}

8 | {{/returnLabel}} 9 | 10 | {{#type}} 11 |
12 |
13 | {{^valuePerLanguage}}{{{value}}}{{/valuePerLanguage}} 14 | {{#valuePerLanguage}}{{{value}}}{{/valuePerLanguage}} 15 |
16 |
17 | {{/type}} 18 | 19 | {{{description}}} 20 | {{/returnsWithMoniker}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/security.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#permissions}} 2 |

3 | {{{type}}} 4 |
5 | {{{description}}} 6 |

7 | {{/permissions}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/seeAlso.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#seeAlso}} 2 |

{{__global.seeAlso}}

3 | {{{ . }}} 4 | {{/seeAlso}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/summary.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#summary}} 2 |
3 |
4 | {{#editLink}} 5 | 8 | {{/editLink}} 9 | {{{summary}}} 10 | {{#isFlags}} 11 |

{{{__global.flagsAttributeDisclaimer}}}

12 | {{/isFlags}} 13 | {{#isInternalOnly}} 14 |

{{__global.internalUseOnly}}

15 | {{/isInternalOnly}} 16 |
17 |
18 | {{/summary}} 19 | {{^summary}} 20 | {{#crossInheritdocsUid}} 21 |
22 |
23 | 24 |
25 |
26 | {{/crossInheritdocsUid}} 27 | {{/summary}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/syntax.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#syntaxWithMoniker}} 2 | {{#values}} 3 |
{{value}}
4 | {{/values}} 5 | {{/syntaxWithMoniker}} 6 | {{#xamlSyntax}} 7 |
{{.}}
8 | {{/xamlSyntax}} 9 | {{#xamlMemberSyntax}} 10 |
{{.}}
11 | {{/xamlMemberSyntax}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/typeContent.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{! this partial template contains h2 tags with static id, so please only use it once in one page.}} 2 | {{#examples}} 3 |

{{__global.examples}}

4 | {{{.}}} 5 | {{/examples}} 6 | 7 | {{#remarks}} 8 |

{{{__global.remarks}}}

9 | {{{.}}} 10 | {{/remarks}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/typeFooter.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{! this partial template contains h2 tags with static id, so please only use it once in one page.}} 2 | {{#threadSafety}} 3 |

{{__global.threadSafety}}

4 | {{{threadSafety}}} 5 | {{/threadSafety}} 6 | 7 | {{>partials/dotnet/seeAlso}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/typeHeader.tmpl.partial: -------------------------------------------------------------------------------- 1 |

{{__global.definition}}

2 | 3 |
4 | {{#namespace}} 5 |
6 |
{{__global.namespace}}:
7 |
8 | 9 |
10 |
11 | {{/namespace}} 12 | 13 | {{#assemblies}} 14 |
15 |
{{assemblyText}}:
{{assemblies}}
16 |
17 | {{/assemblies}} 18 | 19 | {{#assembliesWithMoniker}} 20 |
21 |
{{assemblyTitle}}:
{{value}}
22 |
23 | {{/assembliesWithMoniker}} 24 | 25 | {{#packagesWithMoniker}} 26 |
27 |
{{packageTitle}}:
{{value}}
28 |
29 | {{/packagesWithMoniker}} 30 | 31 | {{#package}} 32 |
33 |
{{__global.package}}:
{{package}}
34 |
35 | {{/package}} 36 |
-------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/typeMember.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#isInheritedFrom}} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ({{__global.inheritedFrom}} ) 10 | 11 | {{/isInheritedFrom}} 12 | {{^isInheritedFrom}} 13 | 14 | {{/isInheritedFrom}} 15 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/typeParameters.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#typeParameters.0}} 2 |

{{__global.typeParameters}}

3 | {{/typeParameters.0}} 4 | {{#typeParameters}} 5 |
6 |
7 |
{{name}}
8 |
9 | {{#constraints}} 10 | {{parameterAttribute}} {{baseTypeName}} 11 | {{/constraints}} 12 |
13 |
14 | {{{description}}} 15 | 16 | {{#isContravariant}} 17 | {{{__global.contravariantDescription}}} 18 | {{/isContravariant}} 19 | 20 | {{#isCovariant}} 21 | {{{__global.covariantDescription}}} 22 | {{/isCovariant}} 23 |
24 | {{/typeParameters}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/uwpProperties.tmpl.partial: -------------------------------------------------------------------------------- 1 | {{#displayUWPRequirements}} 2 |

{{__global.win10Requirements}}

3 | 4 | {{#uwpRequirements}} 5 | {{#deviceFamilies.0}} 6 | 7 | 8 | 15 | 16 | {{/deviceFamilies.0}} 17 | 18 | {{#apiContracts.0}} 19 | 20 | 27 | 28 | {{/apiContracts.0}} 29 | {{/uwpRequirements}} 30 | 31 | {{#capabilities.0}} 32 | 33 | 34 | 41 | 42 | {{/capabilities.0}} 43 |
{{__global.win10_deviceFamily}} 9 |
10 | {{#deviceFamilies}} 11 | {{name}} ({{introducedInVersion}})
12 | {{/deviceFamilies}} 13 |
14 |
API contract 21 |
22 | {{#apiContracts}} 23 | {{name}} ({{introducedInVersion}})
24 | {{/apiContracts}} 25 |
26 |
{{__global.win10_appCapabilities}} 35 |
36 | {{#capabilities}} 37 | {{.}} 38 | {{/capabilities}} 39 |
40 |
44 | {{/displayUWPRequirements}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-fullName-title.tmpl: -------------------------------------------------------------------------------- 1 | {{fullName}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-fullName.tmpl: -------------------------------------------------------------------------------- 1 | {{fullName}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-name-summary-tr.tmpl: -------------------------------------------------------------------------------- 1 | 2 | {{>partials/dotnet/name-summary-td}} 3 | -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-name-summary.tmpl: -------------------------------------------------------------------------------- 1 | {{>partials/dotnet/name-summary-td}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-name-with-title.tmpl: -------------------------------------------------------------------------------- 1 | {{name}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-name.tmpl: -------------------------------------------------------------------------------- 1 | {{name}} -------------------------------------------------------------------------------- /ContentTemplate/partials/dotnet/xref-summary.tmpl: -------------------------------------------------------------------------------- 1 | {{#isInternalOnly}} 2 |

{{__global.internalUseOnly}}

3 | {{/isInternalOnly}} 4 | {{#obsoleteMessagesWithMoniker}} 5 |
6 | {{__global.obsolete}} 7 |
8 | {{/obsoleteMessagesWithMoniker}} 9 | {{{summary}}} -------------------------------------------------------------------------------- /ContentTemplate/schemas/Home.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema##", 3 | "description": "The schema for home page", 4 | "type": "object", 5 | "properties": { 6 | "hero": { 7 | "type": "object", 8 | "properties": { 9 | "title": { 10 | "type": "string" 11 | }, 12 | "description": { 13 | "type": "string", 14 | "contentType": "markdown" 15 | }, 16 | "image": { 17 | "type": "string", 18 | "contentType": "href" 19 | }, 20 | "backgroundImage": { 21 | "type": "string", 22 | "contentType": "href" 23 | }, 24 | "actions": { 25 | "type": "array", 26 | "items": { 27 | "properties": { 28 | "name": { 29 | "type": "string" 30 | }, 31 | "href": { 32 | "type": "string", 33 | "contentType": "href" 34 | } 35 | } 36 | } 37 | } 38 | } 39 | }, 40 | "highlights": { 41 | "type": "array", 42 | "items": { 43 | "type": "object", 44 | "properties": { 45 | "title": { 46 | "type": "string" 47 | }, 48 | "content": { 49 | "type": "string", 50 | "contentType": "markdown" 51 | } 52 | } 53 | } 54 | }, 55 | "quickstart": { 56 | "type": "array", 57 | "items": { 58 | "type": "object", 59 | "properties": { 60 | "title": { 61 | "type": "string" 62 | }, 63 | "content": { 64 | "type": "string", 65 | "contentType": "markdown" 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /ContentTemplate/schemas/Menu.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema##", 3 | "description": "The schema for the main menu bar", 4 | "type": "object", 5 | "required": ["items"], 6 | "renderType": "Component", 7 | "properties": { 8 | "items": { 9 | "type": "array", 10 | "minItems": 1, 11 | "items": { 12 | "type": "object", 13 | "properties": { 14 | "name": { 15 | "type": "string" 16 | }, 17 | "href": { 18 | "type": "string", 19 | "contentType": "href" 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ContentTemplate/schemas/Metadata.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema##", 3 | "description": "The schema for metadata", 4 | "type": "object", 5 | "properties": { 6 | "menu_path": { 7 | "type": "string", 8 | "contentType": "href" 9 | }, 10 | "_appLogoPath": { 11 | "type": "string", 12 | "contentType": "href" 13 | }, 14 | "_appTitle": { 15 | "type": "string" 16 | }, 17 | "_appFooter": { 18 | "type": "string" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ContentTemplate/schemas/NetNamespace.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "NetNamespace", 3 | "$schema": "https://dotnet.github.io/docfx/schemas/v1.0/schema.json#", 4 | "version": "1.0.0", 5 | "description": "The schema for NetNamespace page", 6 | "id": "https://static.docs.com/ui/latest/schemas/NetNamespace.schema.json", 7 | "type": "object", 8 | "additionalProperties": false, 9 | "required": ["name", "uid"], 10 | "renderType": "content", 11 | "archivable": false, 12 | "properties": { 13 | "classes": { 14 | "items": { 15 | "$ref": "#/definitions/typeWithMoniker" 16 | }, 17 | "minItems": 1, 18 | "type": "array" 19 | }, 20 | "commentId": { 21 | "type": "string" 22 | }, 23 | "delegates": { 24 | "items": { 25 | "$ref": "#/definitions/typeWithMoniker" 26 | }, 27 | "minItems": 1, 28 | "type": "array" 29 | }, 30 | "devLangs": { 31 | "items": { 32 | "type": "string" 33 | }, 34 | "type": "array" 35 | }, 36 | "enums": { 37 | "items": { 38 | "$ref": "#/definitions/typeWithMoniker" 39 | }, 40 | "minItems": 1, 41 | "type": "array" 42 | }, 43 | "examples": { 44 | "contentType": "markdown", 45 | "tags": ["localizable"], 46 | "type": "string" 47 | }, 48 | "fullName": { 49 | "type": "string" 50 | }, 51 | "interfaces": { 52 | "items": { 53 | "$ref": "#/definitions/typeWithMoniker" 54 | }, 55 | "minItems": 1, 56 | "type": "array" 57 | }, 58 | "isInternalOnly": { 59 | "type": "boolean" 60 | }, 61 | "metadata": { 62 | "properties": { 63 | "description": { 64 | "type": "string", 65 | "tags": ["localizable"] 66 | }, 67 | "title": { 68 | "type": "string", 69 | "tags": ["localizable"] 70 | } 71 | }, 72 | "type": "object" 73 | }, 74 | "monikers": { 75 | "items": { 76 | "type": "string" 77 | }, 78 | "minItems": 1, 79 | "type": "array" 80 | }, 81 | "name": { 82 | "type": "string" 83 | }, 84 | "remarks": { 85 | "contentType": "markdown", 86 | "tags": ["localizable"], 87 | "type": "string" 88 | }, 89 | "seeAlso": { 90 | "contentType": "markdown", 91 | "tags": ["localizable"], 92 | "type": "string" 93 | }, 94 | "structs": { 95 | "items": { 96 | "$ref": "#/definitions/typeWithMoniker" 97 | }, 98 | "minItems": 1, 99 | "type": "array" 100 | }, 101 | "source": { 102 | "additionalProperties": false, 103 | "required": ["path", "branch", "repo"], 104 | "type": "object", 105 | "properties": { 106 | "path": { 107 | "type": "string" 108 | }, 109 | "branch": { 110 | "type": "string" 111 | }, 112 | "repo": { 113 | "contentType": "href", 114 | "type": "string" 115 | } 116 | } 117 | }, 118 | "summary": { 119 | "contentType": "markdown", 120 | "tags": ["localizable"], 121 | "type": "string" 122 | }, 123 | "uid": { 124 | "contentType": "uid", 125 | "type": "string" 126 | } 127 | }, 128 | "definitions": { 129 | "typeWithMoniker": { 130 | "additionalProperties": false, 131 | "required": ["monikers", "uid"], 132 | "properties": { 133 | "crossInheritdocsUid": { 134 | "contentType": "xref", 135 | "type": "string" 136 | }, 137 | "monikers": { 138 | "items": { 139 | "type": "string" 140 | }, 141 | "minItems": 1, 142 | "type": "array" 143 | }, 144 | "uid": { 145 | "contentType": "xref", 146 | "type": "string" 147 | } 148 | }, 149 | "type": "object" 150 | } 151 | }, 152 | "metadata": "/metadata", 153 | "xrefProperties": ["commentId", "fullName", "monikers", "name", "summary"] 154 | } 155 | -------------------------------------------------------------------------------- /ContentTemplate/shared.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | function isArray(obj) { 4 | return obj !== undefined && obj !== null && Array.isArray(obj); 5 | } 6 | 7 | function isBool(obj) { 8 | return ( 9 | typeof obj == 'boolean' || 10 | (typeof obj == 'object' && obj != null && obj != undefined && obj.constructor === Boolean) 11 | ); 12 | } 13 | 14 | function isNumber(obj) { 15 | return /^-?[\d.]+(?:e-?\d+)?$/.test(obj); 16 | } 17 | 18 | function isObject(obj) { 19 | return obj !== undefined && obj !== null && typeof obj === 'object'; 20 | } 21 | 22 | function isString(obj) { 23 | return ( 24 | typeof obj == 'string' || 25 | (typeof obj == 'object' && obj != null && obj != undefined && obj.constructor === String) 26 | ); 27 | } 28 | 29 | // this was extracted from the docfx shared transforms (getHtmlId) in common.js and modified to our desired format 30 | function createHtmlId(input) { 31 | return standardHtmlId(input); 32 | } 33 | 34 | function standardHtmlId(input) { 35 | if (!input) return ''; 36 | if (isString(input)) { 37 | return normalizeHtmlId(input); 38 | } 39 | if (isObject(input) && input.uid) { 40 | return normalizeHtmlId(input.uid); 41 | } 42 | return ''; 43 | } 44 | 45 | function normalizeHtmlId(input) { 46 | input = input 47 | .toLowerCase() 48 | .replace(/\\/g, '') 49 | .replace(/'/g, '') 50 | .replace(/"/g, '') 51 | .replace(/%/g, '') 52 | .replace(/\^/g, '') 53 | .replace(/\[/g, '(') 54 | .replace(/\]/g, ')') 55 | .replace(//g, ')') 57 | .replace(/{/g, '((') 58 | .replace(/}/g, '))'); 59 | 60 | input = input.replace(/[^a-zA-Z0-9()@*]/g, '-'); 61 | input = input.replace(/^-+/g, ''); 62 | input = input.replace(/-+$/g, ''); 63 | input = input.replace(/-+/g, '-'); 64 | 65 | return input; 66 | } 67 | 68 | exports.createHtmlId = createHtmlId; 69 | exports.isArray = isArray; 70 | exports.isBool = isBool; 71 | exports.isNumber = isNumber; 72 | exports.isObject = isObject; 73 | exports.isString = isString; 74 | -------------------------------------------------------------------------------- /ContentTemplate/toc.json.js: -------------------------------------------------------------------------------- 1 | exports.transform = function (model) { 2 | 3 | groupChildren(model, model) 4 | 5 | return { 6 | items: model.items 7 | }; 8 | }; 9 | 10 | function groupChildren(rootModel, item) { 11 | if (!item || !item.items || item.items.length == 0) { 12 | return; 13 | } 14 | 15 | var groupNames = { 16 | constructor: { key: 'constructorsInSubtitle' }, 17 | field: { key: 'fieldsInSubtitle' }, 18 | property: { key: 'propertiesInSubtitle' }, 19 | method: { key: 'methodsInSubtitle' }, 20 | event: { key: 'eventsInSubtitle' }, 21 | operator: { key: 'operatorsInSubtitle' }, 22 | eii: { key: 'eiisInSubtitle' } 23 | }; 24 | 25 | var grouped = {}; 26 | var items = []; 27 | item.items.forEach(function (element) { 28 | groupChildren(rootModel, element); 29 | if (element.type) { 30 | var type = element.type.toLowerCase(); 31 | if (type === 'constructor') { 32 | element.name = rootModel.__global['constructorsInSubtitle']; 33 | items.push(element); 34 | } else { 35 | if ( 36 | (type === 'method' || type === 'property') && 37 | element.isEii !== undefined && 38 | element.isEii !== null && 39 | element.isEii 40 | ) { 41 | type = 'eii'; 42 | element.type = rootModel.__global['eiisInSubtitle']; 43 | } 44 | 45 | if (!grouped.hasOwnProperty(type)) { 46 | if (!groupNames.hasOwnProperty(type)) { 47 | groupNames[type] = { 48 | name: element.type 49 | }; 50 | } 51 | grouped[type] = []; 52 | } 53 | grouped[type].push(element); 54 | } 55 | } else { 56 | items.push(element); 57 | } 58 | }, this); 59 | 60 | for (var key in groupNames) { 61 | if (groupNames.hasOwnProperty(key) && grouped.hasOwnProperty(key)) { 62 | var monikers = {}; 63 | for (var i = 0; i < grouped[key].length; i++) { 64 | var m = grouped[key][i]; 65 | if (m.monikers && m.monikers.length > 0) { 66 | for (var j = 0; j < m.monikers.length; j++) { 67 | var moniker = m.monikers[j]; 68 | monikers[moniker] = true; 69 | } 70 | } else { 71 | // An element in this group has no monikers associated with it. 72 | // This means the parent node will never be hidden due to moniker selection. 73 | // No need to associate monikers with the parent node. 74 | monikers = {}; 75 | break; 76 | } 77 | } 78 | 79 | var groupedMonikers = Object.keys(monikers); 80 | 81 | if (groupedMonikers && groupedMonikers.length > 0) { 82 | items.push({ 83 | name: rootModel.__global[groupNames[key].key] || groupNames[key].name, 84 | items: grouped[key], 85 | monikers: groupedMonikers 86 | }); 87 | } else { 88 | items.push({ 89 | name: rootModel.__global[groupNames[key].key] || groupNames[key].name, 90 | items: grouped[key] 91 | }); 92 | } 93 | } 94 | } 95 | 96 | item.items = items; 97 | } 98 | -------------------------------------------------------------------------------- /ContentTemplate/token.json: -------------------------------------------------------------------------------- 1 | { 2 | "additionalFeaturesAndRequirements": "Additional features and requirements", 3 | "appliesTo": "Applies to", 4 | "assemblies": "Assemblies", 5 | "assembly": "Assembly", 6 | "attachedEventsInSubtitle": "Attached Events", 7 | "attachedPropertiesInSubtitle": "Attached Properties", 8 | "attributes": "Attributes", 9 | "boilerplateTitle": "Important", 10 | "classesInSubtitle": "Classes", 11 | "clsCompliant": "This API is not CLS-compliant.", 12 | "clsCompliantAlt": "CLS-compliant alternative", 13 | "constructorsInSubtitle": "Constructors", 14 | "contravariantDescription": "This type parameter is contravariant. That is, you can use either the type you specified or any type that is less derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.", 15 | "covariantDescription": "This type parameter is covariant. That is, you can use either the type you specified or any type that is more derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.", 16 | "definition": "Definition", 17 | "delegateInSubtitle": "Delegate", 18 | "delegatesInSubtitle": "Delegates", 19 | "deprecated": "This API is now deprecated.", 20 | "derived": "Derived", 21 | "description": "Description", 22 | "descriptionAPIDefault": "Learn more about the {name} in the {namespace} namespace.", 23 | "descriptionNamespaceDefault": "Explore all classes and interfaces of the {namespace} namespace.", 24 | "edit": "Edit", 25 | "eiisInSubtitle": "Explicit Interface Implementations", 26 | "enumInSubtitle": "Enum", 27 | "enumsInSubtitle": "Enums", 28 | "eventsInSubtitle": "Events", 29 | "eventType": "Event Type", 30 | "examples": "Examples", 31 | "exceptions": "Exceptions", 32 | "extensionMethodsInSubtitle": "Extension Methods", 33 | "fieldsInSubtitle": "Fields", 34 | "fieldValue": "Field Value", 35 | "flagsAttributeDisclaimer": "This enumeration has a FlagsAttribute attribute that allows a bitwise combination of its member values.", 36 | "implements": "Implements", 37 | "inheritance": "Inheritance", 38 | "inheritedFrom": "Inherited from", 39 | "interfacesInSubtitle": "Interfaces", 40 | "internalUseOnly": "This API supports the product infrastructure and is not intended to be used directly from your code.", 41 | "loadMore": "More…", 42 | "methodsInSubtitle": "Methods", 43 | "minimumSupportedOS": "Minimum supported OS", 44 | "namespace": "Namespace", 45 | "notesToCallers": "Notes to Callers", 46 | "notesToImplementers": "Notes to Implementers", 47 | "notesToInheritors": "Notes to Inheritors", 48 | "operatorsInSubtitle": "Operators", 49 | "obsolete": "Obsolete.", 50 | "overloads": "Overloads", 51 | "package": "Package", 52 | "packages": "Packages", 53 | "parameters": "Parameters", 54 | "prereleaseBoilerplate": "Some information relates to prerelease product that may be substantially modified before it’s released.", 55 | "propertiesInSubtitle": "Properties", 56 | "propertyValue": "Property Value", 57 | "remarks": "Remarks", 58 | "returns": "Returns", 59 | "returnValue": "Return Value", 60 | "security": "Security", 61 | "seeAlso": "See also", 62 | "showAllDerived": "Show all derived classes", 63 | "showMore": "Show more", 64 | "softwareDevelopmentKit": "Software Development Kit", 65 | "structsInSubtitle": "Structs", 66 | "threadSafety": "Thread Safety", 67 | "typeParameters": "Type Parameters", 68 | "win10_appCapabilities": "App capabilities", 69 | "win10_deviceFamily": "Device family", 70 | "win10_introducedIn": "introduced in {version}", 71 | "win10Requirements": "Windows requirements", 72 | "class": "Class", 73 | "struct": "Struct", 74 | "interface": "Interface", 75 | "attachedEvent": "Attached Event", 76 | "attachedProperty": "Attached Property", 77 | "event": "Event", 78 | "field": "Field", 79 | "method": "Method", 80 | "operator": "Operator", 81 | "property": "Property" 82 | } 83 | -------------------------------------------------------------------------------- /Home.html.liquid: -------------------------------------------------------------------------------- 1 | {%- assign layout = 'home' -%} 2 | {%- assign pageType = 'home' -%} 3 | 4 | {%- include main -%} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 docfx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Default docfx Site Template 2 | 3 | > ⚠️⚠️⚠️ This repository is archived, the template will be developed in the repo. 4 | 5 | Default site template for [docfx](https://github.com/dotnet/docfx). 6 | 7 | Sample site: https://docascode.github.io/template/ 8 | 9 | ### Development Setup 10 | 11 | To develop the template: 12 | 13 | - Install [Node.js](https://nodejs.org/) 14 | - Install [yarn](https://yarnpkg.com/) 15 | - Install [.NET Core](https://www.microsoft.com/net/download) 16 | 17 | - Checkout submodules using 18 | ``` 19 | git submodule update --init 20 | ``` 21 | 22 | - Build the site template using 23 | ```powershell 24 | yarn 25 | yarn build 26 | ``` 27 | 28 | - Start a local development server using 29 | ```powershell 30 | yarn start 31 | ``` 32 | 33 | To show contributor list locally, set the `DOCFX__SECRETS__GITHUB_TOKEN` environment variable to a GitHub token with read access to `repo` and `user.email`. 34 | -------------------------------------------------------------------------------- /Reference.html.liquid: -------------------------------------------------------------------------------- 1 | {%- assign layout = 'conceptual' -%} 2 | {%- assign pageType = 'reference' -%} 3 | {%- assign heading1 = page.rawTitle -%} 4 | {%- assign disableMetabar = true -%} 5 | 6 | {%- include main -%} 7 | -------------------------------------------------------------------------------- /_includes/footer.liquid: -------------------------------------------------------------------------------- 1 |
2 | {%- if page._appFooter -%} 3 | {{ page._appFooter }} 4 | {%- endif -%} 5 | 6 | {%- if page._disableContribution == false and page._githubOwner and page._githubName -%} 7 |
8 | 9 |
10 | {%- endif -%} 11 |
12 | -------------------------------------------------------------------------------- /_includes/header.liquid: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /_includes/main.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{metadata}} 8 | 9 | {{ page.title }} 10 | 11 | 12 | 13 | 14 | 15 |
16 | {%- include header -%} 17 |
18 | 19 |
20 | {%- if layout == "conceptual" -%} 21 | {%- unless disableBreadcrumb -%} 22 | 23 | {%- endunless -%} 24 | 25 | 28 | 29 |
30 | {{ heading1 }} 31 | {%- unless disableMetabar -%} 32 | {%- include metabar -%} 33 | {%- endunless -%} 34 | 35 | {{ content }} 36 | 37 | {%- if page._disableContribution == false and page.original_content_git_url -%} 38 | 39 | 40 | 41 | 42 | Edit this page on GitHub 43 | 44 | {%- endif -%} 45 |
46 | 47 | 52 | {%- else -%} 53 | {{ content }} 54 | {%- endif -%} 55 |
56 | 57 |
58 | {%- include footer -%} 59 |
60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /_includes/metabar.liquid: -------------------------------------------------------------------------------- 1 |
    2 |
  • 3 | 4 |
  • 5 | {%- if page.wordCount < 400 -%} 6 | {%- capture minToRead %}2{% endcapture -%} 7 | {%- else -%} 8 | {%- capture minToRead %}{{ page.wordCount | divided_by: 200 | round }}{% endcapture -%} 9 | {%- endif -%} 10 |
  • {{ minToRead}} minutes to read
  • 11 | {%- if page._op_gitContributorInformation.contributors and page._op_gitContributorInformation.contributors.size > 0 -%} 12 | {%- assign contributorMax = 5 -%} 13 | {%- assign contributorSize = page._op_gitContributorInformation.contributors.size -%} 14 | {%- if contributorSize <= contributorMax -%} 15 | {%- assign contributorCount = contributorSize | minus: 1 -%} 16 | {%- else -%} 17 | {%- assign contributorCount = contributorMax | minus: 1 -%} 18 | {%- endif -%} 19 | {%- if contributorSize == 1 -%} 20 | {%- capture contributor %}{%- loc contributor -%}{% endcapture -%} 21 | {%- else -%} 22 | {%- capture contributor %}{%- loc contributors -%}{% endcapture -%} 23 | {%- endif -%} 24 |
  • 25 |
      26 | {%- for i in (0..contributorCount) -%} 27 | {%- assign contributor = page._op_gitContributorInformation.contributors[i] -%} 28 | {%- if contributor.profile_url and contributor.profile_url.size > 0 -%} 29 |
    • 30 | 31 | 32 | 33 |
    • 34 | {%- endif -%} 35 | {%- endfor -%} 36 |
    37 | 38 |
  • 39 | {%- endif -%} 40 |
-------------------------------------------------------------------------------- /_includes/toc.liquid: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | const esbuild = require('esbuild') 2 | const { sassPlugin } = require('esbuild-sass-plugin') 3 | const { spawnSync } = require('child_process') 4 | const { existsSync } = require('fs') 5 | 6 | function buildTemplate({ watch } = {}) { 7 | 8 | const debug = { 9 | outdir: 'debug/dist', 10 | bundle: true, 11 | minify: false, 12 | sourcemap: true, 13 | treeShaking: true, 14 | watch: { 15 | onRebuild(error, result) { 16 | if (error) { 17 | console.error('watch build failed:', error) 18 | } else { 19 | console.log('watch build succeeded:', result) 20 | } 21 | } 22 | } 23 | } 24 | 25 | const release = { 26 | outdir: 'dist', 27 | bundle: true, 28 | minify: true, 29 | minifySyntax: true, 30 | sourcemap: false, 31 | treeShaking: true, 32 | } 33 | 34 | return esbuild.build(Object.assign(watch ? debug : release, { 35 | entryPoints: [ 36 | 'src/docfx.ts', 37 | 'src/docfx.scss', 38 | ], 39 | plugins: [ 40 | sassPlugin() 41 | ], 42 | loader: { 43 | '.eot': 'file', 44 | '.svg': 'file', 45 | '.ttf': 'file', 46 | '.woff': 'file', 47 | '.woff2': 'file' 48 | } 49 | })) 50 | } 51 | 52 | 53 | function buildContent() { 54 | const docfx = existsSync('bin/docfx.exe') ? 'bin\\docfx.exe' : 'bin/docfx' 55 | exec(`dotnet build samples/dotnet/CatLibrary`) 56 | exec(`${docfx} build samples --verbose`) 57 | } 58 | 59 | function exec(cmd) { 60 | if (spawnSync(cmd, { stdio: 'inherit', shell: true }).status !== 0) { 61 | throw Error(`exec error: '${cmd}'`) 62 | } 63 | } 64 | 65 | module.exports = { buildTemplate, buildContent } 66 | 67 | if (require.main === module) { 68 | buildTemplate() 69 | buildContent() 70 | } 71 | -------------------------------------------------------------------------------- /build/diff.js: -------------------------------------------------------------------------------- 1 | const { Cluster } = require('puppeteer-cluster') 2 | const { exit } = require('process') 3 | const { mkdirSync, existsSync, readdirSync, readFileSync, writeFileSync, cpSync, rmSync } = require('fs') 4 | const { join } = require('path') 5 | const PNG = require('pngjs').PNG 6 | const pixelmatch = require('pixelmatch') 7 | const { createServer } = require('http-server') 8 | 9 | const expectedDir = 'tests/screenshots/expected' 10 | const actualDir = 'tests/screenshots/actual' 11 | const diffDir = 'tests/screenshots/diff' 12 | 13 | const urls = [ 14 | '/', 15 | '/tutorial/getting-started/', 16 | '/tutorial/walkthrough/walkthrough_create_a_docfx_project_2/' 17 | ] 18 | 19 | const themes = [ 20 | 'light', 21 | 'dark' 22 | ] 23 | 24 | const viewports = [ 25 | { width: 1920, height: 1080 }, 26 | { width: 1152, height: 648 }, 27 | { width: 768, height: 600 }, 28 | { width: 375, height: 812, isMobile: true, hasTouch: true } 29 | ] 30 | 31 | async function diff() { 32 | const url = await serve('./samples/_site') 33 | await captureScreenshots(url) 34 | } 35 | 36 | async function serve(root) { 37 | return new Promise((resolve, reject) => { 38 | const { server } = createServer({ root }) 39 | server.listen(0, 'localhost', async err => { 40 | if (err) { 41 | reject(err) 42 | } else { 43 | resolve(`http://localhost:${server.address().port}`) 44 | } 45 | }) 46 | }) 47 | } 48 | 49 | async function captureScreenshots(baseurl) { 50 | const cluster = await Cluster.launch({ 51 | concurrency: Cluster.CONCURRENCY_CONTEXT, 52 | maxConcurrency: 8, 53 | }); 54 | 55 | ensuredirSync(actualDir) 56 | 57 | await cluster.task(async ({ page, data: { url, viewport, theme } }) => { 58 | try { 59 | const path = `${actualDir}/${url.slice(1).replace(/[/]+/g, '-')}-${viewport.width}-${viewport.height}-${theme}.png` 60 | await page.setCookie({ name: 'docfx.theme', value: theme, domain: 'localhost' }) 61 | await page.setViewport(viewport) 62 | await page.goto(baseurl + url, { 63 | waitUntil: 'networkidle0' 64 | }) 65 | await new Promise(resolve => setTimeout(resolve, 2000)) 66 | await page.screenshot({ path, fullPage: true }) 67 | console.log(`Save screenshot to ${path}`) 68 | } catch (e) { 69 | console.error(e) 70 | } 71 | }); 72 | 73 | for (const theme of themes) { 74 | for (const viewport of viewports) { 75 | for (const url of urls) { 76 | cluster.queue({ url, viewport, theme }); 77 | } 78 | } 79 | } 80 | 81 | await cluster.idle(); 82 | await cluster.close(); 83 | 84 | exit(compare(expectedDir, actualDir) ? 1 : 0) 85 | } 86 | 87 | function ensuredirSync(dir) { 88 | if (!existsSync(dir)) { 89 | mkdirSync(dir, { recursive: true }) 90 | } 91 | } 92 | 93 | function compare(base, target) { 94 | let hasDiff = false 95 | 96 | if (existsSync(base)) { 97 | for (const filename of readdirSync(base)) { 98 | try { 99 | console.log(` ${join(base, filename)} --> ${join(target, filename)}`) 100 | 101 | const img1 = PNG.sync.read(readFileSync(join(base, filename))) 102 | const img2 = PNG.sync.read(readFileSync(join(target, filename))) 103 | const { width, height } = img1; 104 | const diff = new PNG({ width, height }); 105 | 106 | const n = pixelmatch(img1.data, img2.data, diff.data, width, height, { threshold: 0.1 }) 107 | if (n == 0) { 108 | continue 109 | } 110 | 111 | const diffFile = join(diffDir, filename) 112 | ensuredirSync(diffDir) 113 | writeFileSync(diffFile, PNG.sync.write(diff)) 114 | console.error(`Pixelmatch diff [${n}]: ${diffFile}`) 115 | 116 | hasDiff = true 117 | } catch (err) { 118 | console.error(err) 119 | hasDiff = true 120 | } 121 | } 122 | 123 | return hasDiff 124 | } 125 | } 126 | 127 | function acceptDiff() { 128 | if (existsSync(actualDir)) { 129 | if (existsSync(expectedDir)) { 130 | rmSync(expectedDir, { force: true, recursive: true }) 131 | } 132 | cpSync(actualDir, expectedDir, { force: true, recursive: true }) 133 | } 134 | } 135 | 136 | module.exports = { diff, acceptDiff } 137 | 138 | if (require.main === module) { 139 | if (process.argv.includes('--accept')) { 140 | acceptDiff() 141 | } else { 142 | diff() 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /build/start.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path') 2 | const bs = require('browser-sync') 3 | const { buildTemplate, buildContent } = require('./build.js') 4 | 5 | function start(options) { 6 | buildContent() 7 | 8 | Promise.all([ 9 | buildTemplate({ watch: true }), 10 | serve(options) 11 | ]) 12 | } 13 | 14 | function serve() { 15 | const site = 'samples/_site' 16 | const browserSync = bs.create('docfx') 17 | 18 | return browserSync.init({ 19 | open: true, 20 | startPath: '/test', 21 | files: [ 22 | 'debug/dist', 23 | join(site, '**') 24 | ], 25 | server: { 26 | routes: { 27 | '/test/dist': 'debug/dist', 28 | '/test': site 29 | } 30 | } 31 | }) 32 | } 33 | 34 | module.exports = { start } 35 | 36 | if (require.main === module ) { 37 | start() 38 | } 39 | -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular-ACNUA6UY.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/dist/glyphicons-halflings-regular-ACNUA6UY.ttf -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular-JOUF32XT.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/dist/glyphicons-halflings-regular-JOUF32XT.woff -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular-PIHUWCJO.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/dist/glyphicons-halflings-regular-PIHUWCJO.eot -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular-W4DYDFZM.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/dist/glyphicons-halflings-regular-W4DYDFZM.woff2 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@docfx/template", 3 | "license": "MIT", 4 | "scripts": { 5 | "build": "node build/build.js", 6 | "start": "node build/start.js", 7 | "diff": "node build/diff.js", 8 | "accept-diff": "node build/diff.js --accept", 9 | "postinstall": "dotnet build -c Release -o bin extern/docfx/src/docfx" 10 | }, 11 | "dependencies": { 12 | "@popperjs/core": "^2.11.4", 13 | "anchor-js": "^4.3.1", 14 | "bootstrap": "^5.1.3", 15 | "highlight.js": "^11.5.0", 16 | "js-cookie": "^3.0.1", 17 | "jsx-dom": "^8.0.1-beta.5" 18 | }, 19 | "devDependencies": { 20 | "browser-sync": "^2.27.9", 21 | "esbuild": "^0.14.31", 22 | "esbuild-sass-plugin": "^2.2.6", 23 | "http-server": "^14.1.0", 24 | "pixelmatch": "^5.2.1", 25 | "puppeteer": "^13.5.2", 26 | "puppeteer-cluster": "^0.23.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/codesnippet/Rtf/Hyperlink/RtfDocumentProcessor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace RtfDocumentProcessors 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections.Immutable; 9 | using System.Composition; 10 | using System.IO; 11 | using System.Linq; 12 | using System.Web; 13 | using System.Xml.Linq; 14 | 15 | using Microsoft.DocAsCode.Plugins; 16 | using Microsoft.DocAsCode.Utility; 17 | 18 | [Export(typeof(IDocumentProcessor))] 19 | public class RtfDocumentProcessor : IDocumentProcessor 20 | { 21 | [ImportMany(nameof(RtfDocumentProcessor))] 22 | public IEnumerable BuildSteps { get; set; } 23 | 24 | public string Name => nameof(RtfDocumentProcessor); 25 | 26 | public ProcessingPriority GetProcessingPriority(FileAndType file) 27 | { 28 | if (file.Type == DocumentType.Article && 29 | ".rtf".Equals(Path.GetExtension(file.File), StringComparison.OrdinalIgnoreCase)) 30 | { 31 | return ProcessingPriority.Normal; 32 | } 33 | return ProcessingPriority.NotSupported; 34 | } 35 | 36 | public FileModel Load(FileAndType file, ImmutableDictionary metadata) 37 | { 38 | var content = new Dictionary 39 | { 40 | ["conceptual"] = File.ReadAllText(Path.Combine(file.BaseDir, file.File)), 41 | ["type"] = "Conceptual", 42 | ["path"] = file.File, 43 | }; 44 | return new FileModel(file, content); 45 | } 46 | 47 | #region Save 48 | public SaveResult Save(FileModel model) 49 | { 50 | HashSet linkToFiles = CollectLinksAndFixDocument(model); 51 | 52 | return new SaveResult 53 | { 54 | DocumentType = "Conceptual", 55 | ModelFile = model.File, 56 | LinkToFiles = linkToFiles.ToImmutableArray(), 57 | }; 58 | } 59 | #endregion 60 | 61 | #region CollectLinksAndFixDocument 62 | private static HashSet CollectLinksAndFixDocument(FileModel model) 63 | { 64 | string content = (string)((Dictionary)model.Content)["conceptual"]; 65 | var doc = XDocument.Parse(content); 66 | var links = 67 | from attr in doc.Descendants().Attributes() 68 | where "href".Equals(attr.Name.LocalName, StringComparison.OrdinalIgnoreCase) || "src".Equals(attr.Name.LocalName, StringComparison.OrdinalIgnoreCase) 69 | select attr; 70 | var path = (RelativePath)model.File; 71 | var linkToFiles = new HashSet(); 72 | foreach (var link in links) 73 | { 74 | FixLink(link, path, linkToFiles); 75 | } 76 | using (var sw = new StringWriter()) 77 | { 78 | doc.Save(sw); 79 | ((Dictionary)model.Content)["conceptual"] = sw.ToString(); 80 | } 81 | return linkToFiles; 82 | } 83 | #endregion 84 | 85 | #region FixLink 86 | private static void FixLink(XAttribute link, RelativePath filePath, HashSet linkToFiles) 87 | { 88 | string linkFile; 89 | string anchor = null; 90 | if (PathUtility.IsRelativePath(link.Value)) 91 | { 92 | var index = link.Value.IndexOf('#'); 93 | if (index == -1) 94 | { 95 | linkFile = link.Value; 96 | } 97 | else if (index == 0) 98 | { 99 | return; 100 | } 101 | else 102 | { 103 | linkFile = link.Value.Remove(index); 104 | anchor = link.Value.Substring(index); 105 | } 106 | var path = filePath + (RelativePath)linkFile; 107 | var file = (string)path.GetPathFromWorkingFolder(); 108 | link.Value = file + anchor; 109 | linkToFiles.Add(HttpUtility.UrlDecode(file)); 110 | } 111 | } 112 | #endregion 113 | 114 | public void UpdateHref(FileModel model, IDocumentBuildContext context) 115 | { 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /samples/codesnippet/Rtf/RtfBuildStep.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace RtfDocumentProcessors 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections.Immutable; 9 | using System.Composition; 10 | using System.Threading.Tasks; 11 | using System.Threading.Tasks.Schedulers; 12 | 13 | using MarkupConverter; 14 | using Microsoft.DocAsCode.Plugins; 15 | 16 | [Export(nameof(RtfDocumentProcessor), typeof(IDocumentBuildStep))] 17 | public class RtfBuildStep : IDocumentBuildStep 18 | { 19 | #region Build 20 | private readonly TaskFactory _taskFactory = new TaskFactory(new StaTaskScheduler(1)); 21 | 22 | public void Build(FileModel model, IHostService host) 23 | { 24 | string content = (string)((Dictionary)model.Content)["conceptual"]; 25 | content = _taskFactory.StartNew(() => RtfToHtmlConverter.ConvertRtfToHtml(content)).Result; 26 | ((Dictionary)model.Content)["conceptual"] = content; 27 | } 28 | #endregion 29 | 30 | #region Others 31 | public int BuildOrder => 0; 32 | 33 | public string Name => nameof(RtfBuildStep); 34 | 35 | public void Postbuild(ImmutableList models, IHostService host) 36 | { 37 | } 38 | 39 | public IEnumerable Prebuild(ImmutableList models, IHostService host) 40 | { 41 | return models; 42 | } 43 | #endregion 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /samples/codesnippet/Rtf/RtfDocumentProcessor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace RtfDocumentProcessors 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Collections.Immutable; 9 | using System.Composition; 10 | using System.IO; 11 | 12 | using Microsoft.DocAsCode.Common; 13 | using Microsoft.DocAsCode.Plugins; 14 | 15 | [Export(typeof(IDocumentProcessor))] 16 | public class RtfDocumentProcessor : IDocumentProcessor 17 | { 18 | #region BuildSteps 19 | [ImportMany(nameof(RtfDocumentProcessor))] 20 | public IEnumerable BuildSteps { get; set; } 21 | #endregion 22 | 23 | #region Name 24 | public string Name => nameof(RtfDocumentProcessor); 25 | #endregion 26 | 27 | #region GetProcessingPriority 28 | public ProcessingPriority GetProcessingPriority(FileAndType file) 29 | { 30 | if (file.Type == DocumentType.Article && 31 | ".rtf".Equals(Path.GetExtension(file.File), StringComparison.OrdinalIgnoreCase)) 32 | { 33 | return ProcessingPriority.Normal; 34 | } 35 | return ProcessingPriority.NotSupported; 36 | } 37 | #endregion 38 | 39 | #region Load 40 | public FileModel Load(FileAndType file, ImmutableDictionary metadata) 41 | { 42 | var content = new Dictionary 43 | { 44 | ["conceptual"] = File.ReadAllText(Path.Combine(file.BaseDir, file.File)), 45 | ["type"] = "Conceptual", 46 | ["path"] = file.File, 47 | }; 48 | var localPathFromRoot = PathUtility.MakeRelativePath(EnvironmentContext.BaseDirectory, EnvironmentContext.FileAbstractLayer.GetPhysicalPath(file.File)); 49 | 50 | return new FileModel(file, content) 51 | { 52 | LocalPathFromRoot = localPathFromRoot, 53 | }; 54 | } 55 | #endregion 56 | 57 | #region Save 58 | public SaveResult Save(FileModel model) 59 | { 60 | return new SaveResult 61 | { 62 | DocumentType = "Conceptual", 63 | FileWithoutExtension = Path.ChangeExtension(model.File, null), 64 | }; 65 | } 66 | #endregion 67 | 68 | #region UpdateHref 69 | public void UpdateHref(FileModel model, IDocumentBuildContext context) 70 | { 71 | } 72 | #endregion 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /samples/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "..", 3 | "exclude": [ 4 | "dotnet/**" 5 | ], 6 | "dotnet": { 7 | "assemblies": [ 8 | "dotnet/CatLibrary/bin/Debug/net6.0/CatLibrary.dll" 9 | ] 10 | }, 11 | "xref": [ 12 | "https://docs.microsoft.com/en-us/dotnet/.xrefmap.json" 13 | ], 14 | "globalMetadata": { 15 | "_appTitle": "Docfx", 16 | "_appFooter": "© Microsoft", 17 | "menu_path": "menu.yml" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/dotnet/CatLibrary/CatLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | net6.0 6 | enable 7 | enable 8 | True 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /samples/index.yml: -------------------------------------------------------------------------------- 1 | #YamlMime:Home 2 | hero: 3 | title: Build technical documentation sites with Docfx 4 | description: | 5 | Quickly build static documentation sites using markdown files. 6 | Generate .NET API reference pages directly from assemblies. 7 | actions: 8 | - name: Get Started 9 | href: tutorial/getting-started.md 10 | - name: Install 11 | href: https://github.com/dotnet/docfx/releases 12 | 13 | quickstart: 14 | - title: Installation 15 | content: | 16 | Install docfx as a [dotnet tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools) on Windows, Mac or Linux. 17 | 18 | ```bash 19 | dotnet tool install docfx 20 | ``` 21 | - title: Hello World 22 | content: | 23 | Create a new website and add a new markdown article: 24 | 25 | ```bash 26 | mkdir my-docs 27 | cd my-docs 28 | docfx new conceptual 29 | echo "Hello World" > hello.md 30 | ``` 31 | - title: Preview Changes 32 | content: | 33 | Edit and preview content changes locally. Open a browser and go to https://localhost:8080 after executing this command: 34 | 35 | ````bash 36 | docfx build 37 | docfx serve 38 | ```` 39 | 40 | - title: Publish it to GitHub Pages 41 | content: | 42 | Create a git repository. Add, commit and push your website to [GitHub Pages](https://pages.github.com/) 43 | 44 | ````bash 45 | cd _site 46 | git init 47 | git add --all 48 | git commit -m "Initial commit" 49 | git push -u https://github.com/username/username.github.io main 50 | ```` 51 | 52 | highlights: 53 | - title: Document as Code 54 | content: | 55 | Create, collabrate and manage documentations as `code`, using simple text formats like [markdown](https://www.markdownguide.org/) and [YAML](https://yaml.org/). 56 | 57 | Works seamlessly with your favorite text editors and source control systems. 58 | 59 | [Read More](./tutorial/getting-started.md). 60 | - title: .NET API Documentation 61 | content: | 62 | Automatically generates .NET API reference documentation from DLLs and standard XML documentation files. 63 | 64 | [Read More](./tutorial/getting-started.md). 65 | - title: Publish Static Website 66 | content: | 67 | Produces static HTML files ready to publish to [GitHub Pages](https://pages.github.com/). 68 | 69 | [Read More](./tutorial/getting-started.md). 70 | -------------------------------------------------------------------------------- /samples/menu.yml: -------------------------------------------------------------------------------- 1 | #YamlMime:Menu 2 | items: 3 | - name: Tutorials 4 | href: tutorial/getting-started.md 5 | - name: Specifications 6 | href: spec/metadata_format_spec.md 7 | - name: API Documentation 8 | href: api/CatLibrary.yml 9 | -------------------------------------------------------------------------------- /samples/spec/docfx_design_spec.md: -------------------------------------------------------------------------------- 1 | `docfx` Design Spec 2 | ==================================== 3 | ## 0. Terms 4 | 5 | Term | Description 6 | -----|------- 7 | DFM | [DocFX Flavored Markdown](docfx_flavored_markdown.md) 8 | API | The API generated from source code 9 | Overwrite Files | The files with YAML header used to override YAML files when `uid` matches. 10 | 11 | 12 | ## 1. Scenarios 13 | 14 | `docfx` should support the following scenarios: 15 | 16 | 1. Source Code => Website 17 | 2. Conceptual => Website 18 | 3. YAML files => Website 19 | 20 | 21 | 22 | ## 2. Architecture 23 | 24 | ![Workflow](images/docfx_workflow.png) 25 | 26 | ## 3. Feature List 27 | 28 | 1. Support for [DocFX Flavored Markdown](docfx_flavored_markdown.md) 29 | 2. Ability to parse toc.json/toc.yml/toc.md 30 | 3. Custom template naming: {type}.{extension}.tmpl under folder {templateName} 31 | 32 | ## 4. Open Issues 33 | 34 | 1. Should we support other conceptual file format, for example, RST? 35 | ==> How to parse? 36 | 2. How do you know which link to replace to html, and which not? 37 | ==> 38 | -------------------------------------------------------------------------------- /samples/spec/docfx_incremental.md: -------------------------------------------------------------------------------- 1 | Doc-as-code: DocFx.exe Incremental Build Specification 2 | ========================================== 3 | 4 | This documentation describes the implementation of incrementally extracting metadata from source. Currently we are using *Roslyn* to compile and analyse source code on the fly. When input sources are large, it may take minutes to load and process the files. To speed up the extraction, previous extracted details are saved to cache for further reference. 5 | 6 | There are two level caches in current implementation. First one is called *Application* Level cache, and the other one is *Project* level cache. 7 | 8 | *Application* level cache is saved in file `%LocalAppData%/xdoc/cache`. 9 | 10 | For *Project* level cache, 11 | 12 | a. If input sources are supported project files, e.g. `.csproj` or `.vbproj` files, *Project* level cache is located in file `obj/xdoc/.cache` under the same folder of the project file. 13 | 14 | b. If input sources are supported source code files, e.g. `.cs` or `.vb` files, *Project* level cache is located in file `obj/xdoc/.cache` under the same folder of the alphabetically first source code file. 15 | 16 | The cache file contains key-value pairs saved in *JSON* format. The key is the normalized input source code files, and the data structure for the value is as below: 17 | 18 | Property | Description 19 | ---------------------|-------------------------- 20 | TriggeredUTCTime | The UTC time when the action is triggered 21 | CompletedUTCTime | The UTC time when the action is completed 22 | OutputFolder | The output folder for the extracted result 23 | RelativeOutputFiles | The paths of the extracted results related to the *OutputFolder* 24 | CheckSum | The MD5 checksum calculated for all the extracted results 25 | 26 | Detailed Steps are described below: 27 | 1. For each input solution/project/source files, get most latest `LastModifiedTime`. 28 | a. For solution, get `LastModifiedTime` for the solution file, and containing projects 29 | b. For project, get `LastModifiedTime` for the project file, project references, assembly references and containing documents. 30 | c. For source files, get `LastModifiedTime` for the files 31 | 2. Normalize project list, check if *Application* level cache for these project list exists. Compare `TriggeredUTCTime` with the `LastModifiedTime` fetched in #1, and check if checksum remains unchanged for output files. If is, copy result files to output folder. Otherwise, continue to #3. 32 | 33 | 3. For each supported solution/project/source code files, 34 | 35 | *Step 1*. Check if *Project* level cache exists. If not, go to *Step 4*. 36 | 37 | *Step 2*. Compare `TriggeredUTCTime` with the `LastModifiedTime` fetched in #1, and check if checksum remains unchanged for output files. If not, go to *Step 3*. 38 | 39 | *Step 3*. Generate YAML metadata for current project and save to *Project* level cache. 40 | 41 | 4. Read YAML metadata for each project, and merge with others following rules below: 42 | 43 | *Rule 1*. For `namespace`, if `uid` equals, **append**. 44 | 45 | *Rule 2*. For other type, if `uid` equals, **override**. 46 | 47 | 5. Save result, and update **Application* level cache. 48 | -------------------------------------------------------------------------------- /samples/spec/images/docfx_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/spec/images/docfx_workflow.png -------------------------------------------------------------------------------- /samples/spec/images/docfx_workflow.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/spec/images/docfx_workflow.vsdx -------------------------------------------------------------------------------- /samples/spec/images/docfx_workflow_highlevel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/spec/images/docfx_workflow_highlevel.png -------------------------------------------------------------------------------- /samples/spec/images/sdp_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/spec/images/sdp_workflow.png -------------------------------------------------------------------------------- /samples/spec/sdp_design_spec.md: -------------------------------------------------------------------------------- 1 | Schema-driven Document Processor(SDP) Design Spec 2 | ==================================== 3 | 4 | ## 1. Overview 5 | DocFX supports different [document processors](../tutorial/howto_build_your_own_type_of_documentation_with_custom_plug-in.md) to handle different kinds of input. With a new data model introduced in, a new document processor is required to support that model, even most of the code logic is the same for these processors. With this situation considered, a Schema-driven Document Processor (abbreviated to *SDP* below) is introduced to simplify the process. Togethor with a well defined [DocFX Document Schema](docfx_document_schema.md), SDP is able to *validate* and *process* a new data model with no extra effort needed. 6 | 7 | ## 2. Workflow 8 | The workflow for SDP is illustrated below. In general, the schema file, with suggested naming convention, has `documentType` in its name, as `{documentType}`.schema.json (When `title` is defined in the schema file, `title` is considered as the `documentType` for this schema). `docfx` loads the schema files from `schemas` subfolder in `template` folder, and creates processors for these schema files with per schema file per processor. With data models are processed, `docfx` applies templates for that `documentType` to these data model, as details illustrated in [Template Introduction](../tutorial/intro_template.md#naming-rule-for-a-renderer-file) and generates output documentation. 9 | 10 | ![Workflow for SDP](images/sdp_workflow.png) 11 | -------------------------------------------------------------------------------- /samples/spec/toc.md: -------------------------------------------------------------------------------- 1 | # Metadata Specification 2 | ## [General Metadata Specification](metadata_format_spec.md) 3 | ## [.NET Metadata Specification](metadata_dotnet_spec.md) 4 | # Schema-driven Document Processor 5 | ## [Schema v1.0 Specification](docfx_document_schema.md) 6 | ## [Processor Design Specification](sdp_design_spec.md) 7 | # [DocFX Flavored Markdown](docfx_flavored_markdown.md) 8 | # [Triple Slash Comments Support](triple_slash_comments_spec.md) 9 | # [Generated Manifest Specification](docfx_build_manifest_file.md) 10 | # [DocFX Design Specification](docfx_design_spec.md) 11 | -------------------------------------------------------------------------------- /samples/spec/triple_slash_comments_spec.md: -------------------------------------------------------------------------------- 1 | Triple-slash (///) Code Comments Support 2 | ========================================== 3 | DocFX extracts [triple-slash (///) code comments](https://docs.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/xmldoc/xml-documentation-comments) from .NET source code when running `docfx metadata`. [Tags](https://docs.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments) in triple-slash (///) code comments are converted to corresponding metadata in .NET data model. 4 | 5 | > [!NOTE] 6 | > `docfx` supports [DocFX Flavored Markdown syntax](docfx_flavored_markdown.md) inside triple-slash (///) code comments. You can disable this feature by set `shouldSkipMarkup` when generating metadata: `docfx metadata --shouldSkipMarkup`. 7 | 8 | Supported tags 9 | -------- 10 | ### Top level block tags 11 | Top level block tags are transformed to corresponding metadata in .NET data model. 12 | 13 | | Tags | Metadata name | Type 14 | | --- | --- | --- 15 | | `summary` | `summary` | `string` 16 | | `remarks` | `remarks` | `string` 17 | | `returns` | `returns` | `string` 18 | | `value` | `returns` | `string` 19 | | `exception` | `exception` | `List<`@"Microsoft.DocAsCode.DataContracts.ManagedReference.ExceptionInfo"`>` 20 | | `seealso` | `seealso` | `List<`@"Microsoft.DocAsCode.DataContracts.ManagedReference.LinkInfo"`>` 21 | | `see` | `see` | `List<`@"Microsoft.DocAsCode.DataContracts.ManagedReference.LinkInfo"`>` 22 | | `example` | `example` | `List` 23 | 24 | ### Non-toplevel tags 25 | Non-toplevel tags transformed to HTML tags in DocFX. 26 | 27 | |Tags | Transformed | Description 28 | |--- | --- | --- 29 | | `para` | `

` 30 | | `b` | `` 31 | | `i` | `em` 32 | | `see[@langword]`| `` | [langwordMapping.yml](https://github.com/dotnet/docfx/blob/27f7f55746dc48f0d7700205c52dff071b51427b/Documentation/langwordmapping/langwordMapping.yml) lists supported language keywords in `DocFX`. DocFX leverages [cross reference](docfx_flavored_markdown.md#cross-reference) to reference language keywords. You can disable default langword resolver and apply your customized one by calling `docfx build --xref yourLangword.yml --noLangKeyword` 33 | | `see[@href]` | `` 34 | | `see[@cref]` | `` 35 | | `paramref` | `` 36 | | `typeparamref` | `` 37 | | `list type="table"` | `
` 38 | | `list type="bullet"` | `
    ` 39 | | `list type="number"` | `
      ` 40 | | `c` | `` 41 | | `code` | `
      ` 42 | 43 | Custom tags 44 | ------- 45 | ### inheritdoc 46 | `docfx` supports a subset of the [inheritdoc functionality available in Sandcastle](https://ewsoftware.github.io/XMLCommentsGuide/html/86453FFB-B978-4A2A-9EB5-70E118CA8073.htm). Specifically, it implements most of the "Top-Level Inheritance Rules". It does not implement: 47 | * Support for the `select` attribute. 48 | * Automatic inheritance of documentation for explicit interface implementations. 49 | * Support for inline `inheritdoc` tags (i.e., an `inheritdoc` tag inside of an `example` tag). 50 | 51 | -------------------------------------------------------------------------------- /samples/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Tutorials 2 | href: tutorial/ 3 | - name: Specifications 4 | href: spec/ 5 | homepage: spec/metadata_format_spec.md 6 | - name: API Documentation 7 | href: obj/temp/docfxapi/ 8 | -------------------------------------------------------------------------------- /samples/tutorial/advanced_support_hyperlink.md: -------------------------------------------------------------------------------- 1 | 🔧 Advanced: Support Hyperlink 2 | =============================== 3 | 4 | In this topic, we will support hyperlinking in rtf files. 5 | 6 | Create a hyperlink in the rtf file: 7 | 1. Open `foo.rtf` by `Word`. 8 | 2. Add a hyperlink in content 9 | 3. Set the link target to an existing `bar.rtf` 10 | 4. Save the document. 11 | 12 | About link 13 | ---------- 14 | An author can write any valid hyperlink in the document, and then needs to run `DocFX build` to update file links. 15 | 16 | ### What is file link: 17 | 1. The hyperlink must be a relative path and not rooted. 18 | * valid: `foo\bar.rtf`, `../foobar.rtf` 19 | * invalid: `/foo.rtf`, `c:\foo\bar.rtf`, `http://foo.bar/`, `mailto:foo@bar.foobar` 20 | 2. The file must exist. 21 | 22 | ### Why update file link: 23 | 24 | The story is: 25 | 1. In `foo.rtf`, it has a file link to `bar.rtf`. 26 | 2. In document build, `bar.rtf` generates a file with the name `bar.html`. 27 | 3. But in `foo.rtf`, the link target is still `bar.rtf`, thus in the output folder we cannot find this file and we will get a broken link. 28 | 4. To resolve the broken link, we need to update the link target from `bar.rtf` to `bar.html`. 29 | 30 | File link is a relative path, but we cannot track the relative path easily. 31 | So we track the *normalized file path* instead. 32 | 33 | ### What is a *normalized file path*: 34 | 1. It always starts from the working folder (the folder that contains `docfx.json`), and we write it as `~/`. 35 | 2. No `../` or `./` or `//` 36 | 3. Replace `\` with `/`. 37 | 4. No url encoding. The path must be same as it in the file system. 38 | 5. No anchor. 39 | 40 | Finally, a valid *normalized file path* looks like: `~/foo/bar.rtf`. 41 | 42 | * Pros 43 | * Same form in different documents when the target is the same file. 44 | 45 | When file structure is: 46 | ``` 47 | z:\a\b\foo.rtf 48 | z:\a\b\c\bar.rtf 49 | z:\a\b\c\foobar.rtf 50 | ``` 51 | Link target `c/foobar.rtf` in `foo.rtf` and link target `foobar.rtf` in `bar.rtf` is the same file. 52 | When the working folder is `z:\a\`, the link target is always `~/b/c/foobar.rtf`. 53 | 54 | * Avoids differences in style when referring to the same file. 55 | 56 | For example, the following hyperlinks target the same file: `a/foo.rtf`, `./a/foo.rtf`, `a/b/../foo.rtf`, `a//foo.rtf`, `a\foo.rtf` 57 | 58 | * Cons 59 | * A folder with the name `~` is not supported. 60 | 61 | Prepare 62 | ------- 63 | 1. Open the rtf plug-in library project in `Visual Studio`. 64 | 65 | 2. Add nuget packages: 66 | for plug-in: `Microsoft.DocAsCode.Utility` 67 | 68 | 3. Add framework assembly reference: 69 | `System.Core`, `System.Web`, `System.Xml.Linq` 70 | 71 | Update rtf document processor 72 | ----------------------------- 73 | 1. Following the rules for hyperlink, add a `FixLink` help method: 74 | [!Code-csharp[FixLink](../codesnippet/Rtf/Hyperlink/RtfDocumentProcessor.cs?name=FixLink)] 75 | 76 | `RelativePath` helps us generate the links correctly. 77 | 78 | 2. Then add `CollectLinksAndFixDocument` method: 79 | [!Code-csharp[CollectLinksAndFixDocument](../codesnippet/Rtf/Hyperlink/RtfDocumentProcessor.cs?name=CollectLinksAndFixDocument)] 80 | 81 | 3. Modify `Save` method with report links: 82 | [!Code-csharp[Save](../codesnippet/Rtf/Hyperlink/RtfDocumentProcessor.cs?name=Save)] 83 | 84 | 85 | 86 | View final [RtfDocumentProcessor.cs](../codesnippet/Rtf/Hyperlink/RtfDocumentProcessor.cs) 87 | 88 | 89 | Test and verify 90 | --------------- 91 | 1. Build project. 92 | 2. Copy dll to `Plugins` folder. 93 | 3. Modify rtf file, create hyperlink, link to another rtf file, and save. 94 | 4. Build with command `DocFX build`. 95 | 5. Verify output html file. -------------------------------------------------------------------------------- /samples/tutorial/artifacts/docfx.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/artifacts/docfx.zip -------------------------------------------------------------------------------- /samples/tutorial/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | This tutorial shows how to build a documentation website. 4 | 5 | You'll learn how to: 6 | 7 | - Create the documentation project. 8 | - Add a homepage. 9 | - Add a markdown document. 10 | 11 | ## Installation 12 | 13 | The easiest way to install docfx is to use [.NET Tools](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools). Install the latest version of [.NET SDK](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) and run: 14 | 15 | ``` 16 | dotnet tool install -g docfx 17 | ``` 18 | 19 | Or you can download from [GitHub Releases](https://github.com/dotnet/docfx/releases). 20 | 21 | ## Create a documentation project 22 | 23 | Open a command shell, and enter the following command: 24 | 25 | ``` 26 | docfx new conceptual -o mydocs 27 | ``` 28 | 29 | The preceding command creates a new documentation project. The `-o mydocs` parameter creates a directory named `mydocs` with the project files inside. 30 | 31 | ## Run the website locally 32 | 33 | Run the following command: 34 | 35 | ``` 36 | docfx build mydocs 37 | docfx serve mydocs --watch 38 | ``` 39 | 40 | After the command shell indicates that the website has started, browse to https://localhost:5001. 41 | 42 | 43 | [!code[name](toc.yml?highlight=1,2-2,4-)] -------------------------------------------------------------------------------- /samples/tutorial/howto_add_a_customized_post_processor.md: -------------------------------------------------------------------------------- 1 | How-to: Add a customized post-processor 2 | ==================================== 3 | 4 | We provide the ability to process output files by adding a customized post-processor. 5 | In DocFX, the index file for full-text-search is generated by one post-processor named `ExtractSearchIndex`. 6 | In this topic, we will show how to add a customized post-processor. 7 | 8 | ## Step0: Preparation 9 | 10 | * Create a new C# class library project in `Visual Studio`. 11 | * Add nuget packages: 12 | * [`System.Collections.Immutable`](https://www.nuget.org/packages/System.Collections.Immutable/1.3.1) with version 1.3.1 13 | * [`Microsoft.Composition`](https://www.nuget.org/packages/Microsoft.Composition/1.0.31) with version 1.0.31 14 | * Add `Microsoft.DocAsCode.Plugins` 15 | If you are building DocFX from source code, add this reference to the project, 16 | otherwise add the nuget package `Microsoft.DocAsCode.Plugins` with the same version as DocFX. 17 | 18 | ## Step1: Create a new class (MyProcessor.cs) with the following code: 19 | 20 | ```csharp 21 | [Export(nameof(MyProcessor), typeof(IPostProcessor))] 22 | public class MyProcessor : IPostProcessor 23 | { 24 | // TODO: implements IPostProcessor 25 | } 26 | ``` 27 | 28 | ## Step2: Update global metadata 29 | 30 | ```csharp 31 | public ImmutableDictionary PrepareMetadata(ImmutableDictionary metadata) 32 | { 33 | // TODO: add/remove/update property from global metadata 34 | return metadata; 35 | } 36 | ``` 37 | 38 | In this method, we can update the global metadata before building all the files declared in `docfx.json`. Otherwise, you can just return the metadata from parameters if you don't need to change global metadata. 39 | 40 | Using `ExtractSearchIndex` for example, we add `"_enableSearch": true` in global metadata. The default template would then know it should load a search box in the navbar. 41 | 42 | ## Step3: Process all the files generated by DocFX 43 | 44 | ```csharp 45 | public Manifest Process(Manifest manifest, string outputFolder) 46 | { 47 | // TODO: add/remove/update all the files included in manifest 48 | return manifest; 49 | } 50 | ``` 51 | 52 | Input for the method `manifest` contains a list of all files to process, and `outputFolder` specifies the output folder where our static website will be placed. We can implement customized operations here to process all files generated by DocFX. 53 | 54 | > [!Note] 55 | > Post-processor aims to process the output files, so the `FileModel` can't be accessed in this phase. If some metadata is needed here, an option is to save it in `FileModel.ManifestProperties` in build phase, then access it through `ManifestItem.Metadata`. Another option is to save it somewhere in output files, like HTML's `` Tag. 56 | 57 | Using `ExtractSearchIndex` for example again, we traverse all HTML files, extract key words from these HTML files and save a file named `index.json` under the `outputFolder`. Finally we return the manifest which is not modified. 58 | 59 | ## Step4: Build your project and copy the output dll files to: 60 | 61 | * Global: the folder with name `Plugins` under DocFX.exe 62 | * Non-global: the folder with name `Plugins` under a template folder, then run `DocFX build` command with parameter `-t {template}`. 63 | 64 | *Hint*: DocFX can merge templates, so we can specify multiple template folders as `DocFX build -t {templateForRender},{templateForPlugins}`. Each of the template folders should have a subfolder named `Plugins` with exported assemblies. 65 | 66 | ## Step5: Add your post processor in `docfx.json` 67 | 68 | In this step, we need to enable the processor by adding its name in `docfx.json`. Here is an example: 69 | 70 | ```json 71 | { 72 | "build": { 73 | ... 74 | "postProcessors": ["OutputPDF", "BeautifyHTML", "OutputPDF"] 75 | } 76 | } 77 | ``` 78 | 79 | As you can see, the `postProcessors` is an array, which means it could have multiple processors. 80 | It needs to be pointed out that the order of `postProcessors` written in `docfx.json` is also the order to process output files. 81 | In the above example, DocFX will run `OutputPDF` first, then `BeautifyHTML`, and then `OutputPDF` again. 82 | 83 | If you want to enable the post processors without changing `docfx.json`, you can use the build command option like `docfx build --postProcessors=OutputPDF,BeautifyHTML,OutputPDF`. 84 | 85 | One more thing need to be noted: the build command option `postProcessors` would override the corresponding configuration in `docfx.json`. 86 | -------------------------------------------------------------------------------- /samples/tutorial/howto_create_custom_template.md: -------------------------------------------------------------------------------- 1 | How-to: Create A Custom Template 2 | =============================== 3 | 4 | Templates are organized as a zip package or a folder. The file path (without the `.zip` extension) of the zip package or the path of the folder is considered to be the template name. 5 | 6 | Quickstart 7 | --------------- 8 | Let's create a template to transform Markdown files into a simple html file. 9 | 10 | ### Step 1. Create a template folder 11 | Create a folder for the template, for example, `c:/docfx_howto/simple_template`. 12 | 13 | ### Step 2. Add *Renderer* file 14 | Create a file `conceptual.html.primary.tmpl` under the template folder with the following content: 15 | 16 | ```mustache 17 | {{{conceptual}}} 18 | ``` 19 | 20 | Now a simple custom template is created. 21 | 22 | You may notice that DocFX reports a warning message saying that: *Warning: [Build Document.Apply Templates]There is no template processing document type(s): Toc*. It is because our custom template only specifies how to handle document with type `conceptual`. 23 | 24 | To test the output of the template, create a simple documentation project following [Walkthrough Part I](walkthrough/walkthrough_create_a_docfx_project.md) or download the [zipped documentation project](walkthrough/artifacts/walkthrough1.zip) directly. 25 | 26 | In the documentation project, run `docfx build docfx.json -t c:/docfx_howto/simple_template --serve`. The `-t` command option specifies the template name(s) used by the current build. 27 | 28 | Open http://localhost:8080 and you can see a simple web page as follows: 29 | 30 | ![Simple Web Page](images/simple_web_page.png) 31 | 32 | Add *Preprocessor* file 33 | ----------------------- 34 | ### Step 3. Add *Preprocessor* file 35 | Sometimes the input data model is not exactly what *Renderer* wants, you may want to add some properties to the data model, or modify the data model a little bit before applying the *Renderer* file. This can be done by creating a *Preprocessor* file. 36 | 37 | Create a file `conceptual.html.primary.js` under the template folder with the following content: 38 | 39 | ```javascript 40 | exports.transform = function (model) { 41 | model._extra_property = "Hello world"; 42 | return model; 43 | } 44 | ``` 45 | 46 | Update the file `conceptual.html.primary.tmpl` with the following content: 47 | 48 | ```mustache 49 |

      {{_extra_property}}

      50 | {{{conceptual}}} 51 | ``` 52 | 53 | In the documentation project, run `docfx build docfx.json -t c:/docfx_howto/simple_template --serve`. 54 | 55 | Open http://localhost:8080 and you can see `_extra_property` is added to the web page. 56 | 57 | ![Updated Web Page](images/web_page_with_extra_property.png) 58 | 59 | Merge template with `default` template 60 | ------------------------------------------ 61 | DocFX contains some embedded template resources that you can refer to directly. You can use `docfx template list` to list available templates provided by DocFX. 62 | 63 | Take `default` template as an example. 64 | 65 | Run `docfx template export default`. It exports what's inside `default` template into the folder `_exported_templates`. You can see that there are sets of *Preprocessor* and *Renderer* files to deal with different types of documents. 66 | 67 | DocFX supports specifying multiple templates for a documentation project. That allows you to leverage the `default` template for handling other types of documents, together with your custom template. 68 | 69 | When dealing with multiple templates, DocFX merges the files inside these templates. 70 | 71 | The principle for merging is: if a file name collides then the file in the latter template overwrites the one in the former template. 72 | 73 | For example, you can merge `default` template and your custom template by calling `docfx build docfx.json -t default,c:/docfx_howto/simple_template`. Multiple templates are split by a comma `,` in the command line. Or you can define it in `docfx.json` by: 74 | ``` 75 | "build": { 76 | "template": [ 77 | "default", 78 | "c:/docfx_howto/simple_template" 79 | ] 80 | } 81 | ``` 82 | 83 | In the documentation project, run `docfx build docfx.json -t default,c:/docfx_howto/simple_template --serve`. 84 | 85 | Now the warning message *There is no template processing document type(s): Toc* disappears because the default template contains *Renderer* to handle TOC files. 86 | 87 | Open http://localhost:8080/toc.html and you can see a toc web page. 88 | ![TOC Web Page](images/toc_web_page.png) 89 | 90 | > [!Tip] 91 | > Run `docfx template export default` to view what's inside the default template. 92 | > 93 | > [!Note] 94 | > It is possible that DocFX updates its embedded templates when a new version is released. 95 | > So please make sure to re-export the template if you overwrite or are dependent on it in your custom template. 96 | 97 | Extension for *Preprocessor* file 98 | ---------------------------------- 99 | If you want to modify some properties based on DocFX `default` template's *Preprocessor*, you can use *Preprocessor* extension file to achieve this. 100 | 101 | For example, if you want to add a property to the managed reference's data model after `default` template's *Preprocessor*, you can update the file `ManagedReference.extension.js` in your custom template with the following content: 102 | ``` 103 | /** 104 | * This method will be called at the start of exports.transform in ManagedReference.html.primary.js 105 | */ 106 | exports.preTransform = function (model) { 107 | return model; 108 | } 109 | 110 | /** 111 | * This method will be called at the end of exports.transform in ManagedReference.html.primary.js 112 | */ 113 | exports.postTransform = function (model) { 114 | model._extra_property = "Hello world"; 115 | return model; 116 | } 117 | ``` 118 | Compared with modifying `ManagedReference.html.primary.js` directly, you needn't worry about merging your custom templates with DocFX's embedded templates when DocFX updates. 119 | -------------------------------------------------------------------------------- /samples/tutorial/images/simple_web_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/images/simple_web_page.png -------------------------------------------------------------------------------- /samples/tutorial/images/toc_web_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/images/toc_web_page.png -------------------------------------------------------------------------------- /samples/tutorial/images/web_page_with_extra_property.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/images/web_page_with_extra_property.png -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/advanced_cache_file_structure.md: -------------------------------------------------------------------------------- 1 | 🔧 Advanced: Cache File Structure 2 | ===================================== 3 | 4 | DocFX incremental build cache files are centralized and put in a folder specified with option `--intermediateFolder` or `obj/.cache/build/` relative to your `docfx.json` by default. 5 | 6 | In the root folder of the cache files, there is a `build.info`, it is kind of index page, which is the entry point of the cache files. Below table lists the major information inside. 7 | 8 | ### BuildInfo model 9 | 10 | Property | Type | Description 11 | --------------------- | --------------------- | ----------------------------------------------------------- 12 | DirectoryName | string | Base directory of the cache files of last successful build 13 | DocfxVersion | string | DocFX version 14 | PluginHash | string | The hash of plugins plugged in DocFX 15 | TemplateHash | string | The hash of specified Templates 16 | Versions | List<[BuildVersionInfo](#buildversioninfo-model)> | entry point of the cache files per version 17 | PostProcessInfo | [PostProcessInfo](#postprocessinfo-model) | The entry point of the cache files for postprocessor 18 | 19 | ### BuildVersionInfo model 20 | 21 | Property | Type | Description 22 | --------------------- | --------------------- | ----------------------------------------------------------- 23 | VersionName | string | Version name 24 | ConfigHash | string | The hash of configs for the version 25 | DependencyFile | string | The file link for dependency 26 | AttributesFile | string | The file link for file attributes 27 | OutputFile | string | The file link for build outputs 28 | ManifestFile | string | The file link for the manifest file 29 | XRefSpecMapFile | string | The file link for the XRefMap file 30 | ExternalXRefSpecFile | string | The file link for the ExternalXRefSpec file 31 | FileMapFile | string | The file link for the FileMap file 32 | BuildMessageFile | string | The file link for build message file 33 | TocRestructionsFile | string | The file link for TocRestructions file 34 | Processors | List<[ProcessorInfo](#processorinfo-model)> | The entry point of the cache files per processor 35 | 36 | ### ProcessorInfo model 37 | 38 | Property | Type | Description 39 | --------------------- | --------------------- | ----------------------------------------------------------- 40 | Name | string | The name of the processor 41 | IncrementalContextHash | string | The context hash of the processor 42 | IntermediateModelManifestFile | string | The file link for the BuildModel manifest file 43 | Steps | List<[ProcessorStepInfo](#processorstepinfo-model)> | The entry point of cache files per step for the processor 44 | 45 | ### ProcessorStepInfo model 46 | 47 | Property | Type | Description 48 | --------------------- | --------------------- | ----------------------------------------------------------- 49 | Name | string | The name of the step 50 | IncrementalContextHash | string | The context hash of the step 51 | ContextInfoFile | string | The file link for the context info for the step 52 | 53 | ### PostProcessInfo model 54 | 55 | Property | Type | Description 56 | --------------------- | --------------------- | --------------------- 57 | MessageInfoFile | string | The file link for the log message file, to restore the warning message 58 | ManifestItemsFile | string | The file link for the manifest items file, to restore the manifest items 59 | PostProcessOutputsFile | string | The file link for post processing outputs 60 | PostProcessorInfos | List<[PostProcessorInfo](#postprocessorinfo-model)> | The information of post processors 61 | 62 | ### PostProcessorInfo model 63 | 64 | | Property | Type | Description | 65 | |------------------------|--------|------------------------------------| 66 | | Name | string | The name of the step | 67 | | IncrementalContextHash | string | The context hash of the step | 68 | | ContextInfoFile | string | The file link for the context info | 69 | 70 | -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/customize_a_post_processor_to_be_incremental.md: -------------------------------------------------------------------------------- 1 | # Walkthrough: Customize a post processor to be incremental 2 | 3 | In this tutorial, we'll walk through how to enable a post processor to be incremental. 4 | 5 | ## Implement @Microsoft.DocAsCode.Plugins.ISupportIncrementalPostProcessor for the post processor 6 | 7 | ```csharp 8 | public class AppendIntegerPostProcessor : ISupportIncrementalPostProcessor 9 | { 10 | // to-do: implements IPostProcessor 11 | 12 | public IPostProcessorHost PostProcessorHost { get; set; } 13 | 14 | public string GetIncrementalContextHash() 15 | { 16 | // to-do: incremental context hash. If it changes, incremental post processing isn't triggered. 17 | } 18 | } 19 | ``` 20 | 21 | ## Optional: Load and save customized context information from cache 22 | 23 | @Microsoft.DocAsCode.Plugins.IPostProcessorHost is the host to provide incremental post processing information as following. 24 | 25 | Property | Type | Description 26 | --------------------- | --------------------- | --------------------- 27 | SourceFileInfos | List of @Microsoft.DocAsCode.Plugins.SourceFileInfo | Information of source files 28 | ShouldTraceIncrementalInfo | bool | Whether the post processor should trace incremental information 29 | IsIncremental | bool | Whether the post processor can be incremental 30 | 31 | @Microsoft.DocAsCode.Plugins.IPostProcessorHost can also load and save customized context information per post processor in incremental cache. 32 | 33 | Method | Return Type | Description 34 | --------------------- | --------------- | --------------------- 35 | LoadContextInfo() | Stream | Load context information from last post processing 36 | SaveContextInfo() | Stream | Save context information to current post processing 37 | 38 | Here's the sample: 39 | ```csharp 40 | public class AppendIntegerPostProcessor : ISupportIncrementalPostProcessor 41 | { 42 | public IPostProcessorHost PostProcessorHost { get; set; } 43 | 44 | public string GetIncrementalContextHash() { return string.Empty; } 45 | 46 | public Manifest Process(Manifest manifest, string outputFolder) 47 | { 48 | string contextInfo = string.Empty; 49 | var stream = PostProcessorHost.LoadContextInfo(); 50 | if (stream != null) 51 | { 52 | using (var sr = new StreamReader(stream)) 53 | { 54 | contextInfo = sr.ReadToEnd(); 55 | } 56 | } 57 | 58 | using (var saveStream = PostProcessorHost.SaveContextInfo()) 59 | using (var sw = new StreamWriter(saveStream)) 60 | { 61 | sw.Write(contextInfo + "-updated"); 62 | } 63 | 64 | return manifest; 65 | } 66 | } 67 | ``` -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/customize_a_processor_to_support_incremental.md: -------------------------------------------------------------------------------- 1 | Walkthrough: Customize a processor to support incremental build 2 | ================================================================ 3 | 4 | During this tutorial, we'll walk through the steps to enable a processor to be incremental. 5 | 6 | Step1. Implement @Microsoft.DocAsCode.Plugins.ISupportIncrementalDocumentProcessor interface for the processor 7 | ------------------------------------------------------------------------------------ 8 | 9 | ```csharp 10 | public class RtfDocumentProcessor : ISupportIncrementalDocumentProcessor 11 | { 12 | // to-do: implements IDocumentProcessor 13 | 14 | public virtual string GetIncrementalContextHash() 15 | { 16 | // to-do: context related hash. if it changes, incremental build isn't triggered. 17 | } 18 | 19 | public virtual void SaveIntermediateModel(FileModel model, Stream stream) 20 | { 21 | // to-do: the logic to store filemodel 22 | } 23 | 24 | public virtual FileModel LoadIntermediateModel(Stream stream) 25 | { 26 | // to-do: the logic to load filemodel 27 | } 28 | } 29 | ``` 30 | 31 | Step2. Implement @Microsoft.DocAsCode.Plugins.ISupportIncrementalBuildStep interface for all the plugins plugged in the processor 32 | ------------------------------------------------------------------------------------------------------ 33 | Plugins are flexible to register customized dependency types by implementing the interface's method @Microsoft.DocAsCode.Plugins.ISupportIncrementalBuildStep.GetDependencyTypesToRegister. 34 | 35 | Plugins are also flexible to report dependencies by invoking the methods provided by @Microsoft.DocAsCode.Plugins.IHostService. 36 | 37 | ```csharp 38 | public class RtfBuildStep : ISupportIncrementalBuildStep 39 | { 40 | // to-do: implements IDocumentBuildStep 41 | 42 | public bool CanIncrementalBuild(FileAndType fileAndType) => true; 43 | 44 | public string GetIncrementalContextHash() => null; 45 | 46 | public IEnumerable GetDependencyTypesToRegister() => new[] 47 | { 48 | new DependencyType() 49 | { 50 | Name = "ref", 51 | Phase = BuildPhase.Link, 52 | Transitivity = DependencyTransitivity.None, 53 | } 54 | }; 55 | 56 | public override void Build(FileModel model, IHostService host) 57 | { 58 | //..... 59 | host.ReportDependencyTo(model, "uid", DependencyItemSourceType.Uid, "ref"); 60 | } 61 | } 62 | ``` 63 | 64 | The above sample registered a dependency type named `ref`, this type of dependency applies during `Link` phase and it isn't transitive. `DocFX` has some reserved dependency types, you can refer to [Reserved Dependency Types](advanced_report_dependency.md#reserved-dependency-types) for more details. 65 | 66 | In `Build` step, this plugin reports dependencies of type `ref` by invoking @Microsoft.DocAsCode.Plugins.IHostService 's `ReportDependencyTo` method. @Microsoft.DocAsCode.Plugins.IHostService also provides `ReportDependencyFrom` method you can report reverse dependency. 67 | 68 | For more details about how to register your own dependency types and report , you can refer to [Advanced: register and report dependency](advanced_report_dependency.md). 69 | 70 | 71 | Step3. [Optional]Implement @Microsoft.DocAsCode.Plugins.ICanTraceContextInfoBuildStep interface for plugins that need to access context info 72 | ----------------------------------------------------------------------------------------------------------------------- 73 | When building articles, some plugins might need the info of unloaded articles. Incremental Build Framework provides the interface @Microsoft.DocAsCode.Plugins.ICanTraceContextInfoBuildStep, which is the superset of @Microsoft.DocAsCode.Plugins.ISupportIncrementalBuildStep and also contains methods to save/load context info. 74 | 75 | ```csharp 76 | public class RtfBuildStep : ICanTraceContextInfoBuildStep 77 | { 78 | // to-do: implements ISupportIncrementalBuildStep 79 | 80 | public void LoadContext(Stream stream) 81 | { 82 | // to-do: the logic to load last context info 83 | } 84 | 85 | public void SaveContext(Stream stream) 86 | { 87 | // to-do: the logic to save current context info 88 | } 89 | } 90 | ``` 91 | 92 | 93 | Now you're done! Your processor can run incrementally! -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/images/incrementalbuildframework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/incrementalbuild/images/incrementalbuildframework.png -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/images/incrementalpostprocessingframework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/incrementalbuild/images/incrementalpostprocessingframework.png -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/intro_incremental_post_processing.md: -------------------------------------------------------------------------------- 1 | # Introduction to *DocFX Incremental Post Processing* 2 | 3 | ## Workflow 4 | 5 | ![DocFX incremental post processing workflow](images/incrementalpostprocessingframework.png) 6 | 7 | Overall, the output of all post processors would be cached in following: 8 | 1. Manifest items: to restore incremental manifest items. 9 | 2. Log message info: to replay the log message. 10 | 3. Output files: to restore the post processing outputs. 11 | 12 | Based on incremental build result, `IsIncremental` flag of the manifest item could hint whether the item is incremental or not. 13 | 1. If the post processing meets [Incremental Condition](#incremental-condition): 14 | 1. For the incremental manifest items, restore from cache. 15 | 2. For the non-incremental manifest items, they will be handled by post processors, and save the information into cache at the same time. 16 | 2. If the post processing doesn't meet [Incremental Condition](#incremental-condition), set `IsIncremental` flag to false to all manifest items, then they will be handled by post processors. 17 | 18 | ## Incremental Condition 19 | 20 | The post processing could be incremental only if it meets all of the following conditions: 21 | 1. Both last cache file [`build.info`](advanced_cache_file_structure.md) and its [`PostProcessInfo`](advanced_cache_file_structure.md#postprocessinfo-model) exist, which is essential to restore the last incremental post processing info. 22 | 2. Not set option `forcePostProcess` and `force` of build command or `docfx.json` config, to enable incremental post processing. 23 | 3. Post processor requirement: 24 | 1. Each of the post processor implements @Microsoft.DocAsCode.Plugins.ISupportIncrementalPostProcessor. Currently, @Microsoft.DocAsCode.Build.Engine.HtmlPostProcessor implements the interface while @Microsoft.DocAsCode.Build.Engine.ExtractSearchIndex does not. Refer to [Customize a post processor to be incremental](customize_a_post_processor_to_be_incremental.md) for more details. 25 | 2. Post processor number isn't changed. 26 | 3. Each post processor's `IncrementalContextHash` isn't changed 27 | 28 | -------------------------------------------------------------------------------- /samples/tutorial/incrementalbuild/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Introduction to DocFX incremental build 2 | href: intro_incremental_build.md 3 | - name: Customize a processor to support incremental build 4 | href: customize_a_processor_to_support_incremental.md 5 | - name: 'Advanced: Report Dependency' 6 | href: advanced_report_dependency.md 7 | - name: 'Advanced: Cache File Structure' 8 | href: advanced_cache_file_structure.md 9 | - name: Incremental post processing 10 | items: 11 | - name: Introduction to incremental post processing 12 | href: intro_incremental_post_processing.md 13 | - name: Customize a post processor to be incremental 14 | href: customize_a_post_processor_to_be_incremental.md -------------------------------------------------------------------------------- /samples/tutorial/intro_default_template.md: -------------------------------------------------------------------------------- 1 | 🔧 Default Template Introduction 2 | =============================================== 3 | 4 | ## Search Library -- [`lunr.js`](https://lunrjs.com/) 5 | 6 | ## Customize full-text search in your website 7 | 8 | ### Search enable 9 | 10 | ### Disable full-text for specific pages -------------------------------------------------------------------------------- /samples/tutorial/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Getting Started 2 | items: 3 | - name: Quickstart 4 | href: getting-started.md 5 | - name: DocFX User Manual 6 | href: docfx.exe_user_manual.md 7 | - name: "HowTo: Filter Out Unwanted APIs" 8 | href: howto_filter_out_unwanted_apis_attributes.md 9 | - name: Walkthrough Topics 10 | href: walkthrough/toc.md 11 | homepage: walkthrough/walkthrough_overview.md 12 | - name: Content 13 | items: 14 | - name: TOC 15 | href: intro_toc.md 16 | - name: REST API 17 | href: intro_rest_api_documentation.md 18 | - name: Overwrite Files 19 | href: intro_overwrite_files.md 20 | - name: Links and Cross References 21 | href: links_and_cross_references.md 22 | - name: Template 23 | items: 24 | - name: Template System 25 | href: intro_template.md 26 | - name: "HowTo: Create Custom Template" 27 | href: howto_create_custom_template.md 28 | - name: Incremental Build 29 | href: incrementalbuild/toc.yml 30 | - name: Extensibility 31 | items: 32 | - name: How to build your own type of documentation with custom plug-in 33 | href: howto_build_your_own_type_of_documentation_with_custom_plug-in.md 34 | items: 35 | - name: "Advanced: Support Hyperlink" 36 | href: advanced_support_hyperlink.md 37 | - name: How to add a customized post processor 38 | href: howto_add_a_customized_post_processor.md 39 | - name: Validate your markdown files 40 | href: validate_your_markdown_files.md 41 | - name: Intro markdown lite 42 | href: intro_markdown_lite.md 43 | - name: How to customize DocFX Flavored Markdown 44 | href: howto_customize_docfx_flavored_markdown.md 45 | - name: "Multiple Programming Languages Support" 46 | href: universalreference/toc.yml 47 | -------------------------------------------------------------------------------- /samples/tutorial/universalreference/gen_doc_for_js.md: -------------------------------------------------------------------------------- 1 | # Generate API Documentation for JavaScript 2 | 3 | ## 1. Prerequisite 4 | 5 | * [DocFX](https://dotnet.github.io/docfx/tutorial/docfx_getting_started.html#2-use-docfx-as-a-command-line-tool) 6 | * [Node.js](https://nodejs.org/en/download/) (includes npm) 7 | 8 | ## 2. Steps 9 | 10 | ### 2.1 Prepare Source Code 11 | Prepare the JavaScript source code for generating document. In this tutorial, we take [azure-batch](https://www.npmjs.com/package/azure-batch) as an example 12 | ``` 13 | npm install azure-batch 14 | ``` 15 | 16 | ### 2.2 Generate Metadata 17 | We use [Node2DocFX](https://www.npmjs.com/package/node2docfx) tool to generate YAML files. 18 | ``` 19 | npm install node2docfx 20 | ``` 21 | 22 | Create the `node2docfx.json` for the tool configuration: 23 | ```json 24 | { 25 | "source": { 26 | "include": ["node_modules/azure-batch/lib"] 27 | }, 28 | "destination": "yml" 29 | } 30 | ``` 31 | With this config, the tool will read source code under `node_modules/azure-batch/lib`, and extract metadata to YAML files under `yml` folder: 32 | ``` 33 | node node_modules/node2docfx/node2docfx.js node2docfx.json 34 | ``` 35 | 36 | ### 2.3 Build Document 37 | Create the configuration `docfx.json` for DocFX: 38 | ```json 39 | { 40 | "build": { 41 | "content": [ 42 | { 43 | "files": ["**/*.yml"], 44 | "src": "yml", 45 | "dest": "api" 46 | } 47 | ], 48 | "dest": "_site" 49 | } 50 | } 51 | ``` 52 | 53 | More information about `docfx.json` can be found in [user manual](https://dotnet.github.io/docfx/tutorial/docfx.exe_user_manual.html). Run: 54 | ``` 55 | docfx docfx.json --serve 56 | ``` 57 | Now you can see your generated pages: http://localhost:8080/api/Account.html -------------------------------------------------------------------------------- /samples/tutorial/universalreference/gen_doc_for_ts.md: -------------------------------------------------------------------------------- 1 | # Generate API Documentation for TypeScript 2 | 3 | ## 1. Prerequisite 4 | 5 | * [DocFX](https://dotnet.github.io/docfx/tutorial/docfx_getting_started.html#2-use-docfx-as-a-command-line-tool) 6 | * [Node.js](https://nodejs.org/en/download/) (includes npm) 7 | * [Git](https://git-scm.com/) 8 | 9 | ## 2. Steps 10 | 11 | ### 2.1 Prepare Source Code 12 | Prepare the TypeScript source code for generating document. In this tutorial, we take [azure-iot-device](https://github.com/Azure/azure-iot-sdk-node/tree/master/device/core) as an example. 13 | ``` 14 | git clone https://github.com/Azure/azure-iot-sdk-node.git 15 | ``` 16 | 17 | 18 | ### 2.2 Generate Metadata for a package 19 | We use [typedoc](http://typedoc.org/) tool and [type2docfx](https://www.npmjs.com/package/type2docfx) to generate YAML files. 20 | 21 | First, let's install the tools globally. 22 | ``` 23 | npm install -g typedoc type2docfx 24 | ``` 25 | 26 | #### 2.2.1 TypeDoc to parse source code into a JSON format output 27 | Go to the folder where package.json file locate. 28 | Run 29 | ``` 30 | typedoc --json api.json azure-iot-sdk-node/device/core/src --module commonjs --includeDeclarations --ignoreCompilerErrors --excludeExternals 31 | ``` 32 | 33 | The parameter may differ for your needs. You can use `typedoc -h` to explore more options. 34 | 35 | 36 | #### 2.2.2 Type2docfx to extract the JSON format output into YAML files 37 | Find the output `api.json` file and run: 38 | ``` 39 | type2docfx api.json yml 40 | ``` 41 | The `yml` stands for the output folder, you can specify the folder as the content publishing folder in Section 2.3. And you can explore more option by `type2docfx -h`. With `--sourceUrl, --sourceBranch, and --basePath` parameters, you can generate yaml files referencing to the source code in Github, which will help developer to find the corresponding source code easily. 42 | 43 | > [!NOTE] 44 | > 45 | > All sources under `node_modules` path will be automatically ignored. 46 | 47 | ### 2.3 Build Document 48 | Create the configuration `docfx.json` for DocFX: 49 | ```json 50 | { 51 | "build": { 52 | "content": [ 53 | { 54 | "files": ["**/*.yml"], 55 | "src": "yml", 56 | "dest": "api" 57 | } 58 | ], 59 | "dest": "_site" 60 | } 61 | } 62 | ``` 63 | 64 | More information about `docfx.json` can be found in [user manual](https://dotnet.github.io/docfx/tutorial/docfx.exe_user_manual.html). Run: 65 | ``` 66 | docfx docfx.json --serve 67 | ``` 68 | Now you can see your generated pages: http://localhost:8080/api/azure-iot-device/Client.html#azure_iot_device_Client 69 | 70 | ## 3. Know issues 71 | 1. Some types can't link to the property correctly now. They displays in plain text and prefixed with `@`. 72 | -------------------------------------------------------------------------------- /samples/tutorial/universalreference/intro_multiple_langs_support.md: -------------------------------------------------------------------------------- 1 | # Introduction to Multiple Languages Support 2 | 3 | ## 1. Introduction 4 | 5 | DocFX supports generating API documentation for C# and VB natively. However, it's not limited to these. DocFX is designed to support any language. When generating documents for a language, two steps are required: generating metadata and building documents from the metadata. 6 | 7 | ## 2. Workflow 8 | 9 | ### 2.1 Generate Metadata 10 | 11 | As different programming language has different tool written with different language to generate API documentation, this step is not included in DocFX core. We call the tool used as **Metadata Tool**. 12 | 13 | As [UniversalReferenceDocumentProcessor](https://github.com/dotnet/docfx/tree/dev/src/Microsoft.DocAsCode.Build.UniversalReference) is used to process these metadata files, the metadata tool should generate files according the processor's input schema. The files should: 14 | 1. be in YAML format and end with `.yml` or `.yaml` 15 | 2. have YamlMime `### YamlMime:UniversalReference` as the first line 16 | 3. conform to the [data model defined for UniversalReference](https://github.com/dotnet/docfx/tree/dev/src/Microsoft.DocAsCode.DataContracts.UniversalReference) 17 | 18 | Usually, a TOC should be generated along with YAML files for easy navigation among files. 19 | 20 | ### 2.2 Build Document 21 | 22 | The YAML files generated are used as input to DocFX. DocFX will build these YAML files into HTML pages. 23 | 24 | ## 3. Supported Languages 25 | * [JavaScript](gen_doc_for_js.md) 26 | * TypeScript (coming soon ...) 27 | * Python (coming soon ...) 28 | -------------------------------------------------------------------------------- /samples/tutorial/universalreference/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Introduction 2 | href: intro_multiple_langs_support.md 3 | - name: JavaScript 4 | href: gen_doc_for_js.md 5 | - name: TypeScript 6 | href: gen_doc_for_ts.md -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/TOC.md: -------------------------------------------------------------------------------- 1 | # [Part I: Generate a Simple Documentation Website](walkthrough_create_a_docfx_project.md) 2 | # [Part II: Add API Documentation to the Website](walkthrough_create_a_docfx_project_2.md) 3 | # [Part III: Generate PDF Documentation](walkthrough_generate_pdf.md) 4 | # [Advanced: Customize Your Website](advanced_walkthrough.md) -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/advanced_walkthrough.md: -------------------------------------------------------------------------------- 1 | Walkthrough Advanced: Customize Your Website 2 | =================================== 3 | 4 | ## Apply your own styles to the website or PDF 5 | 6 | ### Export the default template 7 | 8 | To export the default HTML template, open the command line at the root of the directory and run `docfx template export default`. 9 | 10 | A folder called `_exported_templates` is added at root with a directory inside called `default`. This is the DocFX default HTML template. 11 | 12 | To export the default PDF template, run `docfx template export pdf.default`. 13 | 14 | ### Create a new template 15 | 16 | Create a new directory at root to hold your custom templates - name it something like `templates`. Inside that folder, create a new folder and name it whatever you want to name your custom template. In this folder you'll replicate files from `_exported_templates/default` or `_exported_templates/pdf.default` (and only those files) you want to overwrite. 17 | 18 | ### Apply the template 19 | 20 | To apply your custom HTML template permanently, add the following to `docfx.json` at the root of the project inside `"build": {`: 21 | 22 | ``` 23 | "template": [ 24 | "default", 25 | "templates/" 26 | ], 27 | ``` 28 | 29 | To apply your custom PDF template permanently, add the following at the same level as `"content"` under `"pdf"`: 30 | 31 | ``` 32 | "template": [ 33 | "pdf.default", 34 | "templates/pdf" 35 | ], 36 | ``` 37 | 38 | To apply a template manually, append a `-t` with the template filepath to the build command: 39 | 40 | ```docfx build docfx.json -t C:\\templates\ --serve``` 41 | 42 | ### Customize your template 43 | 44 | Inside the `_exported_templates/default` or `exported_templates/pdf.default` folder, copy any file you want to overwrite with your custom template. Paste it in your custom template folder, replicating the directory structure. 45 | 46 | For example, to change the copyright in the footer of the HTML template: 47 | 48 | - Copy `_exported_templates/default/partials/footer.tmpl.partial`. 49 | - Paste it in `templates//partials`. 50 | - Edit `templates//partials`. 51 | 52 | To change the CSS of the HTML or PDF template: 53 | 54 | - Copy `_exported_templates/default/styles/main.css` or `_exported_templates/pdf.default/styles/main.css`. 55 | - Paste it in `templates//styles`. 56 | - Edit `templates//partials`. 57 | 58 | Example of changing heading styles in `main.css` for an HTML template: 59 | 60 | ``` 61 | article h1 { 62 | font-size: 40px; 63 | font-weight: 300; 64 | margin-top: 40px; 65 | margin-bottom: 20px; 66 | color: #000000; 67 | } 68 | ``` 69 | 70 | Example of preventing words from breaking across lines for an HTML template: 71 | 72 | ``` 73 | article h1, h2, h3, h4, h5, h6 { 74 | word-break: keep-all; 75 | } 76 | ``` 77 | 78 | Example of changing heading styles for a PDF template: 79 | 80 | ``` 81 | h1 { 82 | font-weight: 200; 83 | color: #007bb8; 84 | } 85 | ``` 86 | 87 | To change the look of the table of contents in the PDF template, use this file: `_exported_templates/default/toc.html.tmpl` 88 | 89 | ## See a list of all your templates 90 | 91 | ```docfx template list``` 92 | 93 | ## See template commands 94 | 95 | ```docfx help template``` 96 | -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/artifacts/walkthrough1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/artifacts/walkthrough1.zip -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/artifacts/walkthrough2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/artifacts/walkthrough2.zip -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/artifacts/walkthrough3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/artifacts/walkthrough3.zip -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/uid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/uid.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough2_step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough2_step3.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough2_step4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough2_step4.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough2_step5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough2_step5.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough3.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough_api.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough_homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough_homepage.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough_simple_homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough_simple_homepage.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/images/walkthrough_step5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/samples/tutorial/walkthrough/images/walkthrough_step5.png -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/walkthrough_create_a_docfx_project.md: -------------------------------------------------------------------------------- 1 | Walkthrough Part I: Generate a Simple Documentation Website 2 | =================================== 3 | 4 | By completing this walkthrough, you'll become familiar with the workflow of `docfx` and the general principle of organizing documents inside `docfx`. You will finish this walkthrough with a static website that can be published to any host service. Download the files used in this walkthrough [here](artifacts/walkthrough1.zip). 5 | 6 | Step1. Setup DocFX 7 | ------------------------ 8 | Download *docfx* from http://dotnet.github.io/docfx/. [Getting Started with docfx](http://dotnet.github.io/docfx/tutorial/docfx_getting_started.html#2-use-docfx-exe-directly) describes three ways to install *docfx*. This walkthrough uses the first one: Use *docfx.exe* directly. 9 | 10 | 1. Download *docfx.zip* and unzip it to `D:\docfx\` 11 | 2. Add `D:\docfx\` to `PATH` so that the command `docfx` can be directly called from everywhere for convenience. (For example, for Windows, `set PATH=%PATH%;D:\docfx\`.) 12 | 13 | Step2. Init a DocFX project 14 | --------------------------- 15 | 1. Create a new folder `D:\docfx_walkthrough` 16 | 2. Start Command Line under `D:\docfx_walkthrough` 17 | 3. Call `docfx init -q`. This command generates a `docfx_project` folder with the default `docfx.json` file under it. `docfx.json` is the configuration file `docfx` uses to generate documentation. `-q` option means generating the project quietly using default values, you can also try `docfx init` and follow the instructions to provide your own settings. 18 | 19 | Step3. Build our website 20 | ----------------------- 21 | Run command `docfx docfx_project/docfx.json`. Note that a new subfolder `_site` is generated under that folder. This is where the static website is generated. 22 | 23 | Step4. Preview our website 24 | ------------------------- 25 | The generated static website can be published to GitHub pages, Azure websites, or your own hosting services without any further changes. You can also run command `docfx serve docfx_project/_site` to preview the website locally. 26 | 27 | If port `8080` is not in use, `docfx` will host `_site` under `http://localhost:8080`. If `8080` is in use, you can use `docfx serve _site -p ` to change the port to be used by `docfx`. 28 | 29 | Congrats! You can now see a simple website similar to: 30 | ![Homepage](images/walkthrough_simple_homepage.png) 31 | 32 | ---------------------- 33 | 34 | Step5. Add a set of articles to the website 35 | ------------------------- 36 | 1. Place more `.md` files into `articles`, e.g., `details1.md`, `details2.md`, `details3.md`. If the files reference any resources, put those resources into the `images` folder. 37 | 2. In order to organize these articles, we add these files into `toc.yml` under `articles` subfolder. The content of `toc.yml` is as below: 38 | 39 | ```yml 40 | - name: Introduction 41 | href: intro.md 42 | - name: Details 1 43 | href: details1.md 44 | - name: Details 2 45 | href: details2.md 46 | - name: Details 3 47 | href: details3.md 48 | ``` 49 | 50 | So now our folder layout is: 51 | ``` 52 | |- index.md 53 | |- toc.yml 54 | |- articles 55 | | |- intro.md 56 | | |- details1.md 57 | | |- details2.md 58 | | |- details3.md 59 | | |- toc.yml 60 | |- images 61 | |- details1_image.png 62 | ``` 63 | 4. Run **Step3** and **Step4** again, and the website is now: 64 | ![Step7](images/walkthrough_step5.png). 65 | 66 | Notice that more items are added to the sidebar for *Articles* nav page. The title inside the sidebar is exactly what we set in the `toc.yml` inside `articles` subfolder. 67 | 68 | Conclusion 69 | --------- 70 | In this walkthrough, we built a website from a set of `.md` files. We call these `.md` files **Conceptual Documentation**. In walkthrough part 2, we will learn to add **API Documentation** to our website. The **API Documentation** is extracted directly from .NET source code. In a series of advanced walkthroughs, we will learn advanced concepts in `docfx`, such as *cross reference* between articles, *external reference* to other documentation sets, etc. We will also learn to customize our websites, from theme to layout to metadata extraction. 71 | 72 | Read more 73 | --------- 74 | * [Walkthrough Part II: Adding API Documentation to the Website](walkthrough_create_a_docfx_project_2.md) 75 | 76 | * [Walkthrough Advanced: Customize Your Website](advanced_walkthrough.md) 77 | -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/walkthrough_generate_pdf.md: -------------------------------------------------------------------------------- 1 | Walkthrough Part III: Generate PDF Documentation 2 | ========================== 3 | 4 | After completing [Walkthrough Part II: Add API Documentation to the Website](walkthrough_create_a_docfx_project_2.md), we successfully create a website containing both Conceptual and API documentation. In this section, we will generate PDF files for these articles. 5 | 6 | After completing walkthrough part II, our `D:\docfx_walkthrough\docfx_project` folder is in the following structure(Download the artifacts [*HERE*](artifacts/walkthrough3.zip)): 7 | 8 | ``` 9 | |- articles 10 | |- images 11 | |- src 12 | |- src2 13 | |- index.md 14 | |- toc.yml 15 | |- docfx.json 16 | ``` 17 | 18 | Step0. Install prerequisite 19 | --------------------------- 20 | We leverage [wkhtmltopdf](https://wkhtmltopdf.org/) to generate PDF. [Download wkhtmltopdf](https://wkhtmltopdf.org/downloads.html) to some folder, e.g. `E:\Program Files\wkhtmltopdf\`, and save the executable folder path to **%PATH%** by: `set PATH=%PATH%;E:\Program Files\wkhtmltopdf\bin`. 21 | 22 | > [!NOTE] 23 | > Alternativeley you can install wkhtmltopdf via [chocolatey](https://chocolatey.org/) with `choco install wkhtmltopdf`. This will also add the executable folder to **%PATH%** during installation. 24 | 25 | Step1. Add a toc.yml specific for PDF 26 | --------------------------- 27 | Current design is that each TOC file generates a corresponding PDF file, TOC is also used as the table of contents page of the PDF, so we create a `toc.yml` file specific for PDF under a new folder `pdf`, using [TOC Include](http://dotnet.github.io/docfx/tutorial/intro_toc.html?q=toc%20inclu#link-to-another-toc-file) to include content from other TOC files. 28 | ```yml 29 | - name: Articles 30 | href: ../articles/toc.yml 31 | - name: Api Documentation 32 | href: ../api/toc.yml 33 | - name: Another Api Documentation 34 | href: ../api-vb/toc.yml 35 | ``` 36 | 37 | Step2. Add *pdf* section into docfx.json 38 | ---------------------------------------------------- 39 | Parameters are similar to `build` section, definitely it is using a different template (the builtin template is `pdf.default`), with another output destination. We also exclude TOC files as each TOC file generates a PDF file: 40 | ```json 41 | ... 42 | "pdf": { 43 | "content": [ 44 | { 45 | "files": [ 46 | "api/**.yml", 47 | "api-vb/**.yml" 48 | ], 49 | "exclude": [ 50 | "**/toc.yml", 51 | "**/toc.md" 52 | ] 53 | }, 54 | { 55 | "files": [ 56 | "articles/**.md", 57 | "articles/**/toc.yml", 58 | "toc.yml", 59 | "*.md", 60 | "pdf/*" 61 | ], 62 | "exclude": [ 63 | "**/bin/**", 64 | "**/obj/**", 65 | "_site_pdf/**", 66 | "**/toc.yml", 67 | "**/toc.md" 68 | ] 69 | }, 70 | { 71 | "files": "pdf/toc.yml" 72 | } 73 | ], 74 | "resource": [ 75 | { 76 | "files": [ 77 | "images/**" 78 | ], 79 | "exclude": [ 80 | "**/bin/**", 81 | "**/obj/**", 82 | "_site_pdf/**" 83 | ] 84 | } 85 | ], 86 | "overwrite": [ 87 | { 88 | "files": [ 89 | "apidoc/**.md" 90 | ], 91 | "exclude": [ 92 | "**/bin/**", 93 | "**/obj/**", 94 | "_site_pdf/**" 95 | ] 96 | } 97 | ], 98 | "wkhtmltopdf": { 99 | "additionalArguments": "--enable-local-file-access" 100 | }, 101 | "dest": "_site_pdf" 102 | } 103 | ``` 104 | 105 | Now, let's run `docfx`, and you can find pdf file walkthrough3_pdf.pdf generated under `_site_pdf` folder: 106 | ![PDF Preview](images/walkthrough3.png) 107 | 108 | *Optional* Step3. Enable plugins 109 | ---------------------------------------------------- 110 | If you wish to use plugins with pdf as well, you need to add a `template` node to the pdf section. It needs to start with the `pdf.template` followed by the path to the plugins you want to use: 111 | 112 | ```json 113 | "template": [ 114 | "pdf.default", 115 | "pluginPackages/rest.tagpage.2.31.0/content" 116 | ], 117 | ``` 118 | 119 | Conclusion 120 | --------- 121 | In this walkthrough, we build a PDF file according to the TOC file under `pdf` folder. Note that TOC plays an important role in PDF generation, it not only determines the files included in the PDF, but also the table of contents page for this PDF file. One TOC file generates one PDF file, so don't forget to exclude TOC files you don't want from docfx.json. 122 | 123 | Read more 124 | --------- 125 | * [Walkthrough Part I: Generate a Simple Documentation Website](walkthrough_create_a_docfx_project.md) 126 | 127 | * [Walkthrough Part II: Adding API Documentation to the Website](walkthrough_create_a_docfx_project_2.md) 128 | 129 | * [Walkthrough Advanced: Customize Your Website](advanced_walkthrough.md) 130 | -------------------------------------------------------------------------------- /samples/tutorial/walkthrough/walkthrough_overview.md: -------------------------------------------------------------------------------- 1 | Walkthrough Overview 2 | =================================== 3 | 4 | By completing these walkthroughs, you'll create a static website, containing both **Conceptual Documentation** which comes from `.md` files and **API Documentation** which comes from .NET source code. You'll also be able to customize your website with your own styles and templates! 5 | 6 | List of Articles 7 | --------- 8 | 1. [Walkthrough Part I: Generate a Simple Documentation Website](walkthrough_create_a_docfx_project.md) 9 | 10 | 2. [Walkthrough Part II: Adding API Documentation to the Website](walkthrough_create_a_docfx_project_2.md) 11 | 12 | 3. [Walkthrough Advanced: Customize Your Website](advanced_walkthrough.md) 13 | -------------------------------------------------------------------------------- /src/docfx.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | :root { 5 | --navbar-bg-color: #164268; 6 | } 7 | 8 | $primary: #2d74b2 !default; 9 | $link-decoration: none !default; 10 | $link-hover-decoration: underline !default; 11 | $container-max-widths: ( 12 | xxl: 1768px 13 | ) !default; 14 | 15 | @import '../node_modules/bootstrap/scss/bootstrap.scss'; 16 | @import '../node_modules/highlight.js/styles/stackoverflow-light.css'; 17 | @import './styles/layout.scss'; 18 | @import './styles/article.scss'; 19 | @import './styles/markdown.scss'; 20 | @import './styles/home.scss'; 21 | @import './styles/nav.scss'; 22 | @import './styles/toc.scss'; 23 | @import './styles/dotnet.scss'; 24 | 25 | .container.page-type-home { 26 | padding: 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/docfx.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import 'bootstrap' 5 | import { enableAnchor } from './scripts/anchor' 6 | import { highlight } from './scripts/highlight' 7 | import { renderAlerts, renderLinks, renderTables, renderTabs } from './scripts/markdown' 8 | import { renderAside, renderNavbar } from './scripts/nav' 9 | import { enableSwitchTheme } from './scripts/theme' 10 | import { renderToc } from './scripts/toc' 11 | 12 | document.addEventListener('DOMContentLoaded', onContentLoad) 13 | 14 | function onContentLoad() { 15 | enableAnchor() 16 | enableSwitchTheme() 17 | highlight() 18 | 19 | renderTables() 20 | renderAlerts() 21 | renderLinks() 22 | 23 | renderNavbar() 24 | renderToc() 25 | 26 | renderAside() 27 | renderTabs() 28 | } -------------------------------------------------------------------------------- /src/scripts/anchor.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import AnchorJs from 'anchor-js'; 5 | 6 | export function enableAnchor() { 7 | const anchors = new AnchorJs() 8 | anchors.options = { 9 | placement: 'right', 10 | visible: 'hover' 11 | }; 12 | anchors.add('article h2,h3'); 13 | } 14 | -------------------------------------------------------------------------------- /src/scripts/highlight.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import hljs from 'highlight.js'; 5 | 6 | export function highlight() { 7 | document.querySelectorAll('pre code').forEach(block => { 8 | hljs.highlightElement(block as HTMLElement) 9 | }) 10 | 11 | document.querySelectorAll('pre code[highlight-lines]').forEach(block => { 12 | if (block.innerHTML === "") return 13 | var lines = block.innerHTML.split('\n') 14 | 15 | var queryString = block.getAttribute('highlight-lines') 16 | if (!queryString) return 17 | 18 | var ranges = queryString.split(',') 19 | for (var j = 0, range; range = ranges[j++];) { 20 | var found = range.match(/^(\d+)\-(\d+)?$/) 21 | if (found) { 22 | // consider region as `{startlinenumber}-{endlinenumber}`, in which {endlinenumber} is optional 23 | var start = +found[1] 24 | var end = +found[2] 25 | if (isNaN(end) || end > lines.length) { 26 | end = lines.length 27 | } 28 | } else { 29 | // consider region as a sigine line number 30 | if (isNaN(range)) continue 31 | var start = +range 32 | var end = start 33 | } 34 | if (start <= 0 || end <= 0 || start > end || start > lines.length) { 35 | // skip current region if invalid 36 | continue; 37 | } 38 | lines[start - 1] = '' + lines[start - 1] 39 | lines[end - 1] = lines[end - 1] + '' 40 | } 41 | 42 | block.innerHTML = lines.join('\n') 43 | }) 44 | } -------------------------------------------------------------------------------- /src/scripts/nav.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import React from 'jsx-dom' 5 | import { getAbsolutePath, getDirectory, isRelativePath, isVisible, meta } from './utility'; 6 | 7 | export interface NavItem { 8 | name: string 9 | href?: string 10 | } 11 | 12 | export async function renderNavbar() { 13 | const navbarElement = document.getElementById('navbar') 14 | const navbarPath = meta('menu_path')?.replace(/\\/g, '/') 15 | if (!navbarPath || !navbarElement) { 16 | return 17 | } 18 | 19 | const data = await (await fetch(navbarPath)).json() 20 | 21 | let activeItem: NavItem 22 | let maxItemPathLength = 1 23 | const navrel = getDirectory(navbarPath) 24 | const windowPath = getAbsolutePath(window.location.pathname).toLowerCase() 25 | 26 | const items = data.items.map(item => { 27 | const href = isRelativePath(item.href) ? navrel + '/' + item.href : item.href; 28 | const result = { href: href, name: item.name } 29 | if (href) { 30 | const itemPath = getAbsolutePath(href).toLowerCase(); 31 | const itemLength = commonPathPrefixLength(windowPath, itemPath); 32 | if (itemLength > maxItemPathLength) { 33 | maxItemPathLength = itemLength 34 | activeItem = result 35 | } 36 | } 37 | return result 38 | }) 39 | 40 | navbarElement.appendChild( 41 | ) 48 | 49 | function commonPathPrefixLength(path1, path2) { 50 | var items1 = path1.split('/'); 51 | var items2 = path2.split('/'); 52 | var length = items1.length > items2.length ? items2.length : items1.length; 53 | for (var i = 0; i < length; i++) { 54 | if (items1[i] !== items2[i]) { 55 | return i; 56 | } 57 | } 58 | return length; 59 | } 60 | } 61 | 62 | export function renderAside() { 63 | const inThisArticle = document.getElementById('in-this-article') 64 | const sections = Array.from(document.querySelectorAll("article h2")) 65 | .filter(e => isVisible(e)) 66 | .map(item => ({ name: item.textContent, href: '#' + item.id })) 67 | 68 | if (!inThisArticle || sections.length <= 0) { 69 | return 70 | } 71 | 72 | document.body.setAttribute('data-bs-spy', 'scroll'); 73 | document.body.setAttribute('data-bs-target', '#in-this-article'); 74 | 75 | inThisArticle.appendChild(
      In this Article
      ) 76 | inThisArticle.appendChild( 77 | 84 | ) 85 | } 86 | -------------------------------------------------------------------------------- /src/scripts/theme.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import cookie from 'js-cookie' 5 | 6 | let theme = cookie.get('docfx.theme') || 'light'; 7 | 8 | export function enableSwitchTheme() { 9 | let getThemeClass = theme => `theme-${theme}`; 10 | document.body.classList.add(getThemeClass(theme)); 11 | 12 | let button = document.getElementById('switch-theme'); 13 | if (!button) { 14 | return; 15 | } 16 | 17 | button.addEventListener('click', () => { 18 | document.body.classList.remove(getThemeClass(theme)); 19 | 20 | let targetTheme = theme === 'light' ? 'dark' : 'light'; 21 | 22 | cookie.set('docfx.theme', targetTheme); 23 | document.body.classList.add(getThemeClass(targetTheme)); 24 | theme = targetTheme; 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /src/scripts/toc.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | import React, { createRef } from 'jsx-dom' 5 | import { NavItem } from './nav'; 6 | import { getAbsolutePath, getDirectory, isRelativePath, meta } from './utility' 7 | 8 | interface TocNode extends NavItem { 9 | items?: TocNode[] 10 | } 11 | 12 | export async function renderToc() { 13 | const tocPath = meta('toc_rel')?.replace(/\\/g, '/') 14 | const tocElement = document.getElementById('toc') 15 | if (!tocPath || !tocElement) { 16 | return 17 | } 18 | 19 | const toc = await (await fetch(tocPath)).json() 20 | const tocrel = getDirectory(tocPath) 21 | const currentHref = getAbsolutePath(window.location.pathname) 22 | const activeNodes: TocNode[] = [] 23 | let activeElement: React.RefObject 24 | 25 | toc.items ||= [] 26 | toc.items.map(expandNodes) 27 | tocElement.appendChild(
        {buildTocNodes(toc.items)}
      ) 28 | registerTocEvents() 29 | 30 | if (activeElement) { 31 | activeElement.current.scrollIntoView({ block: 'nearest' }) 32 | } 33 | 34 | function expandNodes(node: TocNode): boolean { 35 | let isActive = false 36 | if (node.href) { 37 | node.href = isRelativePath(node.href) ? tocrel + '/' + node.href : node.href 38 | if (getAbsolutePath(node.href) == currentHref) { 39 | isActive = true 40 | } 41 | } 42 | 43 | if (node.items) { 44 | for (const item of node.items) { 45 | if (expandNodes(item)) { 46 | isActive = true 47 | } 48 | } 49 | } 50 | 51 | if (isActive) { 52 | activeNodes.unshift(node) 53 | return true 54 | } 55 | return false 56 | } 57 | 58 | function buildTocNodes(nodes: TocNode[]) { 59 | return nodes.map(node => { 60 | const li = createRef() 61 | const { href, name, items } = node 62 | const isLeaf = !items || items.length <= 0 63 | const active = activeNodes.includes(node) 64 | const activeClass= active ? 'active' : null 65 | 66 | if (active) { 67 | activeElement = li 68 | } 69 | 70 | return ( 71 |
    1. 72 | {isLeaf ? null : toggleTocNode(li.current)}>} 73 | {href 74 | ? {name} 75 | : toggleTocNode(li.current)}>{name}} 76 | {isLeaf ? null :
        {buildTocNodes(items)}
      } 77 |
    2. ) 78 | }) 79 | } 80 | 81 | function toggleTocNode(li: HTMLLIElement) { 82 | if (li.classList.contains('active') || li.classList.contains('filtered')) { 83 | li.classList.remove('active') 84 | li.classList.remove('filtered') 85 | } else { 86 | li.classList.add('active') 87 | } 88 | } 89 | 90 | function registerTocEvents() { 91 | const tocFilter = document.getElementById('toc-filter') as HTMLInputElement 92 | if (!tocFilter) { 93 | return 94 | } 95 | 96 | tocFilter.addEventListener('input', () => onTocFilterTextChange()) 97 | 98 | // Set toc filter from local session storage on page load 99 | const filterString = sessionStorage?.filterString 100 | if (filterString) { 101 | tocFilter.value = filterString 102 | onTocFilterTextChange() 103 | } 104 | 105 | function onTocFilterTextChange() { 106 | const filter = tocFilter.value?.toLocaleLowerCase() || '' 107 | if (sessionStorage) { 108 | sessionStorage.filterString = filter 109 | } 110 | 111 | const toc = document.getElementById('toc') 112 | const anchors = toc.querySelectorAll('a') 113 | 114 | if (filter == '') { 115 | anchors.forEach(a => a.parentElement.classList.remove('filtered', 'hide')) 116 | return 117 | } 118 | 119 | const filteredLI = new Set() 120 | anchors.forEach(a => { 121 | const text = a.innerText 122 | if (text && text.toLowerCase().indexOf(filter) >= 0) { 123 | let e: HTMLElement = a 124 | while (e && e !== toc) { 125 | e = e.parentElement 126 | filteredLI.add(e) 127 | } 128 | } 129 | }) 130 | 131 | anchors.forEach(a => { 132 | const li = a.parentElement 133 | if (filteredLI.has(li)) { 134 | li.classList.remove('hide') 135 | li.classList.add('filtered') 136 | } else { 137 | li.classList.add('hide') 138 | } 139 | }) 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/scripts/utility.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | export function meta(name: string): string { 5 | return (document.querySelector(`meta[name="${name}"]`) as HTMLMetaElement)?.content 6 | } 7 | 8 | export function isVisible(element: Element): boolean { 9 | return (element as HTMLElement).offsetParent != null 10 | } 11 | 12 | export function getAbsolutePath(href: string): string { 13 | if (!href) { 14 | return 15 | } 16 | const a = document.createElement('a') 17 | a.href = href 18 | return a.host + a.pathname; 19 | } 20 | 21 | export function isRelativePath(href: string): boolean { 22 | if (href === undefined || href === '' || href[0] === '/') { 23 | return false; 24 | } 25 | return !isAbsolutePath(href); 26 | } 27 | 28 | export function isAbsolutePath(href: string): boolean { 29 | return (/^(?:[a-z]+:)?\/\//i).test(href); 30 | } 31 | 32 | export function getDirectory(href: string): string { 33 | if (!href) return '.'; 34 | var index = href.lastIndexOf('/'); 35 | return index < 0 ? '.' : href.slice(0, index); 36 | } 37 | -------------------------------------------------------------------------------- /src/styles/article.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | /* metabar */ 5 | .metabar { 6 | color: #999; 7 | font-size: 14px; 8 | display: flex; 9 | flex-wrap: wrap; 10 | list-style: none; 11 | padding: 0; 12 | align-items: center; 13 | } 14 | 15 | .metabar > li { 16 | margin: 0 6px; 17 | } 18 | 19 | .contributors { 20 | list-style: none; 21 | display: flex; 22 | flex-wrap: wrap; 23 | padding: 0; 24 | 25 | & > li { 26 | margin: 0 4px; 27 | } 28 | 29 | img { 30 | border-radius: 50%; 31 | } 32 | } 33 | 34 | /* Edit this page */ 35 | .edit-this-page { 36 | display: flex; 37 | align-items: center; 38 | gap: .5em; 39 | font-size: 14px; 40 | margin-top: 4em; 41 | 42 | @media print { 43 | display: none; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/styles/dotnet.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | main.page-type-reference { 5 | .is-hidden { 6 | display: none; 7 | } 8 | 9 | details { 10 | display: none; 11 | } 12 | 13 | h2.appliesTo, 14 | h3.appliesTo { 15 | display: none; 16 | } 17 | 18 | dl.attributeList { 19 | display: flex; 20 | margin: .25em 0; 21 | font-weight: 400; 22 | 23 | dt { 24 | font-weight: 400; 25 | } 26 | 27 | dd { 28 | margin-left: 8px; 29 | } 30 | } 31 | 32 | .stack { 33 | margin-top: 24px; 34 | } 35 | 36 | .metadata { 37 | margin: 1em 0; 38 | color: rgb(120, 120, 120); 39 | dl.attributeList { 40 | font-size: 14px; 41 | } 42 | } 43 | 44 | .propertyInfoTitle { 45 | font-size: 24px; 46 | font-weight: 400; 47 | } 48 | 49 | .cdlHolder .cdl, 50 | .pdlHolder .pdl { 51 | display: inline-block; 52 | } 53 | 54 | .cdlHolder .cdl:after { 55 | content: ', '; 56 | color: rgb(80, 80, 80); 57 | } 58 | 59 | .pdlHolder .pdl:after { 60 | position: relative; 61 | top: .2em; 62 | left: .2em; 63 | display: inline-block; 64 | width: 1em; 65 | margin: 0 .25em; 66 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-255 57 448 448'%3E%3Cpath d='M-253.625 281v-32H131.75L-16.938 100.313 5.687 77.688 193 265 5.687 452.313l-22.625-22.625L131.75 281h-385.375z'/%3E%3C/svg%3E"); 67 | } 68 | 69 | .cdlHolder .cdl:last-child:after, 70 | .pdlHolder .pdl:last-child:after { 71 | content: ''; 72 | } 73 | 74 | .memberInfo { 75 | margin-left: 24px; 76 | } 77 | 78 | .parameterList { 79 | display: flex; 80 | margin: 0; 81 | 82 | dt { 83 | background-color: rgb(242, 242, 242); 84 | padding: 0 6px 2px 6px; 85 | margin-right: 1em; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/styles/home.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | .layout-home { 5 | padding: 0; 6 | 7 | .hero { 8 | background-color: rgb(248, 248, 248); 9 | 10 | .hero-content { 11 | display: flex; 12 | flex-direction: column; 13 | align-items: center; 14 | padding: 5em 0; 15 | gap: 1em; 16 | 17 | h1 { 18 | font-size: calc(1.525rem + 3.3vw); 19 | font-weight: 600; 20 | } 21 | 22 | .lead { 23 | font-weight: 400; 24 | font-size: calc(1.275rem + .3vw); 25 | } 26 | 27 | .actions { 28 | display: flex; 29 | gap: 1em; 30 | 31 | .btn { 32 | font-weight: 600; 33 | @include button-size(.75em, 1.5em, 1.25em, .3em); 34 | } 35 | } 36 | } 37 | } 38 | 39 | .quickstart { 40 | &:nth-child(odd) { 41 | background-color: #f8f8f8; 42 | } 43 | section { 44 | padding: 4em 0; 45 | margin: 0; 46 | } 47 | } 48 | 49 | .highlights { 50 | display: flex; 51 | gap: 1em 3em; 52 | margin: 4em 0; 53 | 54 | @include media-breakpoint-down(md) { 55 | flex-direction: column; 56 | } 57 | 58 | section { 59 | flex-grow: 1; 60 | flex-basis: 0; 61 | h2 { 62 | font-size: 20px; 63 | } 64 | 65 | .content { 66 | font-size: 16px; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/styles/layout.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | body { 5 | min-height: 100vh; 6 | display: flex; 7 | flex-direction: column; 8 | align-items: stretch; 9 | } 10 | 11 | .sticky-top { 12 | position: sticky; 13 | top: 0; 14 | } 15 | 16 | img { 17 | max-width: 100%; 18 | } 19 | 20 | $aside-break: 1086px; 21 | 22 | main.layout-conceptual { 23 | display: grid; 24 | margin-top: 1em; 25 | gap: .5em 2em; 26 | grid-template-columns: minmax(16em, 20%) minmax(0, 1fr) minmax(12em, 15%); 27 | grid-template-rows: auto auto; 28 | grid-template-areas: 29 | 'toc article aside'; 30 | 31 | @media only screen and (max-width: $aside-break) { 32 | grid-template-areas: 33 | 'toc article article'; 34 | } 35 | 36 | @media only screen and (max-width: 768px) { 37 | grid-template-columns: 100%; 38 | grid-template-areas: 39 | 'toc' 40 | 'article' 41 | } 42 | 43 | @media print { 44 | grid-template-columns: 100%; 45 | grid-template-areas: 46 | 'article' 47 | } 48 | } 49 | 50 | nav.layout-toc { 51 | grid-area: toc; 52 | 53 | .navbar-collapse { 54 | flex-direction: column; 55 | align-items: stretch; 56 | margin-top: 0; 57 | } 58 | 59 | @include media-breakpoint-down(md) { 60 | .navbar-collapse { 61 | margin-top: 1em; 62 | } 63 | } 64 | 65 | @media print { 66 | display: none; 67 | } 68 | } 69 | 70 | aside { 71 | grid-area: aside; 72 | 73 | @media only screen and (max-width: $aside-break) { 74 | display: none; 75 | } 76 | 77 | @media print { 78 | display: none; 79 | } 80 | } 81 | 82 | article { 83 | grid-area: article; 84 | margin-bottom: 2em; 85 | } 86 | 87 | footer { 88 | margin-top: auto; 89 | } -------------------------------------------------------------------------------- /src/styles/markdown.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | /* base */ 5 | :not(a):not(pre)>code { 6 | background-color: rgb(249, 242, 244); 7 | padding: .2em .4em; 8 | } 9 | 10 | code, 11 | pre { 12 | border-radius: $border-radius 13 | } 14 | 15 | /* Alerts */ 16 | .alert { 17 | border-radius: $border-radius; 18 | border-width: 0; 19 | 20 | h5 { 21 | font-size: 14px; 22 | font-weight: 600; 23 | text-transform: uppercase; 24 | margin-top: 0; 25 | } 26 | 27 | h5:before { 28 | position: relative; 29 | top: .2em; 30 | width: 1.25em; 31 | display: inline-block; 32 | padding-top: 4px; 33 | margin-right: .25em; 34 | } 35 | 36 | &.NOTE { 37 | background-color: rgb(239, 217, 253); 38 | h5:before { 39 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Cpath d='M208 448C93.313 448 0 354.688 0 240S93.313 32 208 32s208 93.313 208 208-93.312 208-208 208zm0-384c-97.047 0-176 78.953-176 176 0 97.031 78.953 176 176 176 97.031 0 176-78.969 176-176 0-97.047-78.969-176-176-176zm16 64h-32v160h32V128zm0 192h-32v32h32v-32z'/%3E%3C/svg%3E"); 40 | } 41 | } 42 | 43 | &.TIP { 44 | background-color: rgb(223, 246, 221); 45 | h5:before { 46 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2048 2048'%3E%3Cpath d='M960 0q97 0 187 25t168 71 143 110 110 142 71 169 25 187q0 145-55 269t-157 225q-83 82-127 183t-45 219v256q0 40-15 75t-41 61-61 41-75 15H832q-40 0-75-15t-61-41-41-61-15-75v-256q0-118-44-219t-128-183q-102-101-157-225t-55-269q0-97 25-187t71-168 110-143T604 96t169-71T960 0zm128 1920q26 0 45-19t19-45v-192H768v192q0 26 19 45t45 19h256zm67-384q13-129 66-234t143-196q83-84 127-183t45-219q0-119-45-224t-124-183-183-123-224-46q-119 0-224 45T553 297 430 480t-46 224q0 119 44 218t128 184q90 91 143 196t66 234h390z'/%3E%3C/svg%3E"); 47 | } 48 | } 49 | 50 | &.WARNING { 51 | background-color: rgb(255, 244, 206); 52 | h5:before { 53 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Cpath d='M413.031 448H2.953L208 36.094 413.031 448zm-358.39-32h306.703L208 107.906 54.641 416zM224 192h-32v128h32V192zm0 160h-32v32h32v-32z'/%3E%3C/svg%3E"); 54 | } 55 | } 56 | 57 | &.IMPORTANT { 58 | background-color: rgb(215, 234, 248); 59 | h5:before { 60 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Cpath d='M208 448C93.313 448 0 354.688 0 240S93.313 32 208 32s208 93.313 208 208-93.312 208-208 208zm0-384c-97.047 0-176 78.953-176 176 0 97.031 78.953 176 176 176 97.031 0 176-78.969 176-176 0-97.047-78.969-176-176-176zm16 64h-32v32h32v-32zm0 64h-32v160h32V192z'/%3E%3C/svg%3E"); 61 | } 62 | } 63 | 64 | &.CAUTION { 65 | background-color: rgb(253, 231, 233); 66 | h5:before { 67 | content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Cpath d='M208 32C93.313 32 0 125.313 0 240s93.313 208 208 208 208-93.313 208-208S322.688 32 208 32zm0 384c-97.047 0-176-78.969-176-176 0-97.047 78.953-176 176-176 97.031 0 176 78.953 176 176 0 97.031-78.969 176-176 176zm107.313-260.687L230.625 240l84.688 84.688-22.625 22.625L208 262.625l-84.688 84.688-22.625-22.625L185.375 240l-84.688-84.688 22.625-22.625L208 217.375l84.688-84.688 22.625 22.626z'/%3E%3C/svg%3E"); 68 | } 69 | } 70 | } 71 | 72 | /* For tabbed content */ 73 | .tabGroup { 74 | margin-top: 1rem; 75 | 76 | ul[role="tablist"] { 77 | margin: 0; 78 | padding: 0; 79 | list-style: none; 80 | 81 | & > li { 82 | list-style: none; 83 | display: inline-block; 84 | } 85 | } 86 | 87 | a[role="tab"] { 88 | color: #6e6e6e; 89 | box-sizing: border-box; 90 | display: inline-block; 91 | padding: 5px 7.5px; 92 | text-decoration: none; 93 | border-bottom: 3px solid #fff; 94 | } 95 | } 96 | 97 | .tabGroup a[role="tab"]:hover, 98 | .tabGroup a[role="tab"]:focus, 99 | .tabGroup a[role="tab"][aria-selected="true"] { 100 | border-bottom: 3px solid $primary; 101 | } 102 | .tabGroup a[role="tab"][aria-selected="true"] { 103 | color: #222; 104 | } 105 | .tabGroup a[role="tab"]:hover, .tabGroup a[role="tab"]:focus { 106 | color: $primary; 107 | } 108 | .tabGroup a[role="tab"]:focus { 109 | outline: 3px solid $primary; 110 | outline-offset: -3px; 111 | } 112 | @media (min-width: 768px) { 113 | .tabGroup a[role="tab"] { 114 | padding: 5px 15px; 115 | } 116 | } 117 | 118 | .tabGroup section[role="tabpanel"] { 119 | border: 1px solid #e0e0e0; 120 | padding: 15px; 121 | margin: 0; 122 | overflow: hidden; 123 | 124 | & > .codeHeader, 125 | & > pre { 126 | margin-left: -16px; 127 | margin-right: -16px; 128 | } 129 | & > :first-child { 130 | margin-top: 0; 131 | } 132 | & > pre:last-child { 133 | display: block; 134 | margin-bottom: -16px; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/styles/nav.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | header { 5 | .navbar { 6 | background-color: var(--navbar-bg-color); 7 | } 8 | 9 | @media print { 10 | display: none; 11 | } 12 | } 13 | 14 | .in-this-article{ 15 | font-size: 14px; 16 | padding-top: .5em; 17 | 18 | h5 { 19 | font-weight: bold; 20 | text-transform: uppercase; 21 | font-size: inherit; 22 | } 23 | .nav { 24 | display: block; 25 | padding-left: 0; 26 | 27 | a { 28 | padding: 2px 2px 2px 6px; 29 | border-left: 3px solid transparent; 30 | } 31 | a.active { 32 | border-left: 3px solid $primary; 33 | } 34 | a:hover { 35 | text-decoration: underline; 36 | } 37 | } 38 | } 39 | 40 | footer { 41 | background-color: #f8f8f8; 42 | padding: 2rem 0; 43 | 44 | .github-star-button { 45 | display: inline-block; 46 | position: relative; 47 | top: 5px; 48 | margin: 0 10px; 49 | } 50 | 51 | @media print { 52 | display: none; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/styles/toc.scss: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | /* TOC panel appearance */ 5 | .layout-toc { 6 | .navbar-toggler { 7 | font-size: inherit; 8 | cursor: pointer; 9 | 10 | &:before { 11 | content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") 12 | } 13 | } 14 | 15 | .navbar-collapse { 16 | margin-top: .5em; 17 | } 18 | 19 | input { 20 | font-size: 14px; 21 | } 22 | } 23 | 24 | /* TOC appearance */ 25 | .toc { 26 | font-size: 14px; 27 | 28 | a:not(.active):not(.filtered) { 29 | color: inherit 30 | } 31 | a:not([href]) { 32 | &, 33 | &:hover { 34 | cursor: pointer; 35 | text-decoration: none; 36 | } 37 | } 38 | ul { 39 | padding-left: 16px; 40 | list-style-type: none; 41 | } 42 | li { 43 | padding: .25em 0; 44 | } 45 | } 46 | 47 | /* TOC item toggle */ 48 | .toc { 49 | padding: .5em 0; 50 | 51 | li > ul { 52 | display: none; 53 | } 54 | li.filtered > ul, 55 | li.active > ul { 56 | display: block 57 | } 58 | 59 | .toggle::before { 60 | display: inline-block; 61 | margin: 0 0 0 -1.25em; 62 | cursor: pointer; 63 | width: 1.25em; 64 | content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e"); 65 | transition: transform 0.35s ease; 66 | transform-origin: .5em 50%; 67 | } 68 | 69 | li.active > .toggle:before, 70 | li.filtered > .toggle::before { 71 | transform: rotate(90deg); 72 | } 73 | 74 | .hide { 75 | display: none; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /template.yml: -------------------------------------------------------------------------------- 1 | name: Default Template 2 | description: The default docfx site template. 3 | assets: 4 | - dist/** 5 | -------------------------------------------------------------------------------- /tests/screenshots/expected/-1152-648-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-1152-648-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-1152-648-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-1152-648-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-1920-1080-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-1920-1080-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-1920-1080-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-1920-1080-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-375-812-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-375-812-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-375-812-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-375-812-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-768-600-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-768-600-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/-768-600-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/-768-600-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--1152-648-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--1152-648-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--1152-648-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--1152-648-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--1920-1080-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--1920-1080-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--1920-1080-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--1920-1080-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--375-812-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--375-812-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--375-812-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--375-812-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--768-600-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--768-600-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-getting-started--768-600-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-getting-started--768-600-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1152-648-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1152-648-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1152-648-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1152-648-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1920-1080-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1920-1080-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1920-1080-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--1920-1080-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--375-812-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--375-812-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--375-812-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--375-812-light.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--768-600-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--768-600-dark.png -------------------------------------------------------------------------------- /tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--768-600-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docascode/template/dc97fc1eb4cd42e85c861e8d2925f32f914e4c94/tests/screenshots/expected/tutorial-walkthrough-walkthrough_create_a_docfx_project_2--768-600-light.png --------------------------------------------------------------------------------