build(site): [SITE-07] deliver original Monaco language service notices

This commit is contained in:
Harvey Zhao committed 2026-09-15 09:20:49 +08:00
1 parent 0d3ddbf355
commit 11c9fefadd
42 files changed
+3141 -19

No files matched your search

+11
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 { verifyMonacoLanguageNotices } from './site-vendor/monaco/notices.ts'
import { writeOrCheckNotices } from './site-vendor/notices.ts'
assert(process.argv.slice(2).every(arg => arg === '--check'), 'Use yarn build:site-notices [--check]')
@@ -14,11 +15,20 @@ assert.deepEqual(manifest.groups.filter(group => group.name !== 'console').flatM
'copy-text-to-clipboard',
'core-js',
'css-loader',
'glob-to-regexp (Monaco JSON fork)',
'js-beautify (Monaco HTML embedded)',
'jsonc-parser',
'mutation-observer',
'regenerator-runtime',
'style-loader',
'svelte',
'typescript (Monaco worker)',
'vscode-css-languageservice',
'vscode-html-languageservice',
'vscode-json-languageservice',
'vscode-languageserver-textdocument',
'vscode-languageserver-types',
'vscode-uri',
'webpack',
], 'Do not silently drop verified bundled component attribution')
const consoleGroup = manifest.groups.find(group => group.name === 'console')
@@ -75,5 +85,6 @@ 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)
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.`)
+179
View File
@@ -940,6 +940,66 @@
"source": "refactor/baselines/site-vendor/monaco-typescript/ATTRIBUTION.txt",
"target": "docs/licenses/monaco-editor/typescript/ATTRIBUTION.md",
"sha256": "edb4b7526e86fadf7461ffda983f9f56a96472cf1ebf639947948e405ed95321"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/jsonc-parser/LICENSE.md.txt",
"target": "docs/licenses/monaco-editor/language-services/jsonc-parser/LICENSE.md",
"sha256": "c3a24c02d678e5f0711623dcf3ab3f243b273c2633f638a1fa8e35fb7c7f8e4d"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-css-languageservice/LICENSE.md.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-css-languageservice/LICENSE.md",
"sha256": "c3a24c02d678e5f0711623dcf3ab3f243b273c2633f638a1fa8e35fb7c7f8e4d"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-html-languageservice/LICENSE.md.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-html-languageservice/LICENSE.md",
"sha256": "c3a24c02d678e5f0711623dcf3ab3f243b273c2633f638a1fa8e35fb7c7f8e4d"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-html-languageservice/thirdpartynotices.txt.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-html-languageservice/thirdpartynotices.txt",
"sha256": "6fac688548f02e656a57234c7f0cb4a74bd8645b4ef2c7a33f5117861b9f3de0"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-json-languageservice/LICENSE.md.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-json-languageservice/LICENSE.md",
"sha256": "4742836d395a83a45d2278d9b738824d68abb1a03b81d567210a6cbc3e686e12"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-languageserver-textdocument/License.txt.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-languageserver-textdocument/License.txt",
"sha256": "ec9ee83580841e8eb687aca9867f221503809ba6426c7f876ede17d91b9fcfd0"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-languageserver-textdocument/thirdpartynotices.txt.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-languageserver-textdocument/thirdpartynotices.txt",
"sha256": "a89123562fe364dc8e969e85614eb6c1f8452afe131d6e42bd1314bb2d092b04"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-languageserver-types/License.txt.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-languageserver-types/License.txt",
"sha256": "ec9ee83580841e8eb687aca9867f221503809ba6426c7f876ede17d91b9fcfd0"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/vscode-uri/LICENSE.md.txt",
"target": "docs/licenses/monaco-editor/language-services/vscode-uri/LICENSE.md",
"sha256": "c669138cb1eb01fbb745e8e460b291e4f2869c14a40061390b6095d845ed4c82"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/beautify-css-NOTICE.txt",
"target": "docs/licenses/monaco-editor/language-services/beautify-css-NOTICE.txt",
"sha256": "ec728062ceae23091680dda36437fe1fa48975821e047adbb06a76805425e518"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/beautify-html-NOTICE.txt",
"target": "docs/licenses/monaco-editor/language-services/beautify-html-NOTICE.txt",
"sha256": "25451d033cad3539a2cadfeda7fa5e29eb74e3413917cde63d8210a259fdc893"
},
{
"source": "refactor/baselines/site-vendor/monaco-language-notices/ATTRIBUTION.txt",
"target": "docs/licenses/monaco-editor/language-services/ATTRIBUTION.md",
"sha256": "432cca135809edabcd9ccedd05576138b64b167445999005a6e1550132391d98"
}
],
"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.",
@@ -971,6 +1031,125 @@
"docs/licenses/monaco-editor/typescript/ThirdPartyNoticeText.txt",
"docs/licenses/monaco-editor/typescript/ATTRIBUTION.md"
]
},
{
"name": "jsonc-parser",
"version": "3.0.0",
"tarball": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
"assets": [
"docs/assets/js/vs/language/json/jsonWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/jsonc-parser/LICENSE.md",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "vscode-css-languageservice",
"version": "5.1.8",
"tarball": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.1.8.tgz",
"assets": [
"docs/assets/js/vs/language/css/cssWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-css-languageservice/LICENSE.md",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "vscode-html-languageservice",
"version": "4.1.1",
"tarball": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.1.1.tgz",
"assets": [
"docs/assets/js/vs/language/html/htmlWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-html-languageservice/LICENSE.md",
"docs/licenses/monaco-editor/language-services/vscode-html-languageservice/thirdpartynotices.txt",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "vscode-json-languageservice",
"version": "4.1.9",
"tarball": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.9.tgz",
"assets": [
"docs/assets/js/vs/language/json/jsonWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-json-languageservice/LICENSE.md",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "vscode-languageserver-textdocument",
"version": "1.0.2",
"tarball": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.2.tgz",
"assets": [
"docs/assets/js/vs/language/css/cssWorker.js",
"docs/assets/js/vs/language/html/htmlWorker.js",
"docs/assets/js/vs/language/json/jsonWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-languageserver-textdocument/License.txt",
"docs/licenses/monaco-editor/language-services/vscode-languageserver-textdocument/thirdpartynotices.txt",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "vscode-languageserver-types",
"version": "3.16.0",
"tarball": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
"assets": [
"docs/assets/js/vs/language/css/cssWorker.js",
"docs/assets/js/vs/language/html/htmlWorker.js",
"docs/assets/js/vs/language/json/jsonWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-languageserver-types/License.txt",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "vscode-uri",
"version": "3.0.2",
"tarball": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz",
"assets": [
"docs/assets/js/vs/language/css/cssWorker.js",
"docs/assets/js/vs/language/html/htmlWorker.js",
"docs/assets/js/vs/language/json/jsonWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-uri/LICENSE.md",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "js-beautify (Monaco HTML embedded)",
"version": "embedded sources in vscode-html-languageservice 4.1.1",
"tarball": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.1.1.tgz",
"assets": [
"docs/assets/js/vs/language/html/htmlWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/beautify-css-NOTICE.txt",
"docs/licenses/monaco-editor/language-services/beautify-html-NOTICE.txt",
"docs/licenses/monaco-editor/language-services/vscode-html-languageservice/LICENSE.md",
"docs/licenses/monaco-editor/language-services/vscode-html-languageservice/thirdpartynotices.txt",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
},
{
"name": "glob-to-regexp (Monaco JSON fork)",
"version": "embedded source in vscode-json-languageservice 4.1.9",
"tarball": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.9.tgz",
"assets": [
"docs/assets/js/vs/language/json/jsonWorker.js"
],
"notices": [
"docs/licenses/monaco-editor/language-services/vscode-json-languageservice/LICENSE.md",
"docs/licenses/monaco-editor/language-services/ATTRIBUTION.md"
]
}
]
},
+23 -6
View File
@@ -80,9 +80,26 @@ disposes both workers and models. Monaco 0.30.1 has no public CSS/HTML/JSON work
getter equivalent to `getTypeScriptWorker`. Tests exercise valid/invalid CSS and
JSON, HTML tag completion, document symbols, and HTML/JSON formatting on three engines.
This source checkpoint does not close embedded license review. Follow up with the
seven packages' original licenses/third-party notices, including HTML beautifiers
and data sources. Core embedded libraries, mode bundles and language definitions
also remain 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.
## Language-service notices
`monaco-language-notices.json` binds seven verified package versions to their nine
complete original LICENSE/third-party notice files. Two exact source-comment slices
preserve the HTML service's CSS/HTML beautifier MIT notices, 2007-2018 author years
and formatter authors. The package's older 2007-2017 text remains verbatim. A local
attribution explains this difference and the JSON service's original glob-to-regexp
BSD conditions; neither component is relabeled as solely Microsoft's MIT code.
The separate `beautify.js` source is Microsoft's no-op JS formatting adapter.
`notices.ts` binds the nine component entries (seven packages plus two embedded
origins) to their exact worker paths and delivered notices. The normal site build
checks these associations before any output write. Full reproduction additionally
matches all 12 notice inputs against their archived files or exact header byte
ranges. Preserve raw bytes and the `-text` Git attributes for frozen/output notices.
`site-vendor.spec.js` checks all 81 site notice files over HTTP plus the supplement's
12 relative links, alongside mobile player playback and console cleanup.
This does not close all Monaco embedded-source review. Core embedded libraries,
mode bundles, 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.
+80
View File
@@ -0,0 +1,80 @@
import type { VendorManifest } from '../notices.ts'
import type { ArchiveCache, Member } from './archives.ts'
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import { hash } from './archives.ts'
interface Notice {
source: string
target: string
sha256: string
archive?: string
member?: string
memberSha256?: string
slice?: { start: number, end: number }
}
interface Component { name: string, version: string, tarball: string, assets: string[], notices: string[] }
interface NoticeRecord { packages: (Component & { archive: string })[], components: Component[], notices: Notice[] }
interface Sources {
archives: { name: string, version: string, tarball: string }[]
modules: (Member & { id: string })[]
workers: { ids: string[], target: { path: string } }[]
}
function readNotices(root: string): NoticeRecord {
return JSON.parse(fs.readFileSync(path.join(root, 'refactor/baselines/monaco-language-notices.json'), 'utf8'))
}
// Cheap build-time binding checks; do not download or execute archived code.
export function verifyMonacoLanguageNotices(root: string, manifest: VendorManifest): number {
const record = readNotices(root)
const sources: Sources = JSON.parse(fs.readFileSync(path.join(root, 'refactor/baselines/monaco-languages-provenance.json'), 'utf8'))
assert.equal(record.notices.length, 12, 'Missing Monaco language notice source')
assert.equal(record.components.length, 9, 'Missing Monaco language component source')
assert.deepEqual(record.packages.map(item => item.name).sort(), [...new Set(sources.modules.map(item => item.id.split('/')[0]))].sort(), 'Incomplete Monaco service attribution')
const group = manifest.groups.find(group => group.name === 'monaco-editor')
assert(group?.components, 'Missing Monaco group')
for (const pkg of record.packages) {
const archive = sources.archives.find(item => `${item.name}-${item.version}` === pkg.archive)
assert(archive && archive.name === pkg.name && archive.version === pkg.version && archive.tarball === pkg.tarball, 'Wrong Monaco service source identity')
const modules = sources.modules.filter(item => item.archive === pkg.archive).map(item => item.id)
const assets = sources.workers.filter(worker => worker.ids.some(id => modules.includes(id))).map(worker => worker.target.path)
assert.deepEqual(pkg.assets, assets, 'Wrong Monaco service asset binding')
}
for (const expected of record.components) {
const matches: Component[] = group.components.filter(item => item.name === expected.name)
assert.equal(matches.length, 1, `Missing Monaco language component: ${expected.name}`)
const actual = matches[0]!
assert.equal(actual.version, expected.version, 'Wrong Monaco language version')
assert.equal(actual.tarball, expected.tarball, 'Wrong Monaco language source')
assert.deepEqual([...actual.assets].sort(), [...expected.assets].sort(), 'Wrong Monaco language asset')
assert.deepEqual([...actual.notices].sort(), [...expected.notices].sort(), `Wrong Monaco language notice binding: ${expected.name}`)
}
for (const expected of record.notices) {
const matches: Notice[] = group.notices.filter(item => item.target === expected.target)
assert.equal(matches.length, 1, `Missing Monaco language notice: ${expected.target}`)
assert.equal(matches[0]!.source, expected.source, 'Wrong Monaco language notice source')
assert.equal(matches[0]!.sha256, expected.sha256, 'Wrong Monaco language notice fingerprint')
}
return record.notices.length
}
// The source reproducer additionally proves the complete original files and the
// exact byte slices of embedded formatter headers against verified archives.
export function verifyMonacoLanguageNoticeArchives(root: string, cache: ArchiveCache): number {
const record = readNotices(root)
for (const notice of record.notices) {
const local = fs.readFileSync(path.join(root, notice.source))
assert.equal(hash(local), notice.sha256, 'Monaco language notice text changed')
if (notice.archive && notice.member) {
let upstream = cache.read(notice.archive, notice.member)
if (notice.slice) {
assert.equal(hash(upstream), notice.memberSha256, 'Monaco embedded header source changed')
assert(notice.slice.start >= 0 && notice.slice.end > notice.slice.start && notice.slice.end <= upstream.length, 'Invalid Monaco header boundary')
upstream = upstream.subarray(notice.slice.start, notice.slice.end)
}
assert(local.equals(upstream), 'Monaco language notice differs from archive')
}
}
return record.notices.length
}
@@ -7,6 +7,7 @@ import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { ArchiveCache, hash } from './archives.ts'
import { aliasModule, languageHeader, nameModule, verifyWorkerSources } from './languages.ts'
import { verifyMonacoLanguageNoticeArchives } from './notices.ts'
interface Provenance {
archives: Archive[]
@@ -46,6 +47,7 @@ for (const member of record.modules) {
}
const cache = new ArchiveCache(root, path.join(root, 'refactor/.cache/monaco-review'))
await cache.verify(record.archives, record.remotes, process.argv.includes('--fetch'))
const notices = verifyMonacoLanguageNoticeArchives(root, cache)
for (const name of ['typescript', 'terser', 'source-map']) {
const archive = record.archives.find(item => item.name === name)
assert(archive, 'Missing historical compiler dependency')
@@ -115,4 +117,4 @@ for (const worker of record.workers) {
assert.equal(languageHeader(worker.language) + code, target.toString('utf8'), 'Minified language worker differs')
results.push({ language: worker.language, modules: worker.ids.length, exactSources: true, exactWorker: true, sha256: hash(target) })
}
console.log(JSON.stringify({ archives: record.archives.length, gitSources: record.remotes.length, npmModules: modules.size, aliases: aliases.size, workers: results, licenseReviewComplete: false, otherMonacoComponentsReviewed: false }))
console.log(JSON.stringify({ archives: record.archives.length, gitSources: record.remotes.length, npmModules: modules.size, aliases: aliases.size, workers: results, notices, licenseReviewComplete: false, otherMonacoComponentsReviewed: false }))