sass/tool/sync-deprecations.ts
Jennifer Thakar 87699d79b2
Add deprecations.yaml as a single-source-of-truth (#3872)
Instead of having the list of deprecations repeated in several different
places across all of our repos, the new `spec/deprecations.yaml` file
will be the only place we need to update it, with all other uses
generating code based on it.
2024-05-29 14:23:18 -07:00

101 lines
3.1 KiB
TypeScript

// Updates the JS API spec and docs with the list of deprecations specified
// in spec/deprecations.yaml.
import * as colors from 'colors/safe';
import * as crypto from 'crypto';
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 = 'spec/deprecations.yaml';
const specFile = 'spec/js-api/deprecations.d.ts.md';
const docFile = 'js-api-doc/deprecations.d.ts';
const specRegex =
/<!-- START AUTOGENERATED LIST -->[\s\S]*?<!-- END AUTOGENERATED LIST -->/m;
const docRegex =
/\/\/ START AUTOGENERATED LIST[\s\S]*?\/\/ END AUTOGENERATED LIST/m;
(async () => {
const yamlText = fs.readFileSync(yamlFile, 'utf8');
const oldSpecText = fs.readFileSync(specFile, 'utf8');
const oldDocText = fs.readFileSync(docFile, 'utf8');
if (!specRegex.test(oldSpecText)) {
console.error(
`${colors.red(colors.bold('Error:'))} ` +
`Cannot find AUTOGENERATED LIST block in ${specFile}`
);
process.exitCode = 1;
return;
}
if (!docRegex.test(oldDocText)) {
console.error(
`${colors.red(colors.bold('Error:'))} ` +
`Cannot find AUTOGENERATED LIST block in ${docFile}`
);
process.exitCode = 1;
return;
}
const deprecations = parse(yamlText) as YamlData;
let specList = '';
let docList = '';
for (const [id, deprecation] of Object.entries(deprecations)) {
const key = id.includes('-') ? `'${id}'` : id;
specList += ` ${key}: Deprecation<'${id}'>;\n`;
const lowercase =
deprecation.description.substring(0, 1).toLowerCase() +
deprecation.description.substring(1);
const dartSass = deprecation['dart-sass'];
const activeText = !dartSass.deprecated
? 'This deprecation is not yet active, but will be soon.'
: dartSass.deprecated === '0.0.0'
? 'This deprecation was active in the first version of Dart Sass.'
: `This deprecation became active in Dart Sass ${dartSass.deprecated}.`;
const obsoleteText = dartSass.obsolete
? `\nIt became obsolete in Dart Sass ${dartSass.obsolete}.`
: '';
docList += ` /**
* Deprecation for ${lowercase.replace(/\$PLATFORM/g, 'JS')}
*
* ${activeText}${obsoleteText}
*/
${key}: Deprecation<'${id}'>;\n\n`;
}
const checksum = crypto.createHash('sha1').update(yamlText).digest('hex');
const newSpecText = oldSpecText.replace(
/<!-- START AUTOGENERATED LIST -->[\s\S]*?<!-- END AUTOGENERATED LIST -->/m,
`<!-- START AUTOGENERATED LIST -->
<!-- Checksum: ${checksum} -->
\`\`\`ts
export interface Deprecations {
${specList} 'user-authored': Deprecation<'user-authored', 'user'>;
}
\`\`\`
<!-- END AUTOGENERATED LIST -->`
);
const newDocText = oldDocText.replace(
/\/\/ START AUTOGENERATED LIST[\s\S]*?\/\/ END AUTOGENERATED LIST/m,
`// START AUTOGENERATED LIST
// Checksum: ${checksum}
${docList} // END AUTOGENERATED LIST`
);
fs.writeFileSync(specFile, newSpecText);
fs.writeFileSync(docFile, newDocText);
})();