From 002e8473d267b37e2cd17a69408a8a9b73134f9a Mon Sep 17 00:00:00 2001 From: Jennifer Thakar Date: Wed, 29 May 2024 14:24:08 -0700 Subject: [PATCH] Generate deprecations list from language repo (#300) --- lib/index.ts | 2 +- lib/src/deprecations.ts | 150 ++------------------------------------- lib/src/version.ts | 24 +++++++ tool/get-deprecations.ts | 67 +++++++++++++++++ tool/init.ts | 3 + 5 files changed, 101 insertions(+), 145 deletions(-) create mode 100644 lib/src/version.ts create mode 100644 tool/get-deprecations.ts diff --git a/lib/index.ts b/lib/index.ts index 96ce209b..e148d962 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -40,8 +40,8 @@ export { Deprecation, DeprecationOrId, DeprecationStatus, - Version, } from './src/deprecations'; +export {Version} from './src/version'; export {render, renderSync} from './src/legacy'; export const info = `sass-embedded\t${pkg.version}`; diff --git a/lib/src/deprecations.ts b/lib/src/deprecations.ts index 1c679573..e30527c4 100644 --- a/lib/src/deprecations.ts +++ b/lib/src/deprecations.ts @@ -2,33 +2,17 @@ // MIT-style license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. -import * as api from './vendor/sass'; +import {deprecations} from './vendor/deprecations'; +import {Deprecation, DeprecationOrId} from './vendor/sass'; +import {Version} from './version'; +export {deprecations} from './vendor/deprecations'; export {Deprecation, DeprecationOrId, DeprecationStatus} from './vendor/sass'; -export class Version implements api.Version { - constructor( - readonly major: number, - readonly minor: number, - readonly patch: number - ) {} - static parse(version: string): Version { - const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/); - if (match === null) { - throw new Error(`Invalid version ${version}`); - } - return new Version( - parseInt(match[1]), - parseInt(match[2]), - parseInt(match[3]) - ); - } -} - /** * Returns whether the given deprecation was active in the given version. */ -function isActiveIn(deprecation: api.Deprecation, version: Version) { +function isActiveIn(deprecation: Deprecation, version: Version) { const deprecatedIn = deprecation.deprecatedIn; if (deprecation.status !== 'active' || !deprecatedIn) return false; if (version.major > deprecatedIn.major) return true; @@ -43,7 +27,7 @@ function isActiveIn(deprecation: api.Deprecation, version: Version) { * that's ready to include in a CompileRequest. */ export function getDeprecationIds( - arr: (api.DeprecationOrId | Version)[] + arr: (DeprecationOrId | Version)[] ): string[] { return arr.flatMap(item => { if (item instanceof Version) { @@ -56,125 +40,3 @@ export function getDeprecationIds( return item.id; }); } - -export const deprecations: typeof api.deprecations = { - 'call-string': { - id: 'call-string', - status: 'active', - deprecatedIn: new Version(0, 0, 0), - obsoleteIn: null, - description: 'Passing a string directly to meta.call().', - }, - elseif: { - id: 'elseif', - status: 'active', - deprecatedIn: new Version(1, 3, 2), - obsoleteIn: null, - description: '@elseif.', - }, - 'moz-document': { - id: 'moz-document', - status: 'active', - deprecatedIn: new Version(1, 7, 2), - obsoleteIn: null, - description: '@-moz-document.', - }, - 'relative-canonical': { - id: 'relative-canonical', - status: 'active', - deprecatedIn: new Version(1, 14, 2), - obsoleteIn: null, - }, - 'new-global': { - id: 'new-global', - status: 'active', - deprecatedIn: new Version(1, 17, 2), - obsoleteIn: null, - description: 'Declaring new variables with !global.', - }, - 'color-module-compat': { - id: 'color-module-compat', - status: 'active', - deprecatedIn: new Version(1, 23, 0), - obsoleteIn: null, - description: - 'Using color module functions in place of plain CSS functions.', - }, - 'slash-div': { - id: 'slash-div', - status: 'active', - deprecatedIn: new Version(1, 33, 0), - obsoleteIn: null, - description: '/ operator for division.', - }, - 'bogus-combinators': { - id: 'bogus-combinators', - status: 'active', - deprecatedIn: new Version(1, 54, 0), - obsoleteIn: null, - description: 'Leading, trailing, and repeated combinators.', - }, - 'strict-unary': { - id: 'strict-unary', - status: 'active', - deprecatedIn: new Version(1, 55, 0), - obsoleteIn: null, - description: 'Ambiguous + and - operators.', - }, - 'function-units': { - id: 'function-units', - status: 'active', - deprecatedIn: new Version(1, 56, 0), - obsoleteIn: null, - description: 'Passing invalid units to built-in functions.', - }, - 'duplicate-var-flags': { - id: 'duplicate-var-flags', - status: 'active', - deprecatedIn: new Version(1, 62, 0), - obsoleteIn: null, - description: 'Using !default or !global multiple times for one variable.', - }, - 'null-alpha': { - id: 'null-alpha', - status: 'active', - deprecatedIn: new Version(1, 62, 3), - obsoleteIn: null, - description: 'Passing null as alpha in the JS API.', - }, - 'abs-percent': { - id: 'abs-percent', - status: 'active', - deprecatedIn: new Version(1, 65, 0), - obsoleteIn: null, - description: 'Passing percentages to the Sass abs() function.', - }, - 'fs-importer-cwd': { - id: 'fs-importer-cwd', - status: 'active', - deprecatedIn: new Version(1, 73, 0), - obsoleteIn: null, - description: - 'Using the current working directory as an implicit load path.', - }, - 'css-function-mixin': { - id: 'css-function-mixin', - status: 'active', - deprecatedIn: new Version(1, 76, 0), - obsoleteIn: null, - description: 'Function and mixin names beginning with --.', - }, - import: { - id: 'import', - status: 'future', - deprecatedIn: null, - obsoleteIn: null, - description: '@import rules.', - }, - 'user-authored': { - id: 'user-authored', - status: 'user', - deprecatedIn: null, - obsoleteIn: null, - }, -}; diff --git a/lib/src/version.ts b/lib/src/version.ts new file mode 100644 index 00000000..772b8258 --- /dev/null +++ b/lib/src/version.ts @@ -0,0 +1,24 @@ +// Copyright 2024 Google LLC. Use of this source code is governed by an +// MIT-style license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. + +import * as api from './vendor/sass'; + +export class Version implements api.Version { + constructor( + readonly major: number, + readonly minor: number, + readonly patch: number + ) {} + static parse(version: string): Version { + const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/); + if (match === null) { + throw new Error(`Invalid version ${version}`); + } + return new Version( + parseInt(match[1]), + parseInt(match[2]), + parseInt(match[3]) + ); + } +} diff --git a/tool/get-deprecations.ts b/tool/get-deprecations.ts new file mode 100644 index 00000000..73618b4d --- /dev/null +++ b/tool/get-deprecations.ts @@ -0,0 +1,67 @@ +// Generates the list of deprecations from spec/deprecations.yaml in the +// language repo. + +import * as fs from 'fs'; +import {parse} from 'yaml'; + +interface YamlData { + [key: string]: { + description: string; + 'dart-sass': { + status: 'active' | 'future' | 'obsolete'; + deprecated?: string; + obsolete?: string; + }; + }; +} + +const yamlFile = 'build/sass/spec/deprecations.yaml'; + +/** + * Converts a version string in the form X.Y.Z to be code calling the Version + * constructor, or null if the string is undefined. + */ +function toVersionCode(version: string | undefined): string { + if (!version) return 'null'; + const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/); + if (match === null) { + throw new Error(`Invalid version ${version}`); + } + return `new Version(${match[1]}, ${match[2]}, ${match[3]})`; +} + +/** + * Generates the list of deprecations based on the YAML file in the language + * repo. + */ +export async function getDeprecations(outDirectory: string) { + const yamlText = fs.readFileSync(yamlFile, 'utf8'); + + const deprecations = parse(yamlText) as YamlData; + let tsText = + "import {Deprecations} from './sass';\n" + + "import {Version} from '../version';\n\n" + + 'export const deprecations: Deprecations = {\n'; + for (const [id, deprecation] of Object.entries(deprecations)) { + const key = id.includes('-') ? `'${id}'` : id; + const dartSass = deprecation['dart-sass']; + tsText += + ` ${key}: {\n` + + ` id: '${id}',\n` + + ` description: '${deprecation.description}',\n` + + ` status: '${dartSass.status}',\n` + + ` deprecatedIn: ${toVersionCode(dartSass.deprecated)},\n` + + ` obsoleteIn: ${toVersionCode(dartSass.obsolete)},\n` + + ' },\n'; + } + tsText += + " 'user-authored': {\n" + + " id: 'user-authored',\n" + + " status: 'user',\n" + + ' deprecatedIn: null,\n' + + ' obsoleteIn: null,\n' + + ' },\n' + + '}\n'; + + fs.writeFileSync(`${outDirectory}/deprecations.ts`, tsText); +} diff --git a/tool/init.ts b/tool/init.ts index a178675f..230cd09d 100644 --- a/tool/init.ts +++ b/tool/init.ts @@ -4,6 +4,7 @@ import yargs from 'yargs'; +import {getDeprecations} from './get-deprecations'; import {getEmbeddedCompiler} from './get-embedded-compiler'; import {getLanguageRepo} from './get-language-repo'; @@ -65,6 +66,8 @@ void (async () => { await getEmbeddedCompiler(outPath); } } + + await getDeprecations(outPath); } catch (error) { console.error(error); process.exitCode = 1;