param(
[string]$WebsiteRoot = 'C:\Users\XFEstudio\Desktop\work\CSharp\GitHub\XFEstudio\XFEStudioWebSite'
)
$ErrorActionPreference = 'Stop'
$destination = Join-Path $PSScriptRoot '../Source/XFESystem.Documents'
$assetDirectory = Join-Path $destination 'Assets/Website'
$utf8 = New-Object System.Text.UTF8Encoding($false)
$entries = New-Object System.Collections.Generic.List[object]
$mapping = [ordered]@{
'XFEStudioWebSite/wwwroot/css/docs/code-style.css' = 'CodeStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/markdown-style.css' = 'MarkdownStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/log.css' = 'Log.css'
'XFEStudioWebSite/wwwroot/css/docs/terminal.css' = 'Terminal.css'
'XFEStudioWebSite/wwwroot/css/docs/katex.min.css' = 'Katex.min.css'
'XFEStudioWebSite/wwwroot/js/docs/highlight.min.js' = 'Highlight.min.js'
'XFEStudioWebSite/wwwroot/js/docs/xaml.js' = 'Xaml.js'
'XFEStudioWebSite/wwwroot/js/docs/csharp.js' = 'CSharp.js'
'XFEStudioWebSite/wwwroot/js/docs/bash.js' = 'Bash.js'
'XFEStudioWebSite/wwwroot/js/docs/powershell.js' = 'PowerShell.js'
'XFEStudioWebSite/wwwroot/js/docs/dos.js' = 'Dos.js'
'XFEStudioWebSite/wwwroot/js/docs/log.js' = 'Log.js'
'XFEStudioWebSite/wwwroot/js/docs/plaintext.js' = 'PlainText.js'
'XFEStudioWebSite/wwwroot/js/docs/katex.min.js' = 'Katex.min.js'
'XFEStudioWebSite/wwwroot/js/docs/auto-render.min.js' = 'AutoRender.min.js'
'XFEStudioWebSite/wwwroot/js/docs/code-block-tools.js' = 'CodeBlockTools.js'
'XFEStudioWebSite/wwwroot/js/docs/doc-utils.js' = 'DocUtils.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.min.js' = 'Mermaid.min.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.LICENSE.txt' = 'Mermaid.License.txt'
'LICENSE.txt' = 'Website.License.txt'
'XFEStudioWebSite/Services/MarkdownService.cs' = '../../Snapshots/MarkdownService.cs.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownStyles.cshtml' = '../../Snapshots/MarkdownStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownScripts.cshtml' = '../../Snapshots/MarkdownScripts.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightStyles.cshtml' = '../../Snapshots/CodeHighlightStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightScripts.cshtml' = '../../Snapshots/CodeHighlightScripts.cshtml.txt'
'XFEStudioWebSite/Services/CodeHighlightLanguage.cs' = '../../Snapshots/CodeHighlightLanguage.cs.txt'
}
$fontMapping = @{}
Get-ChildItem -LiteralPath (Join-Path $WebsiteRoot 'XFEStudioWebSite/wwwroot/css/docs/fonts') -File | ForEach-Object {
$fontName = 'Katex' + ($_.BaseName.Substring(5) -replace '[_-]', '') + $_.Extension
$fontMapping[$_.Name] = $fontName
$mapping['XFEStudioWebSite/wwwroot/css/docs/fonts/' + $_.Name] = 'Fonts/' + $fontName
}
foreach ($sourceName in $mapping.Keys) {
$source = Join-Path $WebsiteRoot $sourceName
$target = [System.IO.Path]::GetFullPath((Join-Path $assetDirectory $mapping[$sourceName]))
$targetParent = Split-Path $target -Parent
New-Item -ItemType Directory -Force -Path $targetParent | Out-Null
$transformation = 'Exact byte copy'
if ($sourceName.EndsWith('katex.min.css')) {
$text = [System.IO.File]::ReadAllText($source)
$text = [regex]::Replace($text, 'src:([^;}]+)', [System.Text.RegularExpressions.MatchEvaluator]{
param($fontMatch)
$available = @($fontMatch.Groups[1].Value.Split(',') | Where-Object {
$fontUrl = [regex]::Match($_, 'url\(fonts/([^)]+)\)')
$fontUrl.Success -and $fontMapping.ContainsKey($fontUrl.Groups[1].Value)
} | ForEach-Object {
$fontUrl = [regex]::Match($_, 'url\(fonts/([^)]+)\)')
$_.Replace('fonts/' + $fontUrl.Groups[1].Value, 'Fonts/' + $fontMapping[$fontUrl.Groups[1].Value])
})
if ($available.Count -eq 0) { throw 'The website font declaration has no local font file.' }
return 'src:' + ($available -join ',')
})
[System.IO.File]::WriteAllText($target, $text, $utf8)
$transformation = 'Rewrite local font paths to PascalCase; omit missing website fallback files while retaining available formats'
} elseif ($sourceName.EndsWith('doc-utils.js')) {
$text = [System.IO.File]::ReadAllText($source).Replace('/js/docs/mermaid.min.js?v=11.16.0', 'https://xfe-resources.invalid/Documents/Mermaid.min.js')
[System.IO.File]::WriteAllText($target, $text, $utf8)
$transformation = 'Rewrite only the Mermaid loader URL to the bundled resource origin'
} else {
Copy-Item -LiteralPath $source -Destination $target
}
$entries.Add([ordered]@{
SourcePath = $sourceName
SnapshotPath = $mapping[$sourceName]
SourceSha256 = (Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash.ToLowerInvariant()
SnapshotSha256 = (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash.ToLowerInvariant()
Transformation = $transformation
})
}
$commit = & git -C $WebsiteRoot rev-parse HEAD
if ($LASTEXITCODE -ne 0) { throw 'Cannot identify the website commit.' }
$manifest = [ordered]@{
SchemaVersion = 1
SourceRepository = 'XFEStudioWebSite'
SourceCommit = $commit.Trim()
SourceWorkingTreeStatus = @(& git -C $WebsiteRoot status --short)
CapturedUtc = [DateTime]::UtcNow.ToString('o')
Pipeline = 'Markdig 0.44.0: UseAdvancedExtensions + UseAutoIdentifiers; HtmlSanitizer 9.1.968-beta'
Entries = $entries
}
[System.IO.File]::WriteAllText((Join-Path $assetDirectory 'SourceManifest.json'), ($manifest | ConvertTo-Json -Depth 8), $utf8)
$language = [System.IO.File]::ReadAllText((Join-Path $WebsiteRoot 'XFEStudioWebSite/Services/CodeHighlightLanguage.cs')).Replace('namespace XFEStudioWebSite.Services;', 'namespace XFESystem.Documents;')
[System.IO.File]::WriteAllText((Join-Path $destination 'CodeHighlightLanguage.cs'), ('// Adapted from XFEStudioWebSite; see Assets/Website/SourceManifest.json.' + [Environment]::NewLine + $language), $utf8)
# Preserve the older host-only preview bundle above. The native browser uses this
# second bundle without changing CSS declarations, script code, or font URLs.
# URL aliases are routing metadata; the packaged files still use PascalCase.
$exactDirectory = Join-Path $assetDirectory 'Exact'
$exactMapping = [ordered]@{
'XFEStudioWebSite/wwwroot/css/bootstrap.min.css' = 'Bootstrap.min.css'
'XFEStudioWebSite/wwwroot/css/bootstrap-icons.min.css' = 'BootstrapIcons.min.css'
'XFEStudioWebSite/wwwroot/css/theme-variables.css' = 'ThemeVariables.css'
'XFEStudioWebSite/wwwroot/css/docs/docs-layout.css' = 'DocsLayout.css'
'XFEStudioWebSite/wwwroot/css/docs/code-style.css' = 'CodeStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/markdown-style.css' = 'MarkdownStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/log.css' = 'Log.css'
'XFEStudioWebSite/wwwroot/css/docs/terminal.css' = 'Terminal.css'
'XFEStudioWebSite/wwwroot/css/docs/katex.min.css' = 'Katex.min.css'
'XFEStudioWebSite/wwwroot/js/docs/highlight.min.js' = 'Highlight.min.js'
'XFEStudioWebSite/wwwroot/js/docs/xaml.js' = 'Xaml.js'
'XFEStudioWebSite/wwwroot/js/docs/csharp.js' = 'CSharp.js'
'XFEStudioWebSite/wwwroot/js/docs/bash.js' = 'Bash.js'
'XFEStudioWebSite/wwwroot/js/docs/powershell.js' = 'PowerShell.js'
'XFEStudioWebSite/wwwroot/js/docs/dos.js' = 'Dos.js'
'XFEStudioWebSite/wwwroot/js/docs/log.js' = 'Log.js'
'XFEStudioWebSite/wwwroot/js/docs/plaintext.js' = 'PlainText.js'
'XFEStudioWebSite/wwwroot/js/docs/katex.min.js' = 'Katex.min.js'
'XFEStudioWebSite/wwwroot/js/docs/auto-render.min.js' = 'AutoRender.min.js'
'XFEStudioWebSite/wwwroot/js/docs/doc-utils.js' = 'DocUtils.js'
'XFEStudioWebSite/wwwroot/js/docs/code-block-tools.js' = 'CodeBlockTools.js'
'XFEStudioWebSite/wwwroot/js/docs/docs-reader.js' = 'DocsReader.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.min.js' = 'Mermaid.min.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.LICENSE.txt' = 'Mermaid.License.txt'
'LICENSE.txt' = 'Website.License.txt'
'XFEStudioWebSite/Views/Docs/View.cshtml' = 'Snapshots/DocsView.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_Layout.cshtml' = 'Snapshots/Layout.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownStyles.cshtml' = 'Snapshots/MarkdownStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownScripts.cshtml' = 'Snapshots/MarkdownScripts.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightStyles.cshtml' = 'Snapshots/CodeHighlightStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightScripts.cshtml' = 'Snapshots/CodeHighlightScripts.cshtml.txt'
'XFEStudioWebSite/Services/MarkdownService.cs' = 'Snapshots/MarkdownService.cs.txt'
'XFEStudioWebSite/Services/CodeHighlightLanguage.cs' = 'Snapshots/CodeHighlightLanguage.cs.txt'
}
Get-ChildItem -LiteralPath (Join-Path $WebsiteRoot 'XFEStudioWebSite/wwwroot/css/docs/fonts') -File | ForEach-Object {
$fontName = 'Katex' + ($_.BaseName.Substring(5) -replace '[_-]', '') + $_.Extension
$exactMapping['XFEStudioWebSite/wwwroot/css/docs/fonts/' + $_.Name] = 'Fonts/' + $fontName
}
$exactEntries = New-Object System.Collections.Generic.List[object]
foreach ($sourceName in $exactMapping.Keys) {
$source = Join-Path $WebsiteRoot $sourceName
$target = Join-Path $exactDirectory $exactMapping[$sourceName]
New-Item -ItemType Directory -Force -Path (Split-Path $target -Parent) | Out-Null
Copy-Item -LiteralPath $source -Destination $target
$urlPath = $null
if ($sourceName.StartsWith('XFEStudioWebSite/wwwroot/')) { $urlPath = '/' + $sourceName.Substring('XFEStudioWebSite/wwwroot/'.Length) }
$exactEntries.Add([ordered]@{
SourcePath = $sourceName
SnapshotPath = $exactMapping[$sourceName]
UrlPath = $urlPath
SourceSha256 = (Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash.ToLowerInvariant()
SnapshotSha256 = (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash.ToLowerInvariant()
Transformation = 'Exact byte copy; canonical URL aliases are resolved by the resource host'
License = $(if ($sourceName.EndsWith('bootstrap.min.css') -or $sourceName.EndsWith('bootstrap-icons.min.css')) { 'MIT; license header retained in source' }
elseif ($sourceName.EndsWith('highlight.min.js')) { 'BSD-3-Clause; ../Highlight.License.txt' }
elseif ($sourceName.Contains('katex') -or $sourceName.Contains('auto-render') -or $sourceName.Contains('/fonts/')) { 'MIT; ../Katex.License.txt' }
elseif ($sourceName.Contains('mermaid')) { 'MIT; Mermaid.License.txt' }
else { 'Website.License.txt' })
})
}
$exactManifest = [ordered]@{
SchemaVersion = 2
SourceRepository = 'XFEStudioWebSite'
SourceCommit = $commit.Trim()
SourceWorkingTreeStatus = @(& git -C $WebsiteRoot status --short)
CapturedUtc = [DateTime]::UtcNow.ToString('o')
Pipeline = $manifest.Pipeline
Scope = 'Website Markdown article body, shared code highlighting and styles; outer site navigation and authenticated actions are not embedded'
Entries = $exactEntries
}
[System.IO.File]::WriteAllText((Join-Path $exactDirectory 'SourceManifest.json'), ($exactManifest | ConvertTo-Json -Depth 8), $utf8)
$catalogLines = New-Object System.Collections.Generic.List[string]
$catalogLines.Add('// Generated from the read-only website snapshot by scripts/ImportWebsiteDocuments.ps1.')
$catalogLines.Add('// Asset bytes and source licenses: Assets/Website/Exact/SourceManifest.json.')
$catalogLines.Add('namespace XFESystem.Documents;')
$catalogLines.Add('')
$catalogLines.Add('public sealed record WebsiteWebResource(string UrlPath, string AssetName, string ContentType);')
$catalogLines.Add('')
$catalogLines.Add('public static class WebsiteWebResourceCatalog')
$catalogLines.Add('{')
$catalogLines.Add(' public static IReadOnlyList<WebsiteWebResource> Resources { get; } = Array.AsReadOnly(new WebsiteWebResource[]')
$catalogLines.Add(' {')
foreach ($entry in $exactEntries) {
if ($null -eq $entry.UrlPath) { continue }
$mime = switch ([System.IO.Path]::GetExtension($entry.UrlPath)) {
'.css' { 'text/css' }
'.js' { 'application/javascript' }
'.woff2' { 'font/woff2' }
'.woff' { 'font/woff' }
'.ttf' { 'font/ttf' }
default { 'application/octet-stream' }
}
$catalogLines.Add((' new("{0}", "Exact/{1}", "{2}"),' -f $entry.UrlPath, $entry.SnapshotPath, $mime))
}
$catalogLines.Add(' });')
$catalogLines.Add('}')
[System.IO.File]::WriteAllText((Join-Path $destination 'WebsiteWebResourceCatalog.cs'), ($catalogLines -join [Environment]::NewLine) + [Environment]::NewLine, $utf8)
Write-Output ('Imported ' + $entries.Count + ' website sources; website files were read only.')
Write-Output ('Imported ' + $exactEntries.Count + ' exact native browser sources without modifying CSS or JavaScript.')
param(
[string]$WebsiteRoot = 'C:\Users\XFEstudio\Desktop\work\CSharp\GitHub\XFEstudio\XFEStudioWebSite'
)
$ErrorActionPreference = 'Stop'
$destination = Join-Path $PSScriptRoot '../Source/XFESystem.Documents'
$assetDirectory = Join-Path $destination 'Assets/Website'
$utf8 = New-Object System.Text.UTF8Encoding($false)
$entries = New-Object System.Collections.Generic.List[object]
$mapping = [ordered]@{
'XFEStudioWebSite/wwwroot/css/docs/code-style.css' = 'CodeStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/markdown-style.css' = 'MarkdownStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/log.css' = 'Log.css'
'XFEStudioWebSite/wwwroot/css/docs/terminal.css' = 'Terminal.css'
'XFEStudioWebSite/wwwroot/css/docs/katex.min.css' = 'Katex.min.css'
'XFEStudioWebSite/wwwroot/js/docs/highlight.min.js' = 'Highlight.min.js'
'XFEStudioWebSite/wwwroot/js/docs/xaml.js' = 'Xaml.js'
'XFEStudioWebSite/wwwroot/js/docs/csharp.js' = 'CSharp.js'
'XFEStudioWebSite/wwwroot/js/docs/bash.js' = 'Bash.js'
'XFEStudioWebSite/wwwroot/js/docs/powershell.js' = 'PowerShell.js'
'XFEStudioWebSite/wwwroot/js/docs/dos.js' = 'Dos.js'
'XFEStudioWebSite/wwwroot/js/docs/log.js' = 'Log.js'
'XFEStudioWebSite/wwwroot/js/docs/plaintext.js' = 'PlainText.js'
'XFEStudioWebSite/wwwroot/js/docs/katex.min.js' = 'Katex.min.js'
'XFEStudioWebSite/wwwroot/js/docs/auto-render.min.js' = 'AutoRender.min.js'
'XFEStudioWebSite/wwwroot/js/docs/code-block-tools.js' = 'CodeBlockTools.js'
'XFEStudioWebSite/wwwroot/js/docs/doc-utils.js' = 'DocUtils.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.min.js' = 'Mermaid.min.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.LICENSE.txt' = 'Mermaid.License.txt'
'LICENSE.txt' = 'Website.License.txt'
'XFEStudioWebSite/Services/MarkdownService.cs' = '../../Snapshots/MarkdownService.cs.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownStyles.cshtml' = '../../Snapshots/MarkdownStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownScripts.cshtml' = '../../Snapshots/MarkdownScripts.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightStyles.cshtml' = '../../Snapshots/CodeHighlightStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightScripts.cshtml' = '../../Snapshots/CodeHighlightScripts.cshtml.txt'
'XFEStudioWebSite/Services/CodeHighlightLanguage.cs' = '../../Snapshots/CodeHighlightLanguage.cs.txt'
}
$fontMapping = @{}
Get-ChildItem -LiteralPath (Join-Path $WebsiteRoot 'XFEStudioWebSite/wwwroot/css/docs/fonts') -File | ForEach-Object {
$fontName = 'Katex' + ($_.BaseName.Substring(5) -replace '[_-]', '') + $_.Extension
$fontMapping[$_.Name] = $fontName
$mapping['XFEStudioWebSite/wwwroot/css/docs/fonts/' + $_.Name] = 'Fonts/' + $fontName
}
foreach ($sourceName in $mapping.Keys) {
$source = Join-Path $WebsiteRoot $sourceName
$target = [System.IO.Path]::GetFullPath((Join-Path $assetDirectory $mapping[$sourceName]))
$targetParent = Split-Path $target -Parent
New-Item -ItemType Directory -Force -Path $targetParent | Out-Null
$transformation = 'Exact byte copy'
if ($sourceName.EndsWith('katex.min.css')) {
$text = [System.IO.File]::ReadAllText($source)
$text = [regex]::Replace($text, 'src:([^;}]+)', [System.Text.RegularExpressions.MatchEvaluator]{
param($fontMatch)
$available = @($fontMatch.Groups[1].Value.Split(',') | Where-Object {
$fontUrl = [regex]::Match($_, 'url\(fonts/([^)]+)\)')
$fontUrl.Success -and $fontMapping.ContainsKey($fontUrl.Groups[1].Value)
} | ForEach-Object {
$fontUrl = [regex]::Match($_, 'url\(fonts/([^)]+)\)')
$_.Replace('fonts/' + $fontUrl.Groups[1].Value, 'Fonts/' + $fontMapping[$fontUrl.Groups[1].Value])
})
if ($available.Count -eq 0) { throw 'The website font declaration has no local font file.' }
return 'src:' + ($available -join ',')
})
[System.IO.File]::WriteAllText($target, $text, $utf8)
$transformation = 'Rewrite local font paths to PascalCase; omit missing website fallback files while retaining available formats'
} elseif ($sourceName.EndsWith('doc-utils.js')) {
$text = [System.IO.File]::ReadAllText($source).Replace('/js/docs/mermaid.min.js?v=11.16.0', 'https://xfe-resources.invalid/Documents/Mermaid.min.js')
[System.IO.File]::WriteAllText($target, $text, $utf8)
$transformation = 'Rewrite only the Mermaid loader URL to the bundled resource origin'
} else {
Copy-Item -LiteralPath $source -Destination $target
}
$entries.Add([ordered]@{
SourcePath = $sourceName
SnapshotPath = $mapping[$sourceName]
SourceSha256 = (Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash.ToLowerInvariant()
SnapshotSha256 = (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash.ToLowerInvariant()
Transformation = $transformation
})
}
$commit = & git -C $WebsiteRoot rev-parse HEAD
if ($LASTEXITCODE -ne 0) { throw 'Cannot identify the website commit.' }
$manifest = [ordered]@{
SchemaVersion = 1
SourceRepository = 'XFEStudioWebSite'
SourceCommit = $commit.Trim()
SourceWorkingTreeStatus = @(& git -C $WebsiteRoot status --short)
CapturedUtc = [DateTime]::UtcNow.ToString('o')
Pipeline = 'Markdig 0.44.0: UseAdvancedExtensions + UseAutoIdentifiers; HtmlSanitizer 9.1.968-beta'
Entries = $entries
}
[System.IO.File]::WriteAllText((Join-Path $assetDirectory 'SourceManifest.json'), ($manifest | ConvertTo-Json -Depth 8), $utf8)
$language = [System.IO.File]::ReadAllText((Join-Path $WebsiteRoot 'XFEStudioWebSite/Services/CodeHighlightLanguage.cs')).Replace('namespace XFEStudioWebSite.Services;', 'namespace XFESystem.Documents;')
[System.IO.File]::WriteAllText((Join-Path $destination 'CodeHighlightLanguage.cs'), ('// Adapted from XFEStudioWebSite; see Assets/Website/SourceManifest.json.' + [Environment]::NewLine + $language), $utf8)
# Preserve the older host-only preview bundle above. The native browser uses this
# second bundle without changing CSS declarations, script code, or font URLs.
# URL aliases are routing metadata; the packaged files still use PascalCase.
$exactDirectory = Join-Path $assetDirectory 'Exact'
$exactMapping = [ordered]@{
'XFEStudioWebSite/wwwroot/css/bootstrap.min.css' = 'Bootstrap.min.css'
'XFEStudioWebSite/wwwroot/css/bootstrap-icons.min.css' = 'BootstrapIcons.min.css'
'XFEStudioWebSite/wwwroot/css/theme-variables.css' = 'ThemeVariables.css'
'XFEStudioWebSite/wwwroot/css/docs/docs-layout.css' = 'DocsLayout.css'
'XFEStudioWebSite/wwwroot/css/docs/code-style.css' = 'CodeStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/markdown-style.css' = 'MarkdownStyle.css'
'XFEStudioWebSite/wwwroot/css/docs/log.css' = 'Log.css'
'XFEStudioWebSite/wwwroot/css/docs/terminal.css' = 'Terminal.css'
'XFEStudioWebSite/wwwroot/css/docs/katex.min.css' = 'Katex.min.css'
'XFEStudioWebSite/wwwroot/js/docs/highlight.min.js' = 'Highlight.min.js'
'XFEStudioWebSite/wwwroot/js/docs/xaml.js' = 'Xaml.js'
'XFEStudioWebSite/wwwroot/js/docs/csharp.js' = 'CSharp.js'
'XFEStudioWebSite/wwwroot/js/docs/bash.js' = 'Bash.js'
'XFEStudioWebSite/wwwroot/js/docs/powershell.js' = 'PowerShell.js'
'XFEStudioWebSite/wwwroot/js/docs/dos.js' = 'Dos.js'
'XFEStudioWebSite/wwwroot/js/docs/log.js' = 'Log.js'
'XFEStudioWebSite/wwwroot/js/docs/plaintext.js' = 'PlainText.js'
'XFEStudioWebSite/wwwroot/js/docs/katex.min.js' = 'Katex.min.js'
'XFEStudioWebSite/wwwroot/js/docs/auto-render.min.js' = 'AutoRender.min.js'
'XFEStudioWebSite/wwwroot/js/docs/doc-utils.js' = 'DocUtils.js'
'XFEStudioWebSite/wwwroot/js/docs/code-block-tools.js' = 'CodeBlockTools.js'
'XFEStudioWebSite/wwwroot/js/docs/docs-reader.js' = 'DocsReader.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.min.js' = 'Mermaid.min.js'
'XFEStudioWebSite/wwwroot/js/docs/mermaid.LICENSE.txt' = 'Mermaid.License.txt'
'LICENSE.txt' = 'Website.License.txt'
'XFEStudioWebSite/Views/Docs/View.cshtml' = 'Snapshots/DocsView.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_Layout.cshtml' = 'Snapshots/Layout.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownStyles.cshtml' = 'Snapshots/MarkdownStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_MarkdownScripts.cshtml' = 'Snapshots/MarkdownScripts.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightStyles.cshtml' = 'Snapshots/CodeHighlightStyles.cshtml.txt'
'XFEStudioWebSite/Views/Shared/_CodeHighlightScripts.cshtml' = 'Snapshots/CodeHighlightScripts.cshtml.txt'
'XFEStudioWebSite/Services/MarkdownService.cs' = 'Snapshots/MarkdownService.cs.txt'
'XFEStudioWebSite/Services/CodeHighlightLanguage.cs' = 'Snapshots/CodeHighlightLanguage.cs.txt'
}
Get-ChildItem -LiteralPath (Join-Path $WebsiteRoot 'XFEStudioWebSite/wwwroot/css/docs/fonts') -File | ForEach-Object {
$fontName = 'Katex' + ($_.BaseName.Substring(5) -replace '[_-]', '') + $_.Extension
$exactMapping['XFEStudioWebSite/wwwroot/css/docs/fonts/' + $_.Name] = 'Fonts/' + $fontName
}
$exactEntries = New-Object System.Collections.Generic.List[object]
foreach ($sourceName in $exactMapping.Keys) {
$source = Join-Path $WebsiteRoot $sourceName
$target = Join-Path $exactDirectory $exactMapping[$sourceName]
New-Item -ItemType Directory -Force -Path (Split-Path $target -Parent) | Out-Null
Copy-Item -LiteralPath $source -Destination $target
$urlPath = $null
if ($sourceName.StartsWith('XFEStudioWebSite/wwwroot/')) { $urlPath = '/' + $sourceName.Substring('XFEStudioWebSite/wwwroot/'.Length) }
$exactEntries.Add([ordered]@{
SourcePath = $sourceName
SnapshotPath = $exactMapping[$sourceName]
UrlPath = $urlPath
SourceSha256 = (Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash.ToLowerInvariant()
SnapshotSha256 = (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash.ToLowerInvariant()
Transformation = 'Exact byte copy; canonical URL aliases are resolved by the resource host'
License = $(if ($sourceName.EndsWith('bootstrap.min.css') -or $sourceName.EndsWith('bootstrap-icons.min.css')) { 'MIT; license header retained in source' }
elseif ($sourceName.EndsWith('highlight.min.js')) { 'BSD-3-Clause; ../Highlight.License.txt' }
elseif ($sourceName.Contains('katex') -or $sourceName.Contains('auto-render') -or $sourceName.Contains('/fonts/')) { 'MIT; ../Katex.License.txt' }
elseif ($sourceName.Contains('mermaid')) { 'MIT; Mermaid.License.txt' }
else { 'Website.License.txt' })
})
}
$exactManifest = [ordered]@{
SchemaVersion = 2
SourceRepository = 'XFEStudioWebSite'
SourceCommit = $commit.Trim()
SourceWorkingTreeStatus = @(& git -C $WebsiteRoot status --short)
CapturedUtc = [DateTime]::UtcNow.ToString('o')
Pipeline = $manifest.Pipeline
Scope = 'Website Markdown article body, shared code highlighting and styles; outer site navigation and authenticated actions are not embedded'
Entries = $exactEntries
}
[System.IO.File]::WriteAllText((Join-Path $exactDirectory 'SourceManifest.json'), ($exactManifest | ConvertTo-Json -Depth 8), $utf8)
$catalogLines = New-Object System.Collections.Generic.List[string]
$catalogLines.Add('// Generated from the read-only website snapshot by scripts/ImportWebsiteDocuments.ps1.')
$catalogLines.Add('// Asset bytes and source licenses: Assets/Website/Exact/SourceManifest.json.')
$catalogLines.Add('namespace XFESystem.Documents;')
$catalogLines.Add('')
$catalogLines.Add('public sealed record WebsiteWebResource(string UrlPath, string AssetName, string ContentType);')
$catalogLines.Add('')
$catalogLines.Add('public static class WebsiteWebResourceCatalog')
$catalogLines.Add('{')
$catalogLines.Add(' public static IReadOnlyList<WebsiteWebResource> Resources { get; } = Array.AsReadOnly(new WebsiteWebResource[]')
$catalogLines.Add(' {')
foreach ($entry in $exactEntries) {
if ($null -eq $entry.UrlPath) { continue }
$mime = switch ([System.IO.Path]::GetExtension($entry.UrlPath)) {
'.css' { 'text/css' }
'.js' { 'application/javascript' }
'.woff2' { 'font/woff2' }
'.woff' { 'font/woff' }
'.ttf' { 'font/ttf' }
default { 'application/octet-stream' }
}
$catalogLines.Add((' new("{0}", "Exact/{1}", "{2}"),' -f $entry.UrlPath, $entry.SnapshotPath, $mime))
}
$catalogLines.Add(' });')
$catalogLines.Add('}')
[System.IO.File]::WriteAllText((Join-Path $destination 'WebsiteWebResourceCatalog.cs'), ($catalogLines -join [Environment]::NewLine) + [Environment]::NewLine, $utf8)
Write-Output ('Imported ' + $entries.Count + ' website sources; website files were read only.')
Write-Output ('Imported ' + $exactEntries.Count + ' exact native browser sources without modifying CSS or JavaScript.')