diff --git a/eng/common/docgeneration/Generate-DocIndex.ps1 b/eng/common/docgeneration/Generate-DocIndex.ps1
new file mode 100644
index 000000000000..84fd56271550
--- /dev/null
+++ b/eng/common/docgeneration/Generate-DocIndex.ps1
@@ -0,0 +1,196 @@
+# Generates an index page for cataloging different versions of the Docs
+[CmdletBinding()]
+Param (
+ $DocFx,
+ $RepoRoot,
+ $DocGenDir,
+ $DocOutDir = "${RepoRoot}/docfx_project",
+ $DocfxJsonPath = "${PSScriptRoot}\docfx.json",
+ $MainJsPath = "${PSScriptRoot}\templates\matthews\styles\main.js"
+)
+. "${PSScriptRoot}\..\scripts\common.ps1"
+$GetGithubIoDocIndexFn = "Get-${Language}-GithubIoDocIndex"
+
+# Given the metadata url under https://github.com/Azure/azure-sdk/tree/master/_data/releases/latest,
+# the function will return the csv metadata back as part of response.
+function Get-CSVMetadata ([string]$MetadataUri) {
+ $metadataResponse = Invoke-RestMethod -Uri $MetadataUri -method "GET" -MaximumRetryCount 3 -RetryIntervalSec 10 | ConvertFrom-Csv
+ return $metadataResponse
+}
+
+# Given the github io blob storage url and language regex,
+# the helper function will return a list of artifact names.
+function Get-BlobStorage-Artifacts($blobStorageUrl, $blobDirectoryRegex, $blobArtifactsReplacement) {
+ LogDebug "Reading artifact from storage blob ..."
+ $returnedArtifacts = @()
+ $pageToken = ""
+ Do {
+ $resp = ""
+ if (!$pageToken) {
+ # First page call.
+ $resp = Invoke-RestMethod -Method Get -Uri $blobStorageUrl
+ }
+ else {
+ # Next page call
+ $blobStorageUrlPageToken = $blobStorageUrl + "&marker=$pageToken"
+ $resp = Invoke-RestMethod -Method Get -Uri $blobStorageUrlPageToken
+ }
+ # Convert to xml documents.
+ $xmlDoc = [xml](removeBomFromString $resp)
+ foreach ($elem in $xmlDoc.EnumerationResults.Blobs.BlobPrefix) {
+ # What service return like "dotnet/Azure.AI.Anomalydetector/", needs to fetch out "Azure.AI.Anomalydetector"
+ $artifact = $elem.Name -replace $blobDirectoryRegex, $blobArtifactsReplacement
+ $returnedArtifacts += $artifact
+ }
+ # Fetch page token
+ $pageToken = $xmlDoc.EnumerationResults.NextMarker
+ } while ($pageToken)
+ return $returnedArtifacts
+ }
+
+# The sequence of Bom bytes differs by different encoding.
+# The helper function here is only to strip the utf-8 encoding system as it is used by blob storage list api.
+# Return the original string if not in BOM utf-8 sequence.
+function RemoveBomFromString([string]$bomAwareString) {
+ if ($bomAwareString.length -le 3) {
+ return $bomAwareString
+ }
+ $bomPatternByteArray = [byte[]] (0xef, 0xbb, 0xbf)
+ # The default encoding for powershell is ISO-8859-1, so converting bytes with the encoding.
+ $bomAwareBytes = [Text.Encoding]::GetEncoding(28591).GetBytes($bomAwareString.Substring(0, 3))
+ if (@(Compare-Object $bomPatternByteArray $bomAwareBytes -SyncWindow 0).Length -eq 0) {
+ return $bomAwareString.Substring(3)
+ }
+ return $bomAwareString
+}
+
+function Get-TocMapping {
+ Param (
+ [Parameter(Mandatory = $true)] [Object[]] $metadata,
+ [Parameter(Mandatory = $true)] [String[]] $artifacts
+ )
+ # Used for sorting the toc display order
+ $orderServiceMapping = @{}
+
+ foreach ($artifact in $artifacts) {
+ $packageInfo = $metadata | ? {$_.Package -eq $artifact}
+
+ if ($packageInfo -and $packageInfo[0].Hide -eq 'true') {
+ LogDebug "The artifact $artifact set 'Hide' to 'true'."
+ continue
+ }
+ $serviceName = ""
+ $displayName = ""
+ if (!$packageInfo) {
+ LogWarning "There is no artifact $artifact. Please check csv of Azure/azure-sdk/_data/release/latest repo if this is intended. "
+ # If no service name retrieved, print out warning message, and put it into Other page.
+ $serviceName = "Other"
+ }
+ elseif (!$packageInfo[0].ServiceName) {
+ LogWarning "There is no service name for artifact $artifact. Please check csv of Azure/azure-sdk/_data/release/latest repo if this is intended. "
+ # If no service name retrieved, print out warning message, and put it into Other page.
+ $serviceName = "Other"
+ $displayName = $packageInfo[0].DisplayName.Trim()
+ }
+ else {
+ if ($packageInfo.Length -gt 1) {
+ LogWarning "There are more than 1 packages fetched out for artifact $artifact. Please check csv of Azure/azure-sdk/_data/release/latest repo if this is intended. "
+ }
+ $serviceName = $packageInfo[0].ServiceName.Trim()
+ $displayName = $packageInfo[0].DisplayName.Trim()
+ }
+ $orderServiceMapping[$artifact] = @($serviceName, $displayName)
+ }
+ return $orderServiceMapping
+}
+
+function GenerateDocfxTocContent([Hashtable]$tocContent, [String]$lang) {
+ LogDebug "Start generating the docfx toc and build docfx site..."
+
+ LogDebug "Initializing Default DocFx Site..."
+ & $($DocFx) init -q -o "${DocOutDir}"
+ # The line below is used for testing in local
+ #docfx init -q -o "${DocOutDir}"
+ LogDebug "Copying template and configuration..."
+ New-Item -Path "${DocOutDir}" -Name "templates" -ItemType "directory" -Force
+ Copy-Item "${DocGenDir}/templates/*" -Destination "${DocOutDir}/templates" -Force -Recurse
+ Copy-Item "${DocGenDir}/docfx.json" -Destination "${DocOutDir}/" -Force
+ $YmlPath = "${DocOutDir}/api"
+ New-Item -Path $YmlPath -Name "toc.yml" -Force
+ $visitedService = @{}
+ # Sort and display toc service name by alphabetical order, and then sort artifact by order.
+ foreach ($serviceMapping in ($tocContent.GetEnumerator() | Sort-Object Value[0], Key)) {
+ $artifact = $serviceMapping.Key
+ $serviceName = $serviceMapping.Value[0]
+ $displayName = $serviceMapping.Value[1]
+
+ $fileName = ($serviceName -replace '\s', '').ToLower().Trim()
+ if ($visitedService.ContainsKey($serviceName)) {
+ if ($displayName) {
+ Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact`n##### ($displayName)"
+ }
+ else {
+ Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact"
+ }
+ }
+ else {
+ Add-Content -Path "$($YmlPath)/toc.yml" -Value "- name: ${serviceName}`r`n href: ${fileName}.md"
+ New-Item -Path $YmlPath -Name "${fileName}.md" -Force
+ if ($displayName) {
+ Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact`n##### ($displayName)"
+ }
+ else {
+ Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact"
+ }
+ $visitedService[$serviceName] = $true
+ }
+ }
+
+ # Generate toc homepage.
+ LogDebug "Creating Site Title and Navigation..."
+ New-Item -Path "${DocOutDir}" -Name "toc.yml" -Force
+ Add-Content -Path "${DocOutDir}/toc.yml" -Value "- name: Azure SDK for $lang APIs`r`n href: api/`r`n homepage: api/index.md"
+
+ LogDebug "Copying root markdowns"
+ Copy-Item "$($RepoRoot)/README.md" -Destination "${DocOutDir}/api/index.md" -Force
+ Copy-Item "$($RepoRoot)/CONTRIBUTING.md" -Destination "${DocOutDir}/api/CONTRIBUTING.md" -Force
+
+ LogDebug "Building site..."
+ & $($DocFx) build "${DocOutDir}/docfx.json"
+ # The line below is used for testing in local
+ #docfx build "${DocOutDir}/docfx.json"
+ Copy-Item "${DocGenDir}/assets/logo.svg" -Destination "${DocOutDir}/_site/" -Force
+}
+
+function Mutate-Files {
+ Param (
+ [Parameter(Mandatory=$true)] [String]$appTitle,
+ [Parameter(Mandatory=$true)] [String]$lang,
+ [Parameter(Mandatory=$true)] [String]$indexhtmlloc,
+ [Parameter(Mandatory=$false)] [String]$packageRegex = "`"`"",
+ [Parameter(Mandatory=$false)] [String]$regexReplacement = ""
+ )
+ # Update docfx.json
+ $docfxContent = Get-Content -Path $DocfxJsonPath -Raw
+ $docfxContent = $docfxContent -replace "`"_appTitle`": `"`"", "`"_appTitle`": `"$appTitle`""
+ $docfxContent = $docfxContent -replace "`"_appFooter`": `"`"", "`"_appFooter`": `"$appTitle`""
+ Set-Content -Path $DocfxJsonPath -Value $docfxContent
+ # Update main.js var lang
+ $mainJsContent = Get-Content -Path $MainJsPath -Raw
+ $mainJsContent = $mainJsContent -replace "var SELECTED_LANGUAGE = ''", "var SELECTED_LANGUAGE = '$lang'"
+ # Update main.js var index html
+ $mainJsContent = $mainJsContent -replace "var INDEX_HTML = ''", "var INDEX_HTML = '$indexhtmlloc'"
+ # Update main.js package regex and replacement
+ $mainJsContent = $mainJsContent -replace "var PACKAGE_REGEX = ''", "var PACKAGE_REGEX = $packageRegex"
+ $mainJsContent = $mainJsContent -replace "var PACKAGE_REPLACEMENT = ''", "var PACKAGE_REPLACEMENT = `"$regexReplacement`""
+ Set-Content -Path $MainJsPath -Value $mainJsContent -NoNewline
+}
+
+if ($GetGithubIoDocIndexFn -and (Test-Path "function:$GetGithubIoDocIndexFn"))
+{
+ &$GetGithubIoDocIndexFn
+}
+else
+{
+ LogWarning "The function '$GetGithubIoDocIndexFn' was not found."
+}
diff --git a/eng/common/docgeneration/assets/logo.svg b/eng/common/docgeneration/assets/logo.svg
new file mode 100644
index 000000000000..5da99f404886
--- /dev/null
+++ b/eng/common/docgeneration/assets/logo.svg
@@ -0,0 +1,76 @@
+
+
+
+
diff --git a/eng/common/docgeneration/docfx.json b/eng/common/docgeneration/docfx.json
new file mode 100644
index 000000000000..6b113dafd3c0
--- /dev/null
+++ b/eng/common/docgeneration/docfx.json
@@ -0,0 +1,78 @@
+{
+ "metadata": [
+ {
+ "src": [
+ {
+ "files": [
+ "src/**.csproj"
+ ]
+ }
+ ],
+ "dest": "api",
+ "disableGitFeatures": false,
+ "disableDefaultFilter": false
+ }
+ ],
+ "build": {
+ "content": [
+ {
+ "files": [
+ "api/**.yml",
+ "api/**.md",
+ "api/index.md"
+ ]
+ },
+ {
+ "files": [
+ "toc.yml",
+ "*.md"
+ ]
+ }
+ ],
+ "resource": [
+ {
+ "files": [
+ "images/**"
+ ]
+ }
+ ],
+ "overwrite": [
+ {
+ "files": [
+ "apidoc/**.md"
+ ],
+ "exclude": [
+ "obj/**",
+ "_site/**"
+ ]
+ }
+ ],
+ "dest": "_site",
+ "globalMetadataFiles": [],
+ "fileMetadataFiles": [],
+ "template": [
+ "default",
+ "templates/matthews"
+ ],
+ "postProcessors": [],
+ "markdownEngineName": "markdig",
+ "noLangKeyword": false,
+ "keepFileLink": false,
+ "cleanupCacheHistory": false,
+ "disableGitFeatures": false,
+ "globalMetadata": {
+ "_appTitle": "",
+ "_appFooter": "",
+ "_enableSearch": false,
+ "_enableNewTab": true,
+ "_appFaviconPath": "https://c.s-microsoft.com/favicon.ico?v2",
+ "_disableContribution": true
+ }
+ }
+}
+
+
+
+
+
+
diff --git a/eng/common/docgeneration/templates/matthews/partials/affix.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/affix.tmpl.partial
new file mode 100644
index 000000000000..43a33d0120a3
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/partials/affix.tmpl.partial
@@ -0,0 +1,17 @@
+{{^_disableContribution}}
+
+ {{#docurl}}
+
+ {{/docurl}}
+ {{#sourceurl}}
+
+ {{/sourceurl}}
+
+{{/_disableContribution}}
+
+
diff --git a/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial
new file mode 100644
index 000000000000..49a27d827322
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/partials/class.header.tmpl.partial
@@ -0,0 +1,100 @@
+{{>partials/title}}
+{{{summary}}}
+{{{conceptual}}}
+
+{{#inClass}}
+
+
{{__global.inheritance}}
+ {{#inheritance}}
+
{{{specName.0.value}}}
+ {{/inheritance}}
+
{{name.0.value}}
+
+{{/inClass}}
+
+{{#derivedClasses}}
+ {{{specName.0.value}}}
+{{/derivedClasses}}
+
+{{#inheritedMembers.0}}
+
+
{{__global.inheritedMembers}}
+{{/inheritedMembers.0}}
+{{#inheritedMembers}}
+
+ {{#definition}}
+
+ {{/definition}}
+ {{^definition}}
+
+ {{/definition}}
+
+{{/inheritedMembers}}
+{{#inheritedMembers.0}}
+
+{{/inheritedMembers.0}}
+
+{{__global.namespace}}: {{namespace}}
+{{__global.assembly}}: {{assemblies.0}}.dll
+
+{{__global.syntax}}
+
+
{{syntax.content.0.value}}
+
+
+{{#syntax.parameters.0}}
+{{__global.parameters}}
+
+{{/syntax.parameters.0}}
+{{#syntax.parameters}}
+
+
+ {{{type.specName.0.value}}}
+ {{{id}}}
+ {{{description}}}
+ |
+
+{{/syntax.parameters}}
+{{#syntax.parameters.0}}
+
+{{/syntax.parameters.0}}
+
+{{#syntax.return}}
+{{__global.returns}}
+
+
+
+ {{{type.specName.0.value}}}
+ {{{description}}}
+ |
+
+
+{{/syntax.return}}
+
+{{#syntax.typeParameters.0}}
+{{__global.typeParameters}}
+
+{{/syntax.typeParameters.0}}
+{{#syntax.typeParameters}}
+
+
+ {{{id}}}
+ {{{description}}}
+ |
+
+{{/syntax.typeParameters}}
+{{#syntax.typeParameters.0}}
+
+{{/syntax.typeParameters.0}}
+
+{{#remarks}}
+
+
+{{/remarks}}
+
+{{#example.0}}
+{{__global.examples}}
+{{/example.0}}
+{{#example}}
+{{{.}}}
+{{/example}}
diff --git a/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial
new file mode 100644
index 000000000000..5f00b822cc76
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/partials/class.tmpl.partial
@@ -0,0 +1,210 @@
+{{>partials/class.header}}
+{{#children}}
+{{>partials/classSubtitle}}
+{{#children}}
+
+{{^_disableContribution}}
+{{#docurl}}
+
+
+
+
+{{/docurl}}
+{{#sourceurl}}
+
+
+
+{{/sourceurl}}
+{{/_disableContribution}}
+
+{{#overload}}
+
+{{/overload}}
+
+
+
+
+
{{{summary}}}
+
{{{conceptual}}}
+
{{__global.declaration}}
+
+{{#syntax}}
+
+
{{syntax.content.0.value}}
+
+
+{{#parameters.0}}
+
{{__global.parameters}}
+
+{{/parameters.0}}
+{{#parameters}}
+
+
+ {{{type.specName.0.value}}}
+ {{{id}}}
+ {{{description}}}
+ |
+
+{{/parameters}}
+{{#parameters.0}}
+
+{{/parameters.0}}
+
+{{#return}}
+
{{__global.returns}}
+
+
+
+ {{{type.specName.0.value}}}
+ {{{description}}}
+ |
+
+
+{{/return}}
+
+{{#typeParameters.0}}
+
{{__global.typeParameters}}
+
+{{/typeParameters.0}}
+{{#typeParameters}}
+
+
+ {{{id}}}
+ {{{description}}}
+ |
+
+{{/typeParameters}}
+{{#typeParameters.0}}
+
+{{/typeParameters.0}}
+
+{{#fieldValue}}
+
{{__global.fieldValue}}
+
+
+
+ {{{type.specName.0.value}}}
+ {{{description}}}
+ |
+
+
+{{/fieldValue}}
+
+{{#propertyValue}}
+
{{__global.propertyValue}}
+
+
+
+ {{{type.specName.0.value}}}
+ {{{description}}}
+ |
+
+
+{{/propertyValue}}
+
+{{#eventType}}
+
{{__global.eventType}}
+
+
+
+ {{{type.specName.0.value}}}
+ {{{description}}}
+ |
+
+
+{{/eventType}}
+{{/syntax}}
+
+{{#overridden}}
+
{{__global.overrides}}
+
+{{/overridden}}
+
+{{#implements.0}}
+
{{__global.implements}}
+{{/implements.0}}
+{{#implements}}
+ {{#definition}}
+
+ {{/definition}}
+ {{^definition}}
+
+ {{/definition}}
+{{/implements}}
+
+{{#remarks}}
+
+
+{{/remarks}}
+
+{{#example.0}}
+
{{__global.examples}}
+{{/example.0}}
+{{#example}}
+{{{.}}}
+{{/example}}
+
+{{#exceptions.0}}
+
{{__global.exceptions}}
+
+{{/exceptions.0}}
+{{#exceptions}}
+
+
+ {{{type.specName.0.value}}}
+ {{{description}}}
+ |
+
+{{/exceptions}}
+{{#exceptions.0}}
+
+{{/exceptions.0}}
+
+{{#seealso.0}}
+
{{__global.seealso}}
+
+{{/seealso.0}}
+{{#seealso}}
+ {{#isCref}}
+
{{{type.specName.0.value}}}
+ {{/isCref}}
+ {{^isCref}}
+
{{{url}}}
+ {{/isCref}}
+{{/seealso}}
+{{#seealso.0}}
+
+{{/seealso.0}}
+
+{{/children}}
+{{/children}}
+
+{{#extensionMethods.0}}
+{{__global.extensionMethods}}
+{{/extensionMethods.0}}
+{{#extensionMethods}}
+
+ {{#definition}}
+
+ {{/definition}}
+ {{^definition}}
+
+ {{/definition}}
+
+{{/extensionMethods}}
+
+{{#seealso.0}}
+{{__global.seealso}}
+
+{{/seealso.0}}
+{{#seealso}}
+ {{#isCref}}
+
{{{type.specName.0.value}}}
+ {{/isCref}}
+ {{^isCref}}
+
{{{url}}}
+ {{/isCref}}
+{{/seealso}}
+{{#seealso.0}}
+
+{{/seealso.0}}
diff --git a/eng/common/docgeneration/templates/matthews/partials/enum.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/enum.tmpl.partial
new file mode 100644
index 000000000000..91e7ede1ac83
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/partials/enum.tmpl.partial
@@ -0,0 +1,24 @@
+{{>partials/class.header}}
+{{#children}}
+ {{#children}}
+
+
+
+ {{/children}}
+{{/children}}
+
+{{#extensionMethods.0}}
+{{__global.extensionMethods}}
+{{/extensionMethods.0}}
+{{#extensionMethods}}
+
+ {{#definition}}
+
+ {{/definition}}
+ {{^definition}}
+
+ {{/definition}}
+
+{{/extensionMethods}}
diff --git a/eng/common/docgeneration/templates/matthews/partials/namespace.tmpl.partial b/eng/common/docgeneration/templates/matthews/partials/namespace.tmpl.partial
new file mode 100644
index 000000000000..f607a3dc61bd
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/partials/namespace.tmpl.partial
@@ -0,0 +1,17 @@
+{{>partials/title}}
+{{{summary}}}
+{{{conceptual}}}
+
+{{#children}}
+ {{>partials/namespaceSubtitle}}
+
+ {{#children}}
+
+
+
+ {{{summary}}}
+ |
+
+ {{/children}}
+
+{{/children}}
diff --git a/eng/common/docgeneration/templates/matthews/styles/main.css b/eng/common/docgeneration/templates/matthews/styles/main.css
new file mode 100644
index 000000000000..21eb0c3567f3
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/styles/main.css
@@ -0,0 +1,302 @@
+@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css");
+
+/* Clickability fix for selector on sm devices */
+@media (min-width: 768px) and (max-width: 991px) {
+ article h1:first-of-type:before {
+ height: 0;
+ margin-top: 0;
+ }
+}
+
+#search {
+ border: none;
+}
+
+.fa-code {
+ font-size: 19px;
+}
+
+.sidetoc,
+body .toc,
+.sidefilter,
+.sidetoggle {
+ background-color: #f9fbe7;
+}
+
+.sidenav,
+.toc-toggle {
+ padding: 0;
+}
+
+.sidetoggle {
+ padding-bottom: 15px;
+}
+
+/* Remove center align from Navbar and Collapsible section */
+.collapse.in,
+.collapsing {
+ text-align: unset;
+}
+
+article h4 {
+ border-bottom: none;
+ line-height: normal;
+}
+
+@media (min-width: 768px) {
+ .sidetoc, .sidefilter {
+ margin-left: -15px;
+ }
+}
+
+@media (max-width: 767px) {
+ .navbar-collapse {
+ text-align: center !important;
+ }
+
+ .navbar-collapse li .active {
+ border-radius: 20px;
+ }
+}
+
+/* Collapsible Sections
+ ------------------------------------------------------- */
+.expander:after {
+ font-family: 'Glyphicons Halflings';
+ content: "\e260";
+ margin-left: 5px;
+ color: grey;
+ font-size: small;
+}
+
+.expander.collapsed:after {
+ content: "\e259";
+}
+
+/* Floating buttons
+ ------------------------------------------------------- */
+.fab {
+ width: 40px;
+ height: 40px;
+ text-align: center;
+ padding: 11px 0 0 0;
+ border: none;
+ outline: none;
+ color: #FFF;
+ border-radius: 100%;
+ box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
+ transition:.3s;
+}
+
+.fab:hover {
+ transform: scale(1.1);
+}
+
+.fab + .fab {
+ margin-right: 15px;
+}
+
+.contribution-panel {
+ z-index: 1000;
+ position: fixed;
+ right: 30px;
+ top: 70px;
+}
+
+/* Bootstrap docs like sidebar
+ ------------------------------------------------------- */
+.affix h5 {
+ display: none;
+}
+
+/* active & hover links */
+.affix ul > li > a:hover,
+.affix ul > li.active > a,
+.affix ul > li > a:focus {
+ color: #563d7c;
+ text-decoration: none;
+ background-color: transparent;
+ border-left-color: #563d7c;
+}
+
+/* all active links */
+.affix ul > li.active > a,
+.affix ul > li.active:hover > a,
+.affix ul > li.active:focus >a {
+ font-weight: 700;
+}
+
+/* nested active links */
+.affix ul ul > li.active > a,
+.affix ul ul > li.active:hover > a,
+.affix ul ul > li.active:focus > a {
+ font-weight: 500;
+}
+
+/* all links */
+.affix ul > li > a {
+ color: #999;
+ border-left: 2px solid transparent;
+ padding: 4px 20px;
+ font-size: 13px;
+ font-weight: 400;
+}
+
+/* nested links */
+.affix ul ul > li > a {
+ padding-top: 1px;
+ padding-bottom: 1px;
+ padding-left: 30px;
+ font-size: 12px;
+}
+
+/* hide inactive nested list */
+.affix ul ul {
+ display: none;
+}
+
+/* show active nested list */
+.affix ul > li.active > ul {
+ display: block;
+}
+
+.affix > ul > li > a:before {
+ content: '';
+}
+
+.affix ul ul > li > a:before {
+ content: '';
+}
+
+/* Style Buttons
+ ------------------------------------------------------- */
+.btn-warning {
+ background-color: #0071c5;
+}
+
+.btn-info {
+ background-color: #0071c5;
+}
+
+/* Navbar Hamburger
+ ------------------------------------------------------- */
+.icon-bar {
+ transition: 0.4s;
+}
+
+/* Rotate first bar */
+.change .icon-bar:nth-of-type(2) {
+ transform: rotate(-45deg) translate(-4px, 5px) ;
+}
+
+/* Fade out the second bar */
+.change .icon-bar:nth-of-type(3) {
+ opacity: 0;
+}
+
+/* Rotate last bar */
+.change .icon-bar:nth-of-type(4) {
+ transform: rotate(45deg) translate(-4px, -5px) ;
+}
+
+/* Custom Navbar
+ ------------------------------------------------------- */
+.navbar-inverse {
+ background-color: #0071c5;
+ opacity: 0.95;
+ border-color: #0071c5;
+}
+.navbar-inverse .navbar-brand {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+ color: #ecdbff;
+}
+.navbar-inverse .navbar-text {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-nav > li > a {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+ color: #ecdbff;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+ color: #ecdbff;
+ background-color: #0071c5;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+ color: #ecdbff;
+ background-color: #0071c5;
+}
+.navbar-inverse .navbar-toggle {
+ border-color: #0071c5;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+ background-color: #0071c5;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+ background-color: #ffffff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+ border: none;
+}
+.navbar-inverse .navbar-link {
+ color: #ffffff;
+}
+.navbar-inverse .navbar-link:hover {
+ color: #ecdbff;
+}
+.versionarrow {
+ margin-left: 0.8em;
+ margin-top: -1.5em;
+ margin-bottom: -1em;
+ padding: 1em;
+}
+
+.versionarrow::before {
+ position: absolute;
+ content: '';
+ width: 0;
+ height: 0;
+ border: .5em solid transparent;
+ border-left-color: gray;
+ transform-origin: 0 50%;
+ transition: transform .1s;
+ margin-top: 0.2em;
+}
+
+
+.versionarrow.disable {
+ text-decoration: line-through;
+}
+
+.versionarrow.down::before {
+ transform: rotate(90deg);
+ margin-top: 0em;
+ transition: transform .1s;
+}
+
+@media (max-width: 767px) {
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+ color: #ffffff;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #ecdbff;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #ecdbff;
+ background-color: #0071c5;
+ }
+}
\ No newline at end of file
diff --git a/eng/common/docgeneration/templates/matthews/styles/main.js b/eng/common/docgeneration/templates/matthews/styles/main.js
new file mode 100644
index 000000000000..73ccd77747d0
--- /dev/null
+++ b/eng/common/docgeneration/templates/matthews/styles/main.js
@@ -0,0 +1,224 @@
+// Use container fluid
+var containers = $(".container");
+containers.removeClass("container");
+containers.addClass("container-fluid");
+
+WINDOW_CONTENTS = window.location.href.split('/')
+var SELECTED_LANGUAGE = ''
+var INDEX_HTML = ''
+var PACKAGE_REGEX = ''
+var PACKAGE_REPLACEMENT = ''
+
+ATTR1 = '[System.ComponentModel.EditorBrowsable]\n<'
+
+// Navbar Hamburger
+$(function () {
+ $(".navbar-toggle").click(function () {
+ $(this).toggleClass("change");
+ })
+})
+
+// Select list to replace affix on small screens
+$(function () {
+ var navItems = $(".sideaffix .level1 > li");
+
+ if (navItems.length == 0) {
+ return;
+ }
+
+ var selector = $("");
+ selector.addClass("form-control visible-sm visible-xs");
+ var form = $("");
+ form.append(selector);
+ form.prependTo("article");
+
+ selector.change(function () {
+ window.location = $(this).find("option:selected").val();
+ })
+
+ function work(item, level) {
+ var link = item.children('a');
+
+ var text = link.text();
+
+ for (var i = 0; i < level; ++i) {
+ text = ' ' + text;
+ }
+
+ selector.append($('', {
+ 'value': link.attr('href'),
+ 'html': text
+ }));
+
+ var nested = item.children('ul');
+
+ if (nested.length > 0) {
+ nested.children('li').each(function () {
+ work($(this), level + 1);
+ });
+ }
+ }
+
+ navItems.each(function () {
+ work($(this), 0);
+ });
+})
+
+
+$(function () {
+ // Inject line breaks and spaces into the code sections
+ $(".lang-csharp").each(function () {
+ var text = $(this).html();
+ text = text.replace(/, /g, ", ");
+ text = text.replace(ATTR1, '<');
+ $(this).html(text);
+ });
+
+ // Add text to empty links
+ $("p > a").each(function () {
+ var link = $(this).attr('href')
+ if ($(this).text() === "") {
+ $(this).html(link)
+ }
+ });
+})
+
+function httpGetAsync(targetUrl, callback) {
+ var xmlHttp = new XMLHttpRequest();
+ xmlHttp.onreadystatechange = function () {
+ if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
+ callback(xmlHttp.responseText);
+ }
+ xmlHttp.open("GET", targetUrl, true); // true for asynchronous
+ xmlHttp.send(null);
+}
+
+function httpGetAsyncFallbackOnFail(targetUrl, successCallback, failureCallback) {
+ var xmlHttp = new XMLHttpRequest();
+ xmlHttp.onreadystatechange = function () {
+ if (xmlHttp.readyState == 4) {
+ if (xmlHttp.status == 200) {
+ successCallback(xmlHttp.responseText);
+ } else {
+ failureCallback(xmlHttp.status)
+ }
+ }
+ }
+ xmlHttp.open("GET", targetUrl, true); // true for asynchronous
+ xmlHttp.send(null);
+}
+
+function populateOptions(selector, packageName) {
+ var versionRequestUrl = "https://azuresdkdocs.blob.core.windows.net/$web/" + SELECTED_LANGUAGE + "/" + packageName + "/versioning/versions"
+
+ httpGetAsync(versionRequestUrl, function (responseText) {
+ var versionselector = document.createElement("select")
+ var cv = WINDOW_CONTENTS[6]
+
+ versionselector.className = 'navbar-version-select'
+ if (responseText) {
+ options = responseText.match(/[^\r\n]+/g)
+ for (var i in options) {
+ $(versionselector).append('')
+ }
+ }
+
+ if(cv === 'latest')
+ {
+ $(versionselector).selectedIndex = 0
+ }
+ else {
+ $(versionselector).val(cv);
+ }
+
+ $(selector).append(versionselector)
+
+ $(versionselector).change(function () {
+ targetVersion = $(this).val()
+ url = WINDOW_CONTENTS.slice()
+ url[6] = targetVersion
+ var targetUrl = url.join('/')
+ httpGetAsyncFallbackOnFail(targetUrl, (unused) => window.location.href = url.join('/'),
+ (failureStatus) => window.location.href = getPackageUrl(SELECTED_LANGUAGE, packageName, targetVersion))
+ });
+
+ })
+}
+
+function httpGetLatestAsync(targetUrl, latestVersions, packageName) {
+ httpGetAsync(targetUrl, function (responseText) {
+ if (responseText) {
+ version = responseText.match(/[^\r\n]+/g)
+ $(latestVersions).append('' + version + '')
+ }
+ })
+}
+
+function populateIndexList(selector, packageName) {
+ var url = "https://azuresdkdocs.blob.core.windows.net/$web/" + SELECTED_LANGUAGE + "/" + packageName + "/versioning/versions"
+ var latestGAUrl = "https://azuresdkdocs.blob.core.windows.net/$web/" + SELECTED_LANGUAGE + "/" + packageName + "/versioning/latest-ga"
+ var latestPreviewUrl = "https://azuresdkdocs.blob.core.windows.net/$web/" + SELECTED_LANGUAGE + "/" + packageName + "/versioning/latest-preview"
+ var latestVersions = document.createElement("ul")
+ httpGetLatestAsync(latestGAUrl, latestVersions, packageName)
+ httpGetLatestAsync(latestPreviewUrl, latestVersions, packageName)
+ var publishedVersions = $('')
+ var collapsible = $(' Other versions
')
+
+ $(selector).next().after(latestVersions)
+ $(latestVersions).after(collapsible)
+ $(collapsible).after(publishedVersions)
+ // Add collapsible arrows on versioned docs.
+ $(collapsible).on('click', function(event) {
+ event.preventDefault();
+ if (collapsible.hasClass('disable')) {
+ return
+ }
+ $(this).toggleClass('down')
+ if ($(this).hasClass('down')) {
+ if (!$(selector).hasClass('loaded')){
+ httpGetAsync(url, function (responseText) {
+ if (responseText) {
+ options = responseText.match(/[^\r\n]+/g)
+ for (var i in options) {
+ $(publishedVersions).append('' + options[i] + '')
+
+ }
+ }
+ else {
+ $(publishedVersions).append('No discovered versions present in blob storage.')
+ }
+ $(selector).addClass("loaded")
+ })
+ }
+ $(publishedVersions).show()
+ } else {
+ $(publishedVersions).hide()
+ }
+ });
+}
+
+function getPackageUrl(language, package, version) {
+ return "https://azuresdkdocs.blob.core.windows.net/$web/" + language + "/" + package + "/" + version + "/" + INDEX_HTML
+}
+
+// Populate Versions
+$(function () {
+ if (WINDOW_CONTENTS.length < 7 && WINDOW_CONTENTS[WINDOW_CONTENTS.length - 1] != 'index.html') {
+ console.log("Run PopulateList")
+
+ $('h4').each(function () {
+ var pkgName = $(this).text().replace(PACKAGE_REGEX, PACKAGE_REPLACEMENT)
+ populateIndexList($(this), pkgName)
+ })
+ }
+
+ if (WINDOW_CONTENTS.length > 7) {
+ var pkgName = WINDOW_CONTENTS[5]
+ populateOptions($('#navbar'), pkgName)
+ }
+})
+
+
+
+
+
diff --git a/eng/common/pipelines/templates/steps/docindex.yml b/eng/common/pipelines/templates/steps/docindex.yml
new file mode 100644
index 000000000000..002c009bc6a3
--- /dev/null
+++ b/eng/common/pipelines/templates/steps/docindex.yml
@@ -0,0 +1,73 @@
+jobs:
+ - job: CreateDocIndex
+ variables:
+ - template: templates/variables/globals.yml
+ pool:
+ vmImage: windows-2019
+ steps:
+ - task: UsePythonVersion@0
+ displayName: 'Use Python 3.6'
+ inputs:
+ versionSpec: '3.6'
+
+ - pwsh: |
+ Invoke-WebRequest -Uri "https://github.com/dotnet/docfx/releases/download/v2.43.2/docfx.zip" `
+ -OutFile "docfx.zip" | Wait-Process; Expand-Archive -Path "docfx.zip" -DestinationPath ./docfx
+ echo "##vso[task.setvariable variable=docfxPath]$(Build.BinariesDirectory)/docfx/docfx.exe"
+ workingDirectory: $(Build.BinariesDirectory)
+ displayName: Download and Extract DocFX
+
+ - task: PowerShell@2
+ displayName: 'Generate Doc Index'
+ inputs:
+ pwsh: true
+ filePath: $(Build.SourcesDirectory)/eng/common/docgeneration/Generate-DocIndex.ps1
+ arguments: >
+ -Docfx $(docfxPath)
+ -RepoRoot $(Build.SourcesDirectory)
+ -DocGenDir "$(Build.SourcesDirectory)/eng/common/docgeneration"
+ -DocOutDir "$(Build.ArtifactStagingDirectory)/docfx_project"
+ -verbose
+
+ - task: UsePythonVersion@0
+ displayName: 'Use Python 3.6'
+ inputs:
+ versionSpec: '3.6'
+ - template: /eng/common/pipelines/templates/steps/mashup-doc-index.yml
+ parameters:
+ SourceDirectory: $(Build.ArtifactStagingDirectory)
+ - pwsh: |
+ Copy-Item -Path $(Build.SourcesDirectory)/eng/* -Destination ./ -Recurse -Force
+ echo "##vso[task.setvariable variable=toolPath]$(Build.BinariesDirectory)"
+ workingDirectory: $(Build.BinariesDirectory)
+ displayName: Move eng/common to Tool Directory
+
+ - task: PublishPipelineArtifact@0
+ condition: succeeded()
+ inputs:
+ artifactName: "Doc.Index"
+ targetPath: $(Build.ArtifactStagingDirectory)/docfx_project/_site
+
+ - pwsh: |
+ git checkout -b gh-pages-local --track origin/gh-pages-root
+ workingDirectory: $(Build.SourcesDirectory)
+ displayName: Git pull GH pages branch
+
+ - pwsh: |
+ Copy-Item -Path $(Build.ArtifactStagingDirectory)/docfx_project/_site/* -Destination ./ -Recurse -Force
+ git add -A
+ workingDirectory: $(Build.SourcesDirectory)
+ displayName: Copy the latest changes
+
+ - task: PowerShell@2
+ displayName: Push the Docs to GH-Pages
+ condition: succeeded()
+ inputs:
+ pwsh: true
+ workingDirectory: $(Build.SourcesDirectory)
+ filePath: $(toolPath)/common/scripts/git-branch-push.ps1
+ arguments: >
+ -PRBranchName "gh-pages"
+ -CommitMsg "Auto-generated docs from SHA(s) $(Build.SourceVersion)"
+ -GitUrl "https://$(azuresdk-github-pat)@github.com/$(Build.Repository.Name).git"
+ -PushArgs "--force"
\ No newline at end of file