From e215656ce9b965360e540da93ebf5c381cbe4e41 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Wed, 29 Nov 2023 20:13:15 -0500 Subject: Update types --- dev/generate-css-json.js | 61 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 14 deletions(-) (limited to 'dev/generate-css-json.js') diff --git a/dev/generate-css-json.js b/dev/generate-css-json.js index 914c1452..02e54530 100644 --- a/dev/generate-css-json.js +++ b/dev/generate-css-json.js @@ -16,9 +16,13 @@ * along with this program. If not, see . */ +import css from 'css'; import fs from 'fs'; import path from 'path'; +/** + * @returns {{cssFile: string, overridesCssFile: string, outputPath: string}[]} + */ export function getTargets() { return [ { @@ -34,8 +38,11 @@ export function getTargets() { ]; } -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 +60,12 @@ function indexOfRule(rules, selectors) { return -1; } +/** + * @param {import('css-style-applier').RawStyleDataStyleArray} styles + * @param {string} property + * @param {Map} removedProperties + * @returns {number} + */ function removeProperty(styles, property, removedProperties) { let removeCount = removedProperties.get(property); if (typeof removeCount !== 'undefined') { return removeCount; } @@ -69,6 +82,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 +119,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 +161,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} */ const removedProperties = new Map(); for (const declaration of declarations) { switch (declaration.type) { @@ -146,16 +177,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)) { -- cgit v1.2.3 From 338d210b66006189a0b775e8bd524c1cc11c2d9a Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Thu, 30 Nov 2023 20:00:46 -0500 Subject: Update paths --- dev/dictionary-validate.js | 5 ++++- dev/generate-css-json.js | 15 +++++++++------ test/anki-note-builder.test.js | 6 +++--- test/database.test.js | 5 ++++- test/deinflector.test.js | 5 ++++- test/dom-text-scanner.test.js | 4 +++- 6 files changed, 27 insertions(+), 13 deletions(-) (limited to 'dev/generate-css-json.js') diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js index b3654e75..a6948bfe 100644 --- a/dev/dictionary-validate.js +++ b/dev/dictionary-validate.js @@ -20,14 +20,17 @@ import fs from 'fs'; import JSZip from 'jszip'; import path from 'path'; import {performance} from 'perf_hooks'; +import {fileURLToPath} from 'url'; import {createJsonSchema} from './schema-validate.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); + /** * @param {string} relativeFileName * @returns {import('dev/dictionary-validate').Schema} */ function readSchema(relativeFileName) { - const fileName = path.join(__dirname, relativeFileName); + const fileName = path.join(dirname, relativeFileName); const source = fs.readFileSync(fileName, {encoding: 'utf8'}); return JSON.parse(source); } diff --git a/dev/generate-css-json.js b/dev/generate-css-json.js index 02e54530..e5d4d7f0 100644 --- a/dev/generate-css-json.js +++ b/dev/generate-css-json.js @@ -19,6 +19,9 @@ 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}[]} @@ -26,14 +29,14 @@ import path from 'path'; 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') } ]; } diff --git a/test/anki-note-builder.test.js b/test/anki-note-builder.test.js index e4af7943..96dacab6 100644 --- a/test/anki-note-builder.test.js +++ b/test/anki-note-builder.test.js @@ -26,12 +26,14 @@ import {TranslatorVM} from '../dev/translator-vm.js'; import {AnkiNoteBuilder} from '../ext/js/data/anki-note-builder.js'; import {JapaneseUtil} from '../ext/js/language/sandbox/japanese-util.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); + /** * @param {string} url2 * @returns {Promise} */ async function fetch(url2) { - const extDir = path.join(__dirname, '..', 'ext'); + const extDir = path.join(dirname, '..', 'ext'); let filePath; try { filePath = url.fileURLToPath(url2); @@ -51,8 +53,6 @@ async function fetch(url2) { vi.stubGlobal('fetch', fetch); vi.mock('../ext/js/templates/template-renderer-proxy.js'); -const dirname = path.dirname(fileURLToPath(import.meta.url)); - /** * @returns {Promise} */ diff --git a/test/database.test.js b/test/database.test.js index ee818467..30854d55 100644 --- a/test/database.test.js +++ b/test/database.test.js @@ -18,12 +18,15 @@ import {IDBFactory, IDBKeyRange} from 'fake-indexeddb'; import path from 'path'; +import {fileURLToPath} from 'node:url'; import {beforeEach, describe, expect, test, vi} from 'vitest'; import {createDictionaryArchive} from '../dev/util.js'; import {DictionaryDatabase} from '../ext/js/language/dictionary-database.js'; import {DictionaryImporterMediaLoader} from '../ext/js/language/dictionary-importer-media-loader.js'; import {DictionaryImporter} from '../ext/js/language/dictionary-importer.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); + vi.stubGlobal('IDBKeyRange', IDBKeyRange); vi.mock('../ext/js/language/dictionary-importer-media-loader.js'); @@ -34,7 +37,7 @@ vi.mock('../ext/js/language/dictionary-importer-media-loader.js'); * @returns {import('jszip')} */ function createTestDictionaryArchive(dictionary, dictionaryName) { - const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary); + const dictionaryDirectory = path.join(dirname, 'data', 'dictionaries', dictionary); return createDictionaryArchive(dictionaryDirectory, dictionaryName); } diff --git a/test/deinflector.test.js b/test/deinflector.test.js index 77184799..a69f8e56 100644 --- a/test/deinflector.test.js +++ b/test/deinflector.test.js @@ -20,6 +20,9 @@ import fs from 'fs'; import path from 'path'; import {describe, expect, test} from 'vitest'; import {Deinflector} from '../ext/js/language/deinflector.js'; +import {fileURLToPath} from 'node:url'; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); /** * @param {Deinflector} deinflector @@ -924,7 +927,7 @@ function testDeinflections() { } ]; - const deinflectionReasons = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ext', 'data/deinflect.json'), {encoding: 'utf8'})); + const deinflectionReasons = JSON.parse(fs.readFileSync(path.join(dirname, '..', 'ext', 'data/deinflect.json'), {encoding: 'utf8'})); const deinflector = new Deinflector(deinflectionReasons); describe('deinflections', () => { diff --git a/test/dom-text-scanner.test.js b/test/dom-text-scanner.test.js index 6d0c047b..30aec33e 100644 --- a/test/dom-text-scanner.test.js +++ b/test/dom-text-scanner.test.js @@ -19,9 +19,11 @@ import fs from 'fs'; import {JSDOM} from 'jsdom'; import path from 'path'; +import {fileURLToPath} from 'node:url'; import {expect, test} from 'vitest'; import {DOMTextScanner} from '../ext/js/dom/dom-text-scanner.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); /** * @param {string} fileName @@ -188,7 +190,7 @@ async function testDomTextScanner(dom) { /** */ async function testDocument1() { - const dom = createJSDOM(path.join(__dirname, 'data', 'html', 'test-dom-text-scanner.html')); + const dom = createJSDOM(path.join(dirname, 'data', 'html', 'test-dom-text-scanner.html')); const window = dom.window; try { window.getComputedStyle = createAbsoluteGetComputedStyle(window); -- cgit v1.2.3