aboutsummaryrefslogtreecommitdiff
path: root/dev/generate-css-json.js
diff options
context:
space:
mode:
Diffstat (limited to 'dev/generate-css-json.js')
-rw-r--r--dev/generate-css-json.js76
1 files changed, 56 insertions, 20 deletions
diff --git a/dev/generate-css-json.js b/dev/generate-css-json.js
index 914c1452..e5d4d7f0 100644
--- a/dev/generate-css-json.js
+++ b/dev/generate-css-json.js
@@ -16,26 +16,36 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import css from 'css';
import fs from 'fs';
import path from 'path';
+import {fileURLToPath} from 'url';
+
+const dirname = path.dirname(fileURLToPath(import.meta.url));
+/**
+ * @returns {{cssFile: string, overridesCssFile: string, outputPath: string}[]}
+ */
export function getTargets() {
return [
{
- cssFile: path.join(__dirname, '..', 'ext/css/structured-content.css'),
- overridesCssFile: path.join(__dirname, 'data/structured-content-overrides.css'),
- outputPath: path.join(__dirname, '..', 'ext/data/structured-content-style.json')
+ cssFile: path.join(dirname, '..', 'ext/css/structured-content.css'),
+ overridesCssFile: path.join(dirname, 'data/structured-content-overrides.css'),
+ outputPath: path.join(dirname, '..', 'ext/data/structured-content-style.json')
},
{
- cssFile: path.join(__dirname, '..', 'ext/css/display-pronunciation.css'),
- overridesCssFile: path.join(__dirname, 'data/display-pronunciation-overrides.css'),
- outputPath: path.join(__dirname, '..', 'ext/data/pronunciation-style.json')
+ cssFile: path.join(dirname, '..', 'ext/css/display-pronunciation.css'),
+ overridesCssFile: path.join(dirname, 'data/display-pronunciation-overrides.css'),
+ outputPath: path.join(dirname, '..', 'ext/data/pronunciation-style.json')
}
];
}
-import css from 'css';
-
+/**
+ * @param {import('css-style-applier').RawStyleData} rules
+ * @param {string[]} selectors
+ * @returns {number}
+ */
function indexOfRule(rules, selectors) {
const jj = selectors.length;
for (let i = 0, ii = rules.length; i < ii; ++i) {
@@ -53,6 +63,12 @@ function indexOfRule(rules, selectors) {
return -1;
}
+/**
+ * @param {import('css-style-applier').RawStyleDataStyleArray} styles
+ * @param {string} property
+ * @param {Map<string, number>} removedProperties
+ * @returns {number}
+ */
function removeProperty(styles, property, removedProperties) {
let removeCount = removedProperties.get(property);
if (typeof removeCount !== 'undefined') { return removeCount; }
@@ -69,6 +85,10 @@ function removeProperty(styles, property, removedProperties) {
return removeCount;
}
+/**
+ * @param {import('css-style-applier').RawStyleData} rules
+ * @returns {string}
+ */
export function formatRulesJson(rules) {
// Manually format JSON, for improved compactness
// return JSON.stringify(rules, null, 4);
@@ -102,27 +122,39 @@ export function formatRulesJson(rules) {
return result;
}
+/**
+ * @param {string} cssFile
+ * @param {string} overridesCssFile
+ * @returns {import('css-style-applier').RawStyleData}
+ * @throws {Error}
+ */
export function generateRules(cssFile, overridesCssFile) {
const content1 = fs.readFileSync(cssFile, {encoding: 'utf8'});
const content2 = fs.readFileSync(overridesCssFile, {encoding: 'utf8'});
- const stylesheet1 = css.parse(content1, {}).stylesheet;
- const stylesheet2 = css.parse(content2, {}).stylesheet;
+ const stylesheet1 = /** @type {css.StyleRules} */ (css.parse(content1, {}).stylesheet);
+ const stylesheet2 = /** @type {css.StyleRules} */ (css.parse(content2, {}).stylesheet);
const removePropertyPattern = /^remove-property\s+([\w\W]+)$/;
const removeRulePattern = /^remove-rule$/;
const propertySeparator = /\s+/;
+ /** @type {import('css-style-applier').RawStyleData} */
const rules = [];
// Default stylesheet
for (const rule of stylesheet1.rules) {
if (rule.type !== 'rule') { continue; }
- const {selectors, declarations} = rule;
+ const {selectors, declarations} = /** @type {css.Rule} */ (rule);
+ if (typeof selectors === 'undefined') { continue; }
+ /** @type {import('css-style-applier').RawStyleDataStyleArray} */
const styles = [];
- for (const declaration of declarations) {
- if (declaration.type !== 'declaration') { console.log(declaration); continue; }
- const {property, value} = declaration;
- styles.push([property, value]);
+ if (typeof declarations !== 'undefined') {
+ for (const declaration of declarations) {
+ if (declaration.type !== 'declaration') { console.log(declaration); continue; }
+ const {property, value} = /** @type {css.Declaration} */ (declaration);
+ if (typeof property !== 'string' || typeof value !== 'string') { continue; }
+ styles.push([property, value]);
+ }
}
if (styles.length > 0) {
rules.push({selectors, styles});
@@ -132,7 +164,9 @@ export function generateRules(cssFile, overridesCssFile) {
// Overrides
for (const rule of stylesheet2.rules) {
if (rule.type !== 'rule') { continue; }
- const {selectors, declarations} = rule;
+ const {selectors, declarations} = /** @type {css.Rule} */ (rule);
+ if (typeof selectors === 'undefined' || typeof declarations === 'undefined') { continue; }
+ /** @type {Map<string, number>} */
const removedProperties = new Map();
for (const declaration of declarations) {
switch (declaration.type) {
@@ -146,16 +180,18 @@ export function generateRules(cssFile, overridesCssFile) {
entry = {selectors, styles: []};
rules.push(entry);
}
- const {property, value} = declaration;
- removeProperty(entry.styles, property, removedProperties);
- entry.styles.push([property, value]);
+ const {property, value} = /** @type {css.Declaration} */ (declaration);
+ if (typeof property === 'string' && typeof value === 'string') {
+ removeProperty(entry.styles, property, removedProperties);
+ entry.styles.push([property, value]);
+ }
}
break;
case 'comment':
{
const index = indexOfRule(rules, selectors);
if (index < 0) { throw new Error('Could not find rule with matching selectors'); }
- const comment = declaration.comment.trim();
+ const comment = (/** @type {css.Comment} */ (declaration).comment || '').trim();
let m;
if ((m = removePropertyPattern.exec(comment)) !== null) {
for (const property of m[1].split(propertySeparator)) {