1 # Generates an index page for cataloging different versions of the Docs
2 [CmdletBinding()]
3 Param (
4     $DocFx,
5     $RepoRoot,
6     $DocGenDir,
7     $DocOutDir = "${RepoRoot}/docfx_project",
8     $DocfxJsonPath = "${PSScriptRoot}\docfx.json",
9     $MainJsPath = "${PSScriptRoot}\templates\matthews\styles\main.js"
10 )
11 . "${PSScriptRoot}\..\scripts\common.ps1"
12 
13 # Given the github io blob storage url and language regex,
14 # the helper function will return a list of artifact names.
Get-BlobStorage-Artifacts($blobStorageUrl, $blobDirectoryRegex, $blobArtifactsReplacement)15 function Get-BlobStorage-Artifacts($blobStorageUrl, $blobDirectoryRegex, $blobArtifactsReplacement) {
16     LogDebug "Reading artifact from storage blob ..."
17     $returnedArtifacts = @()
18     $pageToken = ""
19     Do {
20       $resp = ""
21       if (!$pageToken) {
22         # First page call.
23         $resp = Invoke-RestMethod -Method Get -Uri $blobStorageUrl
24       }
25       else {
26         # Next page call
27         $blobStorageUrlPageToken = $blobStorageUrl + "&marker=$pageToken"
28         $resp = Invoke-RestMethod -Method Get -Uri $blobStorageUrlPageToken
29       }
30       # Convert to xml documents.
31       $xmlDoc = [xml](removeBomFromString $resp)
32       foreach ($elem in $xmlDoc.EnumerationResults.Blobs.BlobPrefix) {
33         # What service return like "dotnet/Azure.AI.Anomalydetector/", needs to fetch out "Azure.AI.Anomalydetector"
34         $artifact = $elem.Name -replace $blobDirectoryRegex, $blobArtifactsReplacement
35         $returnedArtifacts += $artifact
36       }
37       # Fetch page token
38       $pageToken = $xmlDoc.EnumerationResults.NextMarker
39     } while ($pageToken)
40     return $returnedArtifacts
41   }
42 
43 # The sequence of Bom bytes differs by different encoding.
44 # The helper function here is only to strip the utf-8 encoding system as it is used by blob storage list api.
45 # Return the original string if not in BOM utf-8 sequence.
RemoveBomFromString([string]$bomAwareString)46 function RemoveBomFromString([string]$bomAwareString) {
47     if ($bomAwareString.length -le 3) {
48         return $bomAwareString
49     }
50     $bomPatternByteArray = [byte[]] (0xef, 0xbb, 0xbf)
51     # The default encoding for powershell is ISO-8859-1, so converting bytes with the encoding.
52     $bomAwareBytes = [Text.Encoding]::GetEncoding(28591).GetBytes($bomAwareString.Substring(0, 3))
53     if (@(Compare-Object $bomPatternByteArray $bomAwareBytes -SyncWindow 0).Length -eq 0) {
54         return $bomAwareString.Substring(3)
55     }
56     return $bomAwareString
57 }
58 
Get-TocMappingnull59 function Get-TocMapping {
60     Param (
61         [Parameter(Mandatory = $true)] [Object[]] $metadata,
62         [Parameter(Mandatory = $true)] [String[]] $artifacts
63     )
64     # Used for sorting the toc display order
65     $orderServiceMapping = @{}
66 
67     foreach ($artifact in $artifacts) {
68         $packageInfo = $metadata | ? { $_.Package -eq $artifact -and $_.Hide -ne "true" }
69         $serviceName = ""
70         $displayName = ""
71         if (!$packageInfo) {
72             LogDebug "There is no service name for artifact $artifact or it is marked as hidden. Please check csv of Azure/azure-sdk/_data/release/latest repo if this is intended. "
73             continue
74         }
75         elseif (!$packageInfo[0].ServiceName) {
76             LogWarning "There is no service name for artifact $artifact. Please check csv of Azure/azure-sdk/_data/release/latest repo if this is intended. "
77             # If no service name retrieved, print out warning message, and put it into Other page.
78             $serviceName = "Other"
79             $displayName = $packageInfo[0].DisplayName.Trim()
80         }
81         else {
82             if ($packageInfo.Length -gt 1) {
83                 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. "
84             }
85             $serviceName = $packageInfo[0].ServiceName.Trim()
86             $displayName = $packageInfo[0].DisplayName.Trim()
87         }
88         $orderServiceMapping[$artifact] = @($serviceName, $displayName)
89     }
90     return $orderServiceMapping
91 }
92 
GenerateDocfxTocContent([Hashtable]$tocContent, [String]$lang, [String]$campaignId = "UA-62780441-46")93 function GenerateDocfxTocContent([Hashtable]$tocContent, [String]$lang, [String]$campaignId = "UA-62780441-46") {
94     LogDebug "Start generating the docfx toc and build docfx site..."
95 
96     LogDebug "Initializing Default DocFx Site..."
97     & $($DocFx) init -q -o "${DocOutDir}"
98     # The line below is used for testing in local
99     #docfx init -q -o "${DocOutDir}"
100     LogDebug "Copying template and configuration..."
101     New-Item -Path "${DocOutDir}" -Name "templates" -ItemType "directory" -Force
102     Copy-Item "${DocGenDir}/templates/*" -Destination "${DocOutDir}/templates" -Force -Recurse
103 
104     $headerTemplateLocation = "${DocOutDir}/templates/matthews/partials/head.tmpl.partial"
105 
106     if ($campaignId -and (Test-Path $headerTemplateLocation)){
107         $headerTemplateContent = Get-Content -Path $headerTemplateLocation -Raw
108         $headerTemplateContent = $headerTemplateContent -replace "GA_CAMPAIGN_ID", $campaignId
109         Set-Content -Path $headerTemplateLocation -Value $headerTemplateContent -NoNewline
110     }
111 
112     Copy-Item "${DocGenDir}/docfx.json" -Destination "${DocOutDir}/" -Force
113     $YmlPath = "${DocOutDir}/api"
114     New-Item -Path $YmlPath -Name "toc.yml" -Force
115     $visitedService = @{}
116     # Sort and display toc service name by alphabetical order, and then sort artifact by order.
117     foreach ($serviceMapping in ($tocContent.GetEnumerator() | Sort-Object Value, Key)) {
118         $artifact = $serviceMapping.Key
119         $serviceName = $serviceMapping.Value[0]
120         $displayName = $serviceMapping.Value[1]
121 
122         $fileName = ($serviceName -replace '\s', '').ToLower().Trim()
123         if ($visitedService.ContainsKey($serviceName)) {
124             if ($displayName) {
125                 Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact`n##### ($displayName)"
126             }
127             else {
128                 Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact"
129             }
130         }
131         else {
132             Add-Content -Path "$($YmlPath)/toc.yml" -Value "- name: ${serviceName}`r`n  href: ${fileName}.md"
133             New-Item -Path $YmlPath -Name "${fileName}.md" -Force
134             if ($displayName) {
135                 Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact`n##### ($displayName)"
136             }
137             else {
138                 Add-Content -Path "$($YmlPath)/${fileName}.md" -Value "#### $artifact"
139             }
140             $visitedService[$serviceName] = $true
141         }
142     }
143 
144     # Generate toc homepage.
145     LogDebug "Creating Site Title and Navigation..."
146     New-Item -Path "${DocOutDir}" -Name "toc.yml" -Force
147     Add-Content -Path "${DocOutDir}/toc.yml" -Value "- name: Azure SDK for $lang APIs`r`n  href: api/`r`n  homepage: api/index.md"
148 
149     LogDebug "Copying root markdowns"
150     Copy-Item "$($RepoRoot)/README.md" -Destination "${DocOutDir}/api/index.md" -Force
151     Copy-Item "$($RepoRoot)/CONTRIBUTING.md" -Destination "${DocOutDir}/api/CONTRIBUTING.md" -Force
152 
153     LogDebug "Building site..."
154     & $($DocFx) build "${DocOutDir}/docfx.json"
155     # The line below is used for testing in local
156     #docfx build "${DocOutDir}/docfx.json"
157     Copy-Item "${DocGenDir}/assets/logo.svg" -Destination "${DocOutDir}/_site/" -Force
158 }
159 
UpdateDocIndexFilesnull160 function UpdateDocIndexFiles {
161     Param (
162         [Parameter(Mandatory=$false)] [String]$appTitleLang = $Language,
163         [Parameter(Mandatory=$false)] [String]$lang = $Language,
164         [Parameter(Mandatory=$false)] [String]$packageRegex = "`"`"",
165         [Parameter(Mandatory=$false)] [String]$regexReplacement = ""
166     )
167     # Update docfx.json
168     $docfxContent = Get-Content -Path $DocfxJsonPath -Raw
169     $docfxContent = $docfxContent -replace "`"_appTitle`": `"`"", "`"_appTitle`": `"Azure SDK for $appTitleLang`""
170     $docfxContent = $docfxContent -replace "`"_appFooter`": `"`"", "`"_appFooter`": `"Azure SDK for $appTitleLang`""
171     Set-Content -Path $DocfxJsonPath -Value $docfxContent -NoNewline
172     # Update main.js var lang
173     $mainJsContent = Get-Content -Path $MainJsPath -Raw
174     $mainJsContent = $mainJsContent -replace "var SELECTED_LANGUAGE = ''", "var SELECTED_LANGUAGE = '$lang'"
175     # Update main.js package regex and replacement
176     $mainJsContent = $mainJsContent -replace "var PACKAGE_REGEX = ''", "var PACKAGE_REGEX = $packageRegex"
177     $mainJsContent = $mainJsContent -replace "var PACKAGE_REPLACEMENT = ''", "var PACKAGE_REPLACEMENT = `"$regexReplacement`""
178 
179     Set-Content -Path $MainJsPath -Value $mainJsContent -NoNewline
180 }
181 
182 if ($GetGithubIoDocIndexFn -and (Test-Path "function:$GetGithubIoDocIndexFn"))
183 {
184     &$GetGithubIoDocIndexFn
185 }
186 else
187 {
188     LogWarning "The function for 'GetGithubIoDocIndexFn' was not found.`
189     Make sure it is present in eng/scripts/Language-Settings.ps1 and referenced in eng/common/scripts/common.ps1.`
190     See https://github.com/Azure/azure-sdk-tools/blob/main/doc/common/common_engsys.md#code-structure"
191 }
192