build(site): [SITE-07] restore Monaco Markdown component notices

This commit is contained in:
Harvey Zhao committed 2026-09-15 10:41:24 +08:00
1 parent 426fee8faa
commit 244695e726
36 files changed
+6943 -9

No files matched your search

+4
View File
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict'
import fs from 'node:fs'
import process from 'node:process'
import { verifyConsoleNoticeSources } from './site-vendor/console/notices.ts'
import { verifyMonacoCoreNotices } from './site-vendor/monaco/core-origins.ts'
import { verifyMonacoLanguageNotices } from './site-vendor/monaco/notices.ts'
import { writeOrCheckNotices } from './site-vendor/notices.ts'
@@ -15,9 +16,11 @@ assert.deepEqual(manifest.groups.filter(group => group.name !== 'console').flatM
'copy-text-to-clipboard',
'core-js',
'css-loader',
'dompurify (Monaco core)',
'glob-to-regexp (Monaco JSON fork)',
'js-beautify (Monaco HTML embedded)',
'jsonc-parser',
'marked (Monaco core)',
'mutation-observer',
'regenerator-runtime',
'style-loader',
@@ -85,6 +88,7 @@ assert.deepEqual(typeScriptNotices?.map(target => target.split('/').pop()).sort(
for (const name of ['LICENSE', 'MIT-LICENSE', 'ATTRIBUTION.md'])
assert(vconsoleNotices?.includes(`docs/licenses/vconsole/${name}`), `Missing vConsole notice: ${name}`)
verifyConsoleNoticeSources(process.cwd(), manifest)
verifyMonacoCoreNotices(process.cwd(), manifest)
verifyMonacoLanguageNotices(process.cwd(), manifest)
const count = writeOrCheckNotices(process.cwd(), manifest, process.argv.includes('--check'))
console.log(`Verified site notices: ${count} outputs; Monaco/vConsole/console inventories, embedded and other provenance gates remain open.`)
+7 -1
View File
@@ -22,7 +22,7 @@ files retain their exact upstream bytes, including final blank lines.
`../build-site-notices.mjs` provides `yarn build:site-notices` and read-only
`yarn check:site-notices`. The write command cannot bless altered vendor assets;
review the new archive and license evidence before changing the manifest. The
CLI prevents accidentally dropping any of the three groups, the eleven reviewed
CLI prevents accidentally dropping any of the three groups, the reviewed
Monaco/vConsole components, the 44 identified console components or their notice
count, and vConsole's original license, supplemental MIT body and attribution.
Component references require their runtime assets and every notice before writing.
@@ -73,3 +73,9 @@ Monaco's actual TypeScript 4.4.4 worker now has a separate source proof and noti
supplement; its original notice's 2.7.2 label is retained and explained. See
[Monaco maintenance](monaco/README.md) for the fixed six source adaptations,
minifier reconstruction, exact-byte checks and remaining component review scope.
Monaco's core Markdown path additionally identifies DOMPurify 2.3.1 and marked
3.0.2. Four supplemental files preserve DOMPurify's missing complete license,
marked's original and legacy notices, and module-adaptation attribution. Their
asset/source/notice bindings are checked before output writes; full source matching
and real renderer/HTTP tests are documented in `monaco/README.md`.
+45
View File
@@ -1000,6 +1000,26 @@
"source": "refactor/baselines/site-vendor/monaco-language-notices/ATTRIBUTION.txt",
"target": "docs/licenses/monaco-editor/language-services/ATTRIBUTION.md",
"sha256": "432cca135809edabcd9ccedd05576138b64b167445999005a6e1550132391d98"
},
{
"source": "refactor/baselines/site-vendor/monaco-core-origins/DOMPurify-LICENSE",
"target": "docs/licenses/monaco-editor/core-origins/DOMPurify-LICENSE",
"sha256": "8b6902e953e2eb2876412a4ba75291758b77e88e220962e3423af4d080db1a59"
},
{
"source": "refactor/baselines/site-vendor/monaco-core-origins/marked-LICENSE",
"target": "docs/licenses/monaco-editor/core-origins/marked-LICENSE",
"sha256": "8e3a3f82f59a60958f56ca08f445647c32a4733dc7ca6c2c46f6eb898471ab9c"
},
{
"source": "refactor/baselines/site-vendor/monaco-core-origins/marked-vscode-license.txt",
"target": "docs/licenses/monaco-editor/core-origins/marked-vscode-license.txt",
"sha256": "43624283832b560f19539ec6d5766b7281acd4a63ada62e494c4e63c7a849bdb"
},
{
"source": "refactor/baselines/site-vendor/monaco-core-origins/ATTRIBUTION.md",
"target": "docs/licenses/monaco-editor/core-origins/ATTRIBUTION.md",
"sha256": "3a0ab7f1036d6b1397bf94ff2700375b97db2db3bd576d195dc6d8a88e1a758e"
}
],
"review": "The complete upstream Monaco LICENSE/ThirdPartyNotices are retained. The unmodified bundled Codicons font exactly matches @vscode/codicons 0.0.26; its historical README, CC BY 4.0 content license, MIT code license and added attribution are distributed below. Other site assets remain subject to their separate provenance reviews.",
@@ -1154,6 +1174,31 @@
"docs/licenses/monaco-editor/language-services/vscode-json-languageservice/LICENSE.md",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "dompurify (Monaco core)",
"version": "2.3.1",
"tarball": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.1.tgz",
"assets": [
"docs/assets/js/vs/editor/editor.main.js"
],
"notices": [
"docs/licenses/monaco-editor/core-origins/DOMPurify-LICENSE",
"docs/licenses/monaco-editor/core-origins/ATTRIBUTION.md"
]
},
{
"name": "marked (Monaco core)",
"version": "3.0.2",
"tarball": "https://registry.npmjs.org/marked/-/marked-3.0.2.tgz",
"assets": [
"docs/assets/js/vs/editor/editor.main.js"
],
"notices": [
"docs/licenses/monaco-editor/core-origins/marked-LICENSE",
"docs/licenses/monaco-editor/core-origins/marked-vscode-license.txt",
"docs/licenses/monaco-editor/core-origins/ATTRIBUTION.md"
]
}
]
},
+33
View File
@@ -162,3 +162,36 @@ language definitions and remaining upstream data/origin details stay
under VENDOR-06. Revalidate editor-types and site-vendor tests when changing
declarations or delivered notices. Whole-site, physical-device and remote release
gates remain separate.
## Core Markdown origins
`core-origins.ts` keeps component/asset/license bindings separate from the full
source reproducer. The ordinary notice build rejects missing or swapped DOMPurify
and marked terms. `reproduce-core-origins.ts` verifies four npm archives and seven
fixed VS Code Git files. The original component registrations identify DOMPurify
2.3.1 and marked 3.0.2. Exact export/wrapper edits reproduce their Git sources;
named AMD forms match complete source-map entries and development-bundle spans.
The shipped editor matches the pinned Monaco archive and retains its core prefix
and map suffix. This is not a full reconstruction of the core compiler pipeline.
DOMPurify was missing from Monaco's supplied notice index. Its entire npm license
is now delivered, including both upstream license alternatives. VS Code's copy
differs by exactly one final newline; no body text is normalized or discarded.
marked's complete npm license and older VS Code license are both retained with an
explanation of the package versions and module adaptations. Four additional files
bring the site total to 85 notices plus the generated index.
```sh
yarn verify:monaco-core-origins --fetch
yarn verify:monaco-core-origins
yarn build:site-notices
yarn check:site-notices
yarn test:browser test/browser/editor-markdown.spec.js test/browser/site-vendor.spec.js --workers=1
```
The Markdown test loads the actual bundled parser/sanitizer and renderer. It checks
formatting, table cells, link targets, selected filtering behavior and removal of
temporary sanitizer hooks. The site test checks every delivered notice byte and
relative attribution link while exercising mobile playback/logging/disposal.
Neither is an exhaustive sanitizer audit. Loader, other core modules, localization,
and further embedded-origin details remain under SITE-07/VENDOR-06.
@@ -0,0 +1,45 @@
import type { VendorManifest } from '../notices.ts'
import type { Archive, Member, Remote } from './archives.ts'
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
export interface CoreOrigins {
archives: Archive[]
remotes: Remote[]
members: Member[]
modules: (Member & { id: string, source: string, edits: { before: string, after: string }[], naming: { before: string, after: string } })[]
components: { name: string, version: string, tarball: string, assets: string[], notices: string[] }[]
notices: { source: string, target: string, sha256: string, archive?: string, member?: string }[]
target: { path: string, sha256: string }
}
export function readCoreOrigins(root: string): CoreOrigins {
return JSON.parse(fs.readFileSync(path.join(root, 'refactor/baselines/monaco-core-origins-provenance.json'), 'utf8'))
}
export function adaptCoreOrigin(source: string, edits: { before: string, after: string }[]): string {
for (const edit of edits) {
assert(edit.before && source.split(edit.before).length === 2, 'Missing or repeated core adaptation boundary')
source = source.replace(edit.before, () => edit.after)
}
return source
}
// Normal site builds enforce source/component/notice bindings without network.
export function verifyMonacoCoreNotices(root: string, manifest: VendorManifest): void {
const record = readCoreOrigins(root)
assert.deepEqual(record.components.map(item => item.name).sort(), ['dompurify (Monaco core)', 'marked (Monaco core)'])
assert.equal(record.notices.length, 4, 'Missing Monaco core notice source')
const group = manifest.groups.find(group => group.name === 'monaco-editor')
assert(group?.components, 'Missing Monaco core group')
for (const component of record.components) {
const archive = record.archives.find(archive => `${archive.name} (Monaco core)` === component.name)
assert(archive && component.version === archive.version && component.tarball === archive.tarball, 'Wrong Monaco core origin')
assert.deepEqual(component.assets, [record.target.path], 'Wrong Monaco core asset')
assert.deepEqual(group.components.filter(item => item.name === component.name), [component], 'Wrong Monaco core notice binding')
}
for (const notice of record.notices) {
assert.deepEqual(group.notices.filter(item => item.target === notice.target), [{ source: notice.source, target: notice.target, sha256: notice.sha256 }], 'Missing or changed Monaco core notice')
}
}
@@ -0,0 +1,59 @@
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { ArchiveCache, hash } from './archives.ts'
import { adaptCoreOrigin, readCoreOrigins, verifyMonacoCoreNotices } from './core-origins.ts'
const root = fileURLToPath(new URL('../../../', import.meta.url))
assert(process.argv.slice(2).every(arg => arg === '--fetch'), 'Use reproduce-core-origins.ts [--fetch]')
assert.equal(process.version, `v${fs.readFileSync(path.join(root, '.node-version'), 'utf8').trim()}`, 'Use canonical Node')
const record = readCoreOrigins(root)
const cache = new ArchiveCache(root, path.join(root, 'refactor/.cache/monaco-review'))
await cache.verify(record.archives, record.remotes, process.argv.includes('--fetch'))
verifyMonacoCoreNotices(root, JSON.parse(fs.readFileSync(path.join(root, 'scripts/site-vendor/manifest.json'), 'utf8')))
for (const name of ['dompurify', 'marked']) {
const manifest = record.remotes.find(remote => remote.source.endsWith(`${name}-cgmanifest.json.txt`))
assert(manifest, 'Missing upstream component registration')
const registrations = JSON.parse(fs.readFileSync(path.join(root, manifest.source), 'utf8')).registrations
assert.equal(registrations.length, 1)
assert.equal(registrations[0].component.git.name, name)
assert.equal(registrations[0].version, record.archives.find(archive => archive.name === name)?.version, 'Upstream component version differs')
}
for (const member of record.members)
cache.member(member)
const sourceMap: { sources: string[], sourcesContent: string[] } = JSON.parse(cache.read('monaco-editor-core-0.30.1', 'package/dev/vs/editor/editor.main.js.map').toString('utf8'))
const development = cache.read('monaco-editor-core-0.30.1', 'package/dev/vs/editor/editor.main.js').toString('utf8')
const results = []
for (const module of record.modules) {
assert(record.remotes.some(remote => remote.source === module.source), 'Unverified embedded Git source')
const git = fs.readFileSync(path.join(root, module.source), 'utf8')
assert.equal(adaptCoreOrigin(cache.member(module).toString('utf8'), module.edits), git, 'Embedded npm adaptation differs')
const named = adaptCoreOrigin(git, [module.naming])
assert.equal(sourceMap.sourcesContent[sourceMap.sources.indexOf(`${module.id}.js`)], named, 'Embedded source map differs')
const offset = development.indexOf(named)
assert(offset >= 0 && development.lastIndexOf(named) === offset, 'Missing or repeated complete embedded source')
results.push({ id: module.id, bytes: named.length, offset, exactNpmAdaptation: true, exactGitAndDevelopment: true })
}
for (const notice of record.notices) {
const bytes = fs.readFileSync(path.join(root, notice.source))
assert.equal(hash(bytes), notice.sha256, 'Core notice changed')
if (notice.archive && notice.member)
assert.deepEqual(cache.read(notice.archive, notice.member), bytes, 'Original core notice differs')
}
const purifyNotice = record.remotes.find(remote => remote.source.endsWith('dompurify.license.txt.txt'))
assert(purifyNotice)
const originalLicense = cache.read('dompurify-2.3.1', 'package/LICENSE')
assert.equal(originalLicense.subarray(-2).toString(), '\n\n')
// VS Code drops exactly one final newline; distribute the complete npm bytes.
assert.deepEqual(fs.readFileSync(path.join(root, purifyNotice.source)), originalLicense.subarray(0, -1), 'DOMPurify upstream license differs')
const target = fs.readFileSync(path.join(root, record.target.path))
assert.equal(hash(target), record.target.sha256, 'Core site bytes changed')
assert.deepEqual(target, cache.read('monaco-editor-0.30.1', 'package/min/vs/editor/editor.main.js'), 'Site differs from pinned editor archive')
const core = cache.read('monaco-editor-core-0.30.1', 'package/min/vs/editor/editor.main.js').toString('utf8').replace('"vs/editor/editor.main"', '"vs/editor/edcore.main"')
const mapOffset = core.lastIndexOf('//# sourceMappingURL=')
assert(mapOffset > 0, 'Missing core source map boundary')
assert(target.toString('utf8').startsWith(core.slice(0, mapOffset)), 'Archived core prefix differs')
assert(target.toString('utf8').endsWith(core.slice(mapOffset)), 'Archived core map suffix differs')
console.log(JSON.stringify({ archives: record.archives.length, gitSources: record.remotes.length, modules: results, notices: record.notices.length, archivedCorePrefix: true, completeCoreBuild: false, otherEmbeddedOriginsReviewed: false }))