Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate deprecations list from language repo #300

Merged
merged 3 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`;
Expand Down
150 changes: 6 additions & 144 deletions lib/src/deprecations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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,
},
};
24 changes: 24 additions & 0 deletions lib/src/version.ts
Original file line number Diff line number Diff line change
@@ -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])
);
}
}
67 changes: 67 additions & 0 deletions tool/get-deprecations.ts
Original file line number Diff line number Diff line change
@@ -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);
}
3 changes: 3 additions & 0 deletions tool/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -65,6 +66,8 @@ void (async () => {
await getEmbeddedCompiler(outPath);
}
}

await getDeprecations(outPath);
} catch (error) {
console.error(error);
process.exitCode = 1;
Expand Down
Loading