From c4185888e010b6b68ea2340abbd9bbd6f371fd8b Mon Sep 17 00:00:00 2001 From: JiayingL Date: Wed, 16 Mar 2022 19:33:23 +0800 Subject: [PATCH] Start changing to es6 modules (#1530) * start changing to es6 modules * change more files * use e6s in more files. * finish changing all the files under lib/ and tools/ * make npm run start & npm run live running * make test using es6 * remove experimental flag, add function importJSON() in util.js * Update app.js Co-authored-by: Denis Ah-Kang Co-authored-by: Denis Ah-Kang --- .cspell.json | 3 + .eslintrc.json | 14 +- app.js | 52 +- lib/api.js | 29 +- lib/exceptions.js | 8 +- lib/l10n-en_GB.js | 2 +- lib/l10n.js | 32 +- lib/profiles/SUBM.js | 13 +- lib/profiles/SUBM/MEM-SUBM.js | 24 +- lib/profiles/TR.js | 35 +- lib/profiles/TR/Note/DNOTE-Echidna.js | 17 +- lib/profiles/TR/Note/DNOTE.js | 19 +- lib/profiles/TR/Note/NOTE-Echidna.js | 13 +- lib/profiles/TR/Note/NOTE.js | 11 +- lib/profiles/TR/Note/STMT.js | 12 +- lib/profiles/TR/Note/note-base.js | 16 +- lib/profiles/TR/Recommendation/CR-Echidna.js | 16 +- lib/profiles/TR/Recommendation/CR.js | 22 +- lib/profiles/TR/Recommendation/CRD-Echidna.js | 14 +- lib/profiles/TR/Recommendation/CRD.js | 22 +- lib/profiles/TR/Recommendation/DISC.js | 21 +- lib/profiles/TR/Recommendation/FPWD.js | 24 +- lib/profiles/TR/Recommendation/PR.js | 31 +- lib/profiles/TR/Recommendation/REC-RSCND.js | 21 +- lib/profiles/TR/Recommendation/REC.js | 41 +- lib/profiles/TR/Recommendation/WD-Echidna.js | 15 +- lib/profiles/TR/Recommendation/WD.js | 24 +- .../TR/Recommendation/recommendation-base.js | 19 +- lib/profiles/TR/Registry/CRY.js | 20 +- lib/profiles/TR/Registry/CRYD.js | 20 +- lib/profiles/TR/Registry/DRY.js | 19 +- lib/profiles/TR/Registry/RY.js | 19 +- lib/profiles/TR/Registry/registry-base.js | 6 +- lib/profiles/base.js | 95 +- lib/profiles/metadata.js | 40 +- lib/profiles/profileUtil.js | 17 +- lib/rules/echidna/todays-date.js | 10 +- lib/rules/headers/copyright.js | 17 +- lib/rules/headers/details-summary.js | 10 +- lib/rules/headers/div-head.js | 10 +- lib/rules/headers/dl.js | 10 +- lib/rules/headers/errata.js | 10 +- lib/rules/headers/github-repo.js | 10 +- lib/rules/headers/h1-title.js | 10 +- lib/rules/headers/h2-toc.js | 10 +- lib/rules/headers/hr.js | 10 +- lib/rules/headers/logo.js | 10 +- lib/rules/headers/memsub-copyright.js | 10 +- lib/rules/headers/ol-toc.js | 10 +- lib/rules/headers/secno.js | 10 +- lib/rules/headers/subm-logo.js | 10 +- lib/rules/headers/w3c-state.js | 14 +- lib/rules/heuristic/date-format.js | 10 +- lib/rules/links/compound.js | 17 +- lib/rules/links/internal.js | 10 +- lib/rules/links/linkchecker.js | 12 +- lib/rules/links/reliability.js | 10 +- lib/rules/metadata/charters.js | 10 +- lib/rules/metadata/deliverers.js | 10 +- lib/rules/metadata/dl.js | 15 +- lib/rules/metadata/docDate.js | 10 +- lib/rules/metadata/editor-ids.js | 10 +- lib/rules/metadata/editor-names.js | 10 +- lib/rules/metadata/errata.js | 10 +- lib/rules/metadata/informative.js | 10 +- lib/rules/metadata/patent-policy.js | 10 +- lib/rules/metadata/process.js | 10 +- lib/rules/metadata/profile.js | 22 +- lib/rules/metadata/title.js | 10 +- lib/rules/sotd/ac-review.js | 10 +- lib/rules/sotd/candidate-review-end.js | 10 +- lib/rules/sotd/charter.js | 18 +- lib/rules/sotd/deliverer-note.js | 10 +- lib/rules/sotd/deployment.js | 10 +- lib/rules/sotd/diff.js | 10 +- lib/rules/sotd/draft-stability.js | 10 +- lib/rules/sotd/new-features.js | 10 +- lib/rules/sotd/obsl-rescind.js | 14 +- lib/rules/sotd/pp.js | 14 +- lib/rules/sotd/process-document.js | 10 +- lib/rules/sotd/publish.js | 10 +- lib/rules/sotd/rec-addition.js | 10 +- lib/rules/sotd/rec-comment-end.js | 10 +- lib/rules/sotd/review-end.js | 10 +- lib/rules/sotd/stability.js | 14 +- lib/rules/sotd/submission.js | 14 +- lib/rules/sotd/supersedable.js | 14 +- lib/rules/sotd/usage.js | 10 +- lib/rules/structure/canonical.js | 10 +- lib/rules/structure/display-only.js | 28 +- lib/rules/structure/h2.js | 17 +- lib/rules/structure/name.js | 13 +- lib/rules/structure/neutral.js | 14 +- lib/rules/structure/section-ids.js | 10 +- lib/rules/structure/security-privacy.js | 10 +- lib/rules/style/back-to-top.js | 10 +- lib/rules/style/body-toc-sidebar.js | 10 +- lib/rules/style/meta.js | 14 +- lib/rules/style/script.js | 10 +- lib/rules/style/sheet.js | 19 +- lib/rules/validation/html.js | 17 +- lib/rules/validation/wcag.js | 10 +- lib/sink.js | 9 +- lib/throttled-ua.js | 6 +- lib/util.js | 81 +- lib/validator.js | 181 +-- lib/views.js | 24 +- package.json | 1 + test/api.js | 32 +- test/data/SUBM/MEM-SUBM.js | 10 +- test/data/SUBM/SUBMBase.js | 16 +- test/data/TR/Note/DNOTE-Echidna.js | 10 +- test/data/TR/Note/DNOTE.js | 10 +- test/data/TR/Note/NOTE-Echidna.js | 8 +- test/data/TR/Note/NOTE.js | 6 +- test/data/TR/Note/STMT.js | 6 +- test/data/TR/Note/noteBase.js | 12 +- test/data/TR/Recommendation/CR-Echidna.js | 14 +- test/data/TR/Recommendation/CR.js | 14 +- test/data/TR/Recommendation/CRD-Echidna.js | 14 +- test/data/TR/Recommendation/CRD.js | 14 +- test/data/TR/Recommendation/DISC.js | 12 +- test/data/TR/Recommendation/FPWD.js | 10 +- test/data/TR/Recommendation/PR.js | 14 +- test/data/TR/Recommendation/REC-RSCND.js | 14 +- test/data/TR/Recommendation/REC.js | 14 +- test/data/TR/Recommendation/WD-Echidna.js | 14 +- test/data/TR/Recommendation/WD.js | 14 +- .../TR/Recommendation/recommendationBase.js | 12 +- test/data/TR/Registry/CRY.js | 10 +- test/data/TR/Registry/CRYD.js | 10 +- test/data/TR/Registry/DRY.js | 10 +- test/data/TR/Registry/RY.js | 6 +- test/data/TR/Registry/registryBase.js | 6 +- test/data/TR/TRBase.js | 26 +- test/data/goodDocuments.js | 2 +- test/data/specBase.js | 2 +- test/doc-views/SUBM/MEM-SUBM.js | 9 +- test/doc-views/TR/Note/DNOTE-Echidna.js | 16 +- test/doc-views/TR/Note/DNOTE.js | 13 +- test/doc-views/TR/Note/NOTE-Echidna.js | 12 +- test/doc-views/TR/Note/NOTE.js | 9 +- test/doc-views/TR/Note/STMT.js | 9 +- test/doc-views/TR/Note/noteBase.js | 10 +- .../doc-views/TR/Recommendation/CR-Echidna.js | 19 +- test/doc-views/TR/Recommendation/CR.js | 14 +- .../TR/Recommendation/CRD-Echidna.js | 16 +- test/doc-views/TR/Recommendation/CRD.js | 17 +- test/doc-views/TR/Recommendation/DISC.js | 11 +- test/doc-views/TR/Recommendation/FPWD.js | 15 +- test/doc-views/TR/Recommendation/PR.js | 17 +- test/doc-views/TR/Recommendation/REC-RSCND.js | 17 +- test/doc-views/TR/Recommendation/REC.js | 17 +- .../doc-views/TR/Recommendation/WD-Echidna.js | 14 +- test/doc-views/TR/Recommendation/WD.js | 17 +- .../TR/Recommendation/recommendationBase.js | 6 +- test/doc-views/TR/Registry/CRY.js | 9 +- test/doc-views/TR/Registry/CRYD.js | 15 +- test/doc-views/TR/Registry/DRY.js | 13 +- test/doc-views/TR/Registry/RY.js | 9 +- test/doc-views/TR/Registry/registryBase.js | 9 +- test/doc-views/TR/TRBase.js | 170 ++- test/doc-views/specBase.js | 1348 +++++++++-------- test/l10n.js | 24 +- test/rules.js | 304 ++-- test/samples.js | 2 +- test/validation.js | 17 +- tools/fetch-groups-db.js | 12 +- tools/make-groups-db.js | 12 +- 169 files changed, 2416 insertions(+), 2013 deletions(-) diff --git a/.cspell.json b/.cspell.json index 95d11dd72..0b277e018 100644 --- a/.cspell.json +++ b/.cspell.json @@ -6,6 +6,7 @@ "badterms", "Beihang", "blocklist", + "capi", "Çelik", "charmod", "CRYD", @@ -14,6 +15,7 @@ "dcterms", "deniak", "DNOTE", + "doasync", "doctypes", "dvcs", "ERCIM", @@ -38,6 +40,7 @@ "linkchecker", "mediacapture", "memsub", + "metaviewport", "middot", "minami", "nodate", diff --git a/.eslintrc.json b/.eslintrc.json index 2029a1383..c11017c59 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,7 +10,9 @@ "global-require": "off", "no-restricted-syntax": "warn", "guard-for-in": "warn", - "prefer-destructuring": "warn" + "prefer-destructuring": "warn", + "import/prefer-default-export": "off", + "import/extensions": "off" }, "overrides": [ { @@ -25,6 +27,10 @@ { "files": ["app.js", "lib/**/*.js", "tools/**/*.js"], "plugins": ["node"], + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module" + }, "extends": ["plugin:node/recommended", "plugin:jsdoc/recommended"] }, { @@ -36,7 +42,11 @@ "node/no-unpublished-require": "off" }, "plugins": ["node"], - "extends": "plugin:node/recommended" + "extends": "plugin:node/recommended", + "parserOptions": { + "ecmaVersion": 2022, + "sourceType": "module" + } } ] } diff --git a/app.js b/app.js index e5316630d..a28165a87 100644 --- a/app.js +++ b/app.js @@ -2,7 +2,21 @@ * Main runnable file. */ -'use strict'; +import compression from 'compression'; +import cors from 'cors'; +import express from 'express'; +import http from 'http'; +import insafe from 'insafe'; +import morgan from 'morgan'; +import { Server } from 'socket.io'; +import * as api from './lib/api.js'; +import * as l10n from './lib/l10n.js'; +import { Sink } from './lib/sink.js'; +import { allProfiles, importJSON } from './lib/util.js'; +import { Specberus } from './lib/validator.js'; +import * as views from './lib/views.js'; + +const { version } = importJSON('./package.json', import.meta.url); // Settings: const DEFAULT_PORT = 80; @@ -19,33 +33,13 @@ if (!process.env.BASE_URI || process.env.BASE_URI.length < 1) { ); } -// Native packages: -const http = require('http'); - -// External packages: -const compression = require('compression'); -const express = require('express'); -const insafe = require('insafe'); -const morgan = require('morgan'); -const socket = require('socket.io'); -// Internal packages: -const self = require('./package.json'); -const l10n = require('./lib/l10n'); -const sink = require('./lib/sink'); -const validator = require('./lib/validator'); -const views = require('./lib/views'); -const util = require('./lib/util'); -const api = require('./lib/api'); - const app = express(); const server = http.createServer(app); -const io = socket(server); -const { Sink } = sink; -const { version } = self; +const io = new Server(server); // Middleware: app.use(morgan('combined')); app.use(compression()); -app.use('/badterms.json', require('cors')()); +app.use('/badterms.json', cors()); app.use(express.static('public')); api.setUp(app, process.env.W3C_API_KEY); @@ -61,7 +55,7 @@ io.on('connection', socket => { socket.on('extractMetadata', data => { if (!data.url) return socket.emit('exception', { message: 'URL not provided.' }); - const specberus = new validator.Specberus(process.env.W3C_API_KEY); + const specberus = new Specberus(process.env.W3C_API_KEY); const handler = new Sink(); handler.on('err', (type, data) => { try { @@ -105,26 +99,26 @@ io.on('connection', socket => { events: handler, }); }); - socket.on('validate', data => { + socket.on('validate', async data => { if (!data.url) return socket.emit('exception', { message: 'URL not provided.' }); if (!data.profile) return socket.emit('exception', { message: 'Profile not provided.', }); - const profilePath = util.allProfiles.find(p => + const profilePath = allProfiles.find(p => p.endsWith(`/${data.profile}.js`) ); let profile; try { - // eslint-disable-next-line import/no-dynamic-require - profile = require(`./lib/profiles/${profilePath}`); + // eslint-disable-next-line node/no-unsupported-features/es-syntax + profile = await import(`./lib/profiles/${profilePath}`); } catch (err) { return socket.emit('exception', { message: 'Profile does not exist.', }); } - const specberus = new validator.Specberus(process.env.W3C_API_KEY); + const specberus = new Specberus(process.env.W3C_API_KEY); const handler = new Sink(); const profileCode = profile.name; socket.emit('start', { diff --git a/lib/api.js b/lib/api.js index 3c12b1635..4dc5561c8 100644 --- a/lib/api.js +++ b/lib/api.js @@ -3,13 +3,12 @@ */ // Internal packages: -const self = require('../package.json'); -const sink = require('./sink'); -const util = require('./util'); -const validator = require('./validator'); +import { Sink } from './sink.js'; +import { buildJSONresult, importJSON, processParams } from './util.js'; +import { Specberus } from './validator.js'; + +const { version } = importJSON('../package.json', import.meta.url); -const { Sink } = sink; -const { version } = self; /** * Send the JSON result to the client. * @@ -21,7 +20,7 @@ const { version } = self; */ const sendJSONresult = function (err, warn, inf, res, metadata) { - const wrapper = util.buildJSONresult(err, warn, inf, metadata); + const wrapper = buildJSONresult(err, warn, inf, metadata); res.status(wrapper.success ? 200 : 400).json(wrapper); }; @@ -30,7 +29,7 @@ const sendJSONresult = function (err, warn, inf, res, metadata) { * * @param {string} apiKey */ -const processRequest = apiKey => (req, res) => { +const processRequest = apiKey => async (req, res) => { if (req.path === '/api/version') { res.status(200).send(version); } else if (req.path === '/api/metadata' || req.path === '/api/validate') { @@ -48,7 +47,7 @@ const processRequest = apiKey => (req, res) => { let handler; let handler2; try { - options = util.processParams(req.query, undefined, { + options = await processParams(req.query, undefined, { required: validate ? ['profile'] : [], forbidden: ['document', 'source'], }); @@ -57,7 +56,7 @@ const processRequest = apiKey => (req, res) => { } if (validate && options.profile === 'auto') { errors = []; - v = new validator.Specberus(apiKey); + v = new Specberus(apiKey); handler = new Sink( (...data) => { errors.push(Object.assign({}, ...data)); @@ -70,7 +69,7 @@ const processRequest = apiKey => (req, res) => { if (options.url) meta.url = options.url; else meta.file = options.file; try { - options2 = util.processParams(meta, undefined, { + options2 = processParams(meta, undefined, { allowUnknownParams: true, }); } catch (err) { @@ -86,7 +85,7 @@ const processRequest = apiKey => (req, res) => { errors2 = []; warnings2 = []; info2 = []; - v2 = new validator.Specberus(apiKey); + v2 = new Specberus(apiKey); handler2 = new Sink( (...data2) => { errors2.push(Object.assign({}, ...data2)); @@ -136,7 +135,7 @@ const processRequest = apiKey => (req, res) => { errors = []; warnings = []; info = []; - v = new validator.Specberus(apiKey); + v = new Specberus(apiKey); handler = new Sink( (...data) => { errors.push(Object.assign({}, ...data)); @@ -169,8 +168,6 @@ const processRequest = apiKey => (req, res) => { } }; -const setUp = function (app, apiKey) { +export const setUp = function (app, apiKey) { app.get('/api/*', processRequest(apiKey)); }; - -exports.setUp = setUp; diff --git a/lib/exceptions.js b/lib/exceptions.js index 5a5c0cf3b..0f482b770 100644 --- a/lib/exceptions.js +++ b/lib/exceptions.js @@ -1,4 +1,6 @@ -const records = require('./exceptions.json'); +import { importJSON } from './util.js'; + +const records = importJSON('./exceptions.json', import.meta.url); /** * @param data @@ -36,7 +38,7 @@ function findSet(shortname) { return recursiveFindSet(shortname); } -const Exceptions = function () {}; +export const Exceptions = function () {}; Exceptions.prototype.has = function (shortname, rule, key, extra) { const set = findSet(shortname); @@ -58,5 +60,3 @@ Exceptions.prototype.has = function (shortname, rule, key, extra) { } return false; }; - -exports.Exceptions = Exceptions; diff --git a/lib/l10n-en_GB.js b/lib/l10n-en_GB.js index 305862b6a..841deda47 100644 --- a/lib/l10n-en_GB.js +++ b/lib/l10n-en_GB.js @@ -1,5 +1,5 @@ /* eslint-disable no-template-curly-in-string */ -exports.messages = { +export const messages = { // Generic 'generic.sotd.not-found': 'No “status of this document” section found. Some errors related to this one will be omitted from the output, but most likely this will cause further problems along the line.', diff --git a/lib/l10n.js b/lib/l10n.js index 98fef7324..22e897bb1 100644 --- a/lib/l10n.js +++ b/lib/l10n.js @@ -3,10 +3,13 @@ */ // Internal packages: -const originalRules = require('./rules.json'); -const english = require('./l10n-en_GB'); +import { messages } from './l10n-en_GB.js'; +import { importJSON } from './util.js'; + +const originalRules = importJSON('./rules.json', import.meta.url); + // Constants: -const enGB = english.messages; +const enGB = messages; // Variables: let lang; @@ -24,7 +27,10 @@ for (const t in originalRules) * @param {string} language - locale, expressed as a string, eg en_GB. */ -exports.setLanguage = function (language) { +/** + * @param language + */ +export function setLanguage(language) { if (!language) throw new Error( 'l10n.setLanguage() invoked without passing a language code as parameter' @@ -34,7 +40,7 @@ exports.setLanguage = function (language) { throw new Error( 'Language code passed to l10n.setLanguage() is not valid' ); -}; +} /** * @param profileCode @@ -42,7 +48,7 @@ exports.setLanguage = function (language) { * @param key * @param extra */ -exports.assembleData = function (profileCode, rule, key, extra) { +export function assembleData(profileCode, rule, key, extra) { const messageData = {}; // Corner case: if the profile is unknown, let's assume 'WD' (most common). const profile = profileCode ? profileCode.replace('-Echidna', '') : 'WD'; @@ -81,11 +87,17 @@ to let developers examine the problem (you can submit it as is; no additional in messageData.profile = profile; return messageData; } -}; +} -exports.message = function (profileCode, rule, key, extra) { +/** + * @param profileCode + * @param rule + * @param key + * @param extra + */ +export function message(profileCode, rule, key, extra) { const result = {}; - const messageData = exports.assembleData(profileCode, rule, key, extra); + const messageData = assembleData(profileCode, rule, key, extra); if (!messageData) return; result.message = messageData.message && messageData.message.length @@ -158,4 +170,4 @@ ${selector}&labels=from-template">file this issue on GitHub to help develope if (messageData.additionalMessage) result.message += messageData.additionalMessage; return result; -}; +} diff --git a/lib/profiles/SUBM.js b/lib/profiles/SUBM.js index d00ed5274..0fba908b8 100644 --- a/lib/profiles/SUBM.js +++ b/lib/profiles/SUBM.js @@ -1,11 +1,8 @@ // Base profile for all Submissions +import * as submLogo from '../rules/headers/subm-logo.js'; +import { rules as baseRules } from './base.js'; +import { insertAfter } from './profileUtil.js'; -exports.name = 'Submission'; +export const name = 'Submission'; -const profileUtil = require('./profileUtil'); - -exports.rules = profileUtil.insertAfter( - require('./base').rules, - 'headers.logo', - require('../rules/headers/subm-logo') -); +export const rules = insertAfter(baseRules, 'headers.logo', submLogo); diff --git a/lib/profiles/SUBM/MEM-SUBM.js b/lib/profiles/SUBM/MEM-SUBM.js index 681238a72..e9f5e06ee 100644 --- a/lib/profiles/SUBM/MEM-SUBM.js +++ b/lib/profiles/SUBM/MEM-SUBM.js @@ -1,22 +1,24 @@ -exports.name = 'MEM-SUBM'; -exports.config = { +import * as memsubCopyright from '../../rules/headers/memsub-copyright.js'; +import * as submission from '../../rules/sotd/submission.js'; +import { insertAfter } from '../profileUtil.js'; +import { rules as baseRules } from '../SUBM.js'; + +export const name = 'MEM-SUBM'; +export const config = { status: 'SUBM', longStatus: 'Member Submission', styleSheet: 'W3C-Member-SUBM', submissionType: 'member', }; -const profileUtil = require('../profileUtil'); -let rules = profileUtil.insertAfter( - require('../SUBM').rules, +const rulesWithAdditionalHeaderRule = insertAfter( + baseRules, 'headers.w3c-state', - [require('../../rules/headers/memsub-copyright')] + [memsubCopyright] ); -rules = profileUtil.insertAfter( - rules, +export const rules = insertAfter( + rulesWithAdditionalHeaderRule, 'sotd.supersedable', - require('../../rules/sotd/submission') + submission ); - -exports.rules = rules; diff --git a/lib/profiles/TR.js b/lib/profiles/TR.js index 2b3c4be2e..10b59e421 100644 --- a/lib/profiles/TR.js +++ b/lib/profiles/TR.js @@ -1,20 +1,23 @@ -// base profile for all things TR -exports.name = 'TR'; - -const profileUtil = require('./profileUtil'); -const base = require('./base').rules; +import * as copyright from '../rules/headers/copyright.js'; +import * as githubRepo from '../rules/headers/github-repo.js'; +import * as charter from '../rules/sotd/charter.js'; +import * as pp from '../rules/sotd/pp.js'; +import * as processDocument from '../rules/sotd/process-document.js'; +import * as publish from '../rules/sotd/publish.js'; +import * as stability from '../rules/sotd/stability.js'; +import { rules as base } from './base.js'; +import { insertAfter } from './profileUtil.js'; -let rules = profileUtil.insertAfter(base, 'headers.w3c-state', [ - require('../rules/headers/github-repo'), - require('../rules/headers/copyright'), -]); +// base profile for all things TR +export const name = 'TR'; -rules = profileUtil.insertAfter(rules, 'sotd.supersedable', [ - require('../rules/sotd/stability'), - require('../rules/sotd/publish'), - require('../rules/sotd/pp'), - require('../rules/sotd/charter'), - require('../rules/sotd/process-document'), +const rulesWithAdditionalHeaderRule = insertAfter(base, 'headers.w3c-state', [ + githubRepo, + copyright, ]); -exports.rules = rules; +export const rules = insertAfter( + rulesWithAdditionalHeaderRule, + 'sotd.supersedable', + [stability, publish, pp, charter, processDocument] +); diff --git a/lib/profiles/TR/Note/DNOTE-Echidna.js b/lib/profiles/TR/Note/DNOTE-Echidna.js index f937a0fd4..31c77c47b 100644 --- a/lib/profiles/TR/Note/DNOTE-Echidna.js +++ b/lib/profiles/TR/Note/DNOTE-Echidna.js @@ -1,13 +1,12 @@ // TODO: merge all Echidna files. -exports.name = 'DNOTE-Echidna'; -const base = require('./DNOTE'); -exports.config = base.config; +import * as todaysDate from '../../../rules/echidna/todays-date.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './DNOTE.js'; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/echidna/todays-date'), -]); +export const name = 'DNOTE-Echidna'; +export const config = baseConfig; -exports.rules = rules; +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + todaysDate, +]); diff --git a/lib/profiles/TR/Note/DNOTE.js b/lib/profiles/TR/Note/DNOTE.js index a1fad9c26..e2a2bf3f3 100644 --- a/lib/profiles/TR/Note/DNOTE.js +++ b/lib/profiles/TR/Note/DNOTE.js @@ -1,18 +1,13 @@ -exports.name = 'DNOTE'; -const base = require('./note-base'); +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './note-base.js'; -// customize config -const config = { +export const name = 'DNOTE'; +export const config = { + ...baseConfig, status: 'DNOTE', longStatus: 'Group Draft Note', styleSheet: 'W3C-DNOTE', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.pp', [ - require('../../../rules/sotd/draft-stability'), -]); - -exports.rules = rules; +export const rules = insertAfter(baseRules, 'sotd.pp', [draftStability]); diff --git a/lib/profiles/TR/Note/NOTE-Echidna.js b/lib/profiles/TR/Note/NOTE-Echidna.js index 9afab841f..a6acc53d7 100644 --- a/lib/profiles/TR/Note/NOTE-Echidna.js +++ b/lib/profiles/TR/Note/NOTE-Echidna.js @@ -1,9 +1,10 @@ -exports.name = 'NOTE-Echidna'; -const base = require('./NOTE'); +import * as todaysDate from '../../../rules/echidna/todays-date.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './NOTE.js'; -exports.config = base.config; +export const name = 'NOTE-Echidna'; +export const config = baseConfig; -const profileUtil = require('../../profileUtil'); -exports.rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/echidna/todays-date'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + todaysDate, ]); diff --git a/lib/profiles/TR/Note/NOTE.js b/lib/profiles/TR/Note/NOTE.js index 6340878d0..1eb9e8282 100644 --- a/lib/profiles/TR/Note/NOTE.js +++ b/lib/profiles/TR/Note/NOTE.js @@ -1,12 +1,11 @@ -exports.name = 'NOTE'; -const base = require('./note-base'); +import { config as baseConfig, rules as baseRules } from './note-base.js'; -// customize config -const config = { +export const name = 'NOTE'; +export const config = { + ...baseConfig, status: 'NOTE', longStatus: 'Group Note', styleSheet: 'W3C-NOTE', }; -exports.config = { ...base.config, ...config }; -exports.rules = base.rules; +export const rules = baseRules; diff --git a/lib/profiles/TR/Note/STMT.js b/lib/profiles/TR/Note/STMT.js index c2aa273dd..8b1d88ffa 100644 --- a/lib/profiles/TR/Note/STMT.js +++ b/lib/profiles/TR/Note/STMT.js @@ -1,12 +1,10 @@ -exports.name = 'STMT'; -const base = require('./note-base'); +import { config as baseConfig, rules as baseRules } from './note-base.js'; -// customize config -const config = { +export const name = 'STMT'; +export const config = { + ...baseConfig, status: 'STMT', longStatus: 'Statement', styleSheet: 'W3C-STMT', }; -exports.config = { ...base.config, ...config }; - -exports.rules = base.rules; +export const rules = baseRules; diff --git a/lib/profiles/TR/Note/note-base.js b/lib/profiles/TR/Note/note-base.js index 3302dc31f..53c706a48 100644 --- a/lib/profiles/TR/Note/note-base.js +++ b/lib/profiles/TR/Note/note-base.js @@ -1,13 +1,9 @@ -exports.config = { +import * as deliverNote from '../../../rules/sotd/deliverer-note.js'; +import { insertAfter } from '../../profileUtil.js'; +import { rules as baseRules } from '../../TR.js'; + +export const config = { track: 'Note', }; -// customize rules -const base = require('../../TR'); -const profileUtil = require('../../profileUtil'); - -const rules = profileUtil.insertAfter(base.rules, 'sotd.pp', [ - require('../../../rules/sotd/deliverer-note'), -]); - -exports.rules = rules; +export const rules = insertAfter(baseRules, 'sotd.pp', [deliverNote]); diff --git a/lib/profiles/TR/Recommendation/CR-Echidna.js b/lib/profiles/TR/Recommendation/CR-Echidna.js index e8dc85c6b..ebe6bb93c 100644 --- a/lib/profiles/TR/Recommendation/CR-Echidna.js +++ b/lib/profiles/TR/Recommendation/CR-Echidna.js @@ -1,12 +1,10 @@ -exports.name = 'CR-Echidna'; -const base = require('./CR'); +import * as todaysDate from '../../../rules/echidna/todays-date.js'; +import { insertAfter } from '../../profileUtil.js'; +import { rules as baseRules } from './CR.js'; -exports.config = base.config; +export const name = 'CR-Echidna'; +export { config } from './CR.js'; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/echidna/todays-date'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + todaysDate, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/CR.js b/lib/profiles/TR/Recommendation/CR.js index b0a9fcb18..32aa4cab6 100644 --- a/lib/profiles/TR/Recommendation/CR.js +++ b/lib/profiles/TR/Recommendation/CR.js @@ -1,19 +1,19 @@ -exports.name = 'CR'; -const base = require('./recommendation-base'); +import * as candidateReviewEnd from '../../../rules/sotd/candidate-review-end.js'; +import { insertAfter } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -// customize config -const config = { +export const name = 'CR'; +export const config = { + ...baseConfig, status: 'CR', longStatus: 'Candidate Recommendation', crType: 'Snapshot', styleSheet: 'W3C-CR', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/sotd/candidate-review-end'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + candidateReviewEnd, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/CRD-Echidna.js b/lib/profiles/TR/Recommendation/CRD-Echidna.js index c65c53ba7..cb2ce2f55 100644 --- a/lib/profiles/TR/Recommendation/CRD-Echidna.js +++ b/lib/profiles/TR/Recommendation/CRD-Echidna.js @@ -1,10 +1,10 @@ -exports.name = 'CRD-Echidna'; -const base = require('./CRD'); +import * as todaysDate from '../../../rules/echidna/todays-date.js'; +import { insertAfter } from '../../profileUtil.js'; +import { rules as baseRules } from './CRD.js'; -exports.config = base.config; +export { config } from './CRD.js'; +export const name = 'CRD-Echidna'; -// customize rules -const profileUtil = require('../../profileUtil'); -exports.rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/echidna/todays-date'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + todaysDate, ]); diff --git a/lib/profiles/TR/Recommendation/CRD.js b/lib/profiles/TR/Recommendation/CRD.js index d64c4c6e5..f7df75012 100644 --- a/lib/profiles/TR/Recommendation/CRD.js +++ b/lib/profiles/TR/Recommendation/CRD.js @@ -1,19 +1,17 @@ -exports.name = 'CRD'; -const base = require('./recommendation-base'); +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import { insertAfter } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -// customize config -const config = { +export const name = 'CRD'; +export const config = { + ...baseConfig, status: 'CRD', longStatus: 'Candidate Recommendation', crType: 'Draft', styleSheet: 'W3C-CRD', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.pp', [ - require('../../../rules/sotd/draft-stability'), -]); - -exports.rules = rules; +export const rules = insertAfter(baseRules, 'sotd.pp', [draftStability]); diff --git a/lib/profiles/TR/Recommendation/DISC.js b/lib/profiles/TR/Recommendation/DISC.js index f6baf7886..982bdaf7a 100644 --- a/lib/profiles/TR/Recommendation/DISC.js +++ b/lib/profiles/TR/Recommendation/DISC.js @@ -1,20 +1,19 @@ -exports.name = 'DISC'; -const base = require('./recommendation-base'); +// customize rules +import { removeRules } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -// customize config -const config = { +export const name = 'DISC'; +export const config = { + ...baseConfig, status: 'DISC', longStatus: 'Discontinued Draft', styleSheet: 'W3C-DISC', }; -exports.config = { ...base.config, ...config }; - -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.removeRules(base.rules, [ +export const rules = removeRules(baseRules, [ 'structure.security-privacy', 'sotd.diff', ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/FPWD.js b/lib/profiles/TR/Recommendation/FPWD.js index 097b149f3..61e6709e6 100644 --- a/lib/profiles/TR/Recommendation/FPWD.js +++ b/lib/profiles/TR/Recommendation/FPWD.js @@ -1,23 +1,21 @@ -exports.name = 'FPWD'; -const base = require('./recommendation-base'); +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import { insertAfter, removeRules } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -// customize config -const config = { +export const name = 'FPWD'; +export const config = { + ...baseConfig, status: 'WD', longStatus: 'First Public Working Draft', styleSheet: 'W3C-WD', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -let rules = profileUtil.insertAfter(base.rules, 'sotd.pp', [ - require('../../../rules/sotd/draft-stability'), -]); +const rulesWithOthers = insertAfter(baseRules, 'sotd.pp', [draftStability]); -rules = profileUtil.removeRules(rules, [ +export const rules = removeRules(rulesWithOthers, [ 'structure.security-privacy', 'sotd.diff', ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/PR.js b/lib/profiles/TR/Recommendation/PR.js index 9d983cddf..6d4c99ff7 100644 --- a/lib/profiles/TR/Recommendation/PR.js +++ b/lib/profiles/TR/Recommendation/PR.js @@ -1,21 +1,24 @@ -exports.name = 'PR'; -const base = require('./recommendation-base'); +import * as acReview from '../../../rules/sotd/ac-review.js'; +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import * as newFeatures from '../../../rules/sotd/new-features.js'; +import * as reviewEnd from '../../../rules/sotd/review-end.js'; +import { insertAfter } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -// customize config -const config = { +export const name = 'PR'; +export const config = { + ...baseConfig, status: 'PR', longStatus: 'Proposed Recommendation', styleSheet: 'W3C-PR', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/sotd/ac-review'), - require('../../../rules/sotd/review-end'), - require('../../../rules/sotd/new-features'), - require('../../../rules/sotd/draft-stability'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + acReview, + reviewEnd, + newFeatures, + draftStability, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/REC-RSCND.js b/lib/profiles/TR/Recommendation/REC-RSCND.js index e9a28d263..ed887eae5 100644 --- a/lib/profiles/TR/Recommendation/REC-RSCND.js +++ b/lib/profiles/TR/Recommendation/REC-RSCND.js @@ -1,22 +1,21 @@ -exports.name = 'REC-RSCND'; -const base = require('./REC'); +import * as obslRescind from '../../../rules/sotd/obsl-rescind.js'; +import { insertAfter, removeRules } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './REC.js'; -// customize config -const config = { +export const name = 'REC-RSCND'; +export const config = { + ...baseConfig, status: 'REC', longStatus: 'Rescinded Recommendation', rescinds: true, styleSheet: 'W3C-RSCND', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -let rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/sotd/obsl-rescind'), +const rulesWithObslRescind = insertAfter(baseRules, 'sotd.process-document', [ + obslRescind, ]); -rules = profileUtil.removeRules(rules, [ +export const rules = removeRules(rulesWithObslRescind, [ 'headers.errata', 'sotd.stability', 'sotd.publish', @@ -28,5 +27,3 @@ rules = profileUtil.removeRules(rules, [ 'sotd.new-features', 'sotd.deployment', ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/REC.js b/lib/profiles/TR/Recommendation/REC.js index 455c744fb..a76b0de49 100644 --- a/lib/profiles/TR/Recommendation/REC.js +++ b/lib/profiles/TR/Recommendation/REC.js @@ -1,26 +1,31 @@ -exports.name = 'REC'; -const base = require('./recommendation-base'); +import * as errata from '../../../rules/headers/errata.js'; +import * as deployment from '../../../rules/sotd/deployment.js'; +import * as newFeatures from '../../../rules/sotd/new-features.js'; +import * as recAddition from '../../../rules/sotd/rec-addition.js'; +import * as recCommentEnd from '../../../rules/sotd/rec-comment-end.js'; +import { insertAfter, removeRules } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -// customize config -const config = { +export const name = 'REC'; +export const config = { + ...baseConfig, status: 'REC', longStatus: 'Recommendation', styleSheet: 'W3C-REC', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -let rules = profileUtil.insertAfter(base.rules, 'headers.dl', [ - require('../../../rules/headers/errata'), -]); -rules = profileUtil.insertAfter(rules, 'sotd.supersedable', [ - require('../../../rules/sotd/rec-addition'), - require('../../../rules/sotd/rec-comment-end'), - require('../../../rules/sotd/new-features'), - require('../../../rules/sotd/deployment'), -]); +const rulesWithErrata = insertAfter(baseRules, 'headers.dl', [errata]); -rules = profileUtil.removeRules(rules, ['structure.security-privacy']); +const rulesWithOthers = insertAfter(rulesWithErrata, 'sotd.supersedable', [ + recAddition, + recCommentEnd, + newFeatures, + deployment, +]); -exports.rules = rules; +export const rules = removeRules(rulesWithOthers, [ + 'structure.security-privacy', +]); diff --git a/lib/profiles/TR/Recommendation/WD-Echidna.js b/lib/profiles/TR/Recommendation/WD-Echidna.js index e9d56a7ad..a1ad8223c 100644 --- a/lib/profiles/TR/Recommendation/WD-Echidna.js +++ b/lib/profiles/TR/Recommendation/WD-Echidna.js @@ -1,11 +1,10 @@ -// Working Draft profile +import * as todaysDate from '../../../rules/echidna/todays-date.js'; +import { insertAfter } from '../../profileUtil.js'; +import { rules as baseRules } from './WD.js'; -exports.name = 'WD-Echidna'; -const base = require('./WD'); +export const name = 'WD-Echidna'; +export { config } from './WD.js'; -exports.config = base.config; - -const profileUtil = require('../../profileUtil'); -exports.rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/echidna/todays-date'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + todaysDate, ]); diff --git a/lib/profiles/TR/Recommendation/WD.js b/lib/profiles/TR/Recommendation/WD.js index 19e9aa7cb..3c3ed7224 100644 --- a/lib/profiles/TR/Recommendation/WD.js +++ b/lib/profiles/TR/Recommendation/WD.js @@ -1,20 +1,18 @@ -// Working Draft profile +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import { insertAfter } from '../../profileUtil.js'; +import { + config as baseConfig, + rules as baseRules, +} from './recommendation-base.js'; -exports.name = 'WD'; -const base = require('./recommendation-base'); - -// customize config -const config = { +export const name = 'WD'; +export const config = { + ...baseConfig, status: 'WD', longStatus: 'Working Draft', styleSheet: 'W3C-WD', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.supersedable', [ - require('../../../rules/sotd/draft-stability'), +export const rules = insertAfter(baseRules, 'sotd.supersedable', [ + draftStability, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Recommendation/recommendation-base.js b/lib/profiles/TR/Recommendation/recommendation-base.js index 9ec5fa909..268501810 100644 --- a/lib/profiles/TR/Recommendation/recommendation-base.js +++ b/lib/profiles/TR/Recommendation/recommendation-base.js @@ -1,14 +1,13 @@ -exports.config = { +import * as diff from '../../../rules/sotd/diff.js'; +import * as securityPrivacy from '../../../rules/structure/security-privacy.js'; +import { insertAfter } from '../../profileUtil.js'; +import { rules as baseRules } from '../../TR.js'; + +export const config = { track: 'Recommendation', }; -// customize rules -const base = require('../../TR'); - -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.supersedable', [ - require('../../../rules/sotd/diff'), - require('../../../rules/structure/security-privacy'), +export const rules = insertAfter(baseRules, 'sotd.supersedable', [ + diff, + securityPrivacy, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Registry/CRY.js b/lib/profiles/TR/Registry/CRY.js index c0f399301..3030bb2da 100644 --- a/lib/profiles/TR/Registry/CRY.js +++ b/lib/profiles/TR/Registry/CRY.js @@ -1,19 +1,17 @@ -exports.name = 'CRY'; -const base = require('./registry-base'); +// customize rules +import * as candidateReviewEnd from '../../../rules/sotd/candidate-review-end.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './registry-base.js'; -// customize config -const config = { +export const name = 'CRY'; +export const config = { + ...baseConfig, status: 'CRY', longStatus: 'Candidate Registry', cryType: 'Snapshot', styleSheet: 'W3C-CRY', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.process-document', [ - require('../../../rules/sotd/candidate-review-end'), +export const rules = insertAfter(baseRules, 'sotd.process-document', [ + candidateReviewEnd, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Registry/CRYD.js b/lib/profiles/TR/Registry/CRYD.js index 55309d15d..2f75af88b 100644 --- a/lib/profiles/TR/Registry/CRYD.js +++ b/lib/profiles/TR/Registry/CRYD.js @@ -1,20 +1,16 @@ -exports.name = 'CRYD'; -const base = require('./registry-base'); +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './registry-base.js'; -// customize config -const config = { +export const name = 'CRYD'; +export const config = { + ...baseConfig, status: 'CRYD', longStatus: 'Candidate Registry', cryType: 'Draft', styleSheet: 'W3C-CRYD', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); - -const rules = profileUtil.insertAfter(base.rules, 'sotd.supersedable', [ - require('../../../rules/sotd/draft-stability'), +export const rules = insertAfter(baseRules, 'sotd.supersedable', [ + draftStability, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Registry/DRY.js b/lib/profiles/TR/Registry/DRY.js index 5a48c8e2e..85cc46512 100644 --- a/lib/profiles/TR/Registry/DRY.js +++ b/lib/profiles/TR/Registry/DRY.js @@ -1,18 +1,15 @@ -exports.name = 'DRY'; -const base = require('./registry-base'); +import * as draftStability from '../../../rules/sotd/draft-stability.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './registry-base.js'; -// customize config -const config = { +export const name = 'DRY'; +export const config = { + ...baseConfig, status: 'DRY', longStatus: 'Draft Registry', styleSheet: 'W3C-DRY', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.supersedable', [ - require('../../../rules/sotd/draft-stability'), +export const rules = insertAfter(baseRules, 'sotd.supersedable', [ + draftStability, ]); - -exports.rules = rules; diff --git a/lib/profiles/TR/Registry/RY.js b/lib/profiles/TR/Registry/RY.js index 42c51d40a..9495a6d1c 100644 --- a/lib/profiles/TR/Registry/RY.js +++ b/lib/profiles/TR/Registry/RY.js @@ -1,18 +1,13 @@ -exports.name = 'RY'; -const base = require('./registry-base'); +import * as usage from '../../../rules/sotd/usage.js'; +import { insertAfter } from '../../profileUtil.js'; +import { config as baseConfig, rules as baseRules } from './registry-base.js'; -// customize config -const config = { +export const name = 'RY'; +export const config = { + ...baseConfig, status: 'RY', longStatus: 'Registry', styleSheet: 'W3C-RY', }; -exports.config = { ...base.config, ...config }; -// customize rules -const profileUtil = require('../../profileUtil'); -const rules = profileUtil.insertAfter(base.rules, 'sotd.supersedable', [ - require('../../../rules/sotd/usage'), -]); - -exports.rules = rules; +export const rules = insertAfter(baseRules, 'sotd.supersedable', [usage]); diff --git a/lib/profiles/TR/Registry/registry-base.js b/lib/profiles/TR/Registry/registry-base.js index c79b908d5..5fde85a8c 100644 --- a/lib/profiles/TR/Registry/registry-base.js +++ b/lib/profiles/TR/Registry/registry-base.js @@ -1,7 +1,5 @@ -exports.config = { +export const config = { track: 'Registry', }; -const base = require('../../TR'); - -exports.rules = base.rules; +export { rules } from '../../TR.js'; diff --git a/lib/profiles/base.js b/lib/profiles/base.js index 2db48f4c0..65b793b05 100644 --- a/lib/profiles/base.js +++ b/lib/profiles/base.js @@ -1,39 +1,62 @@ // Base profile for all W3C published documents -exports.name = 'Base'; +import * as detailsSummary from '../rules/headers/details-summary.js'; +import * as divHead from '../rules/headers/div-head.js'; +import * as dl from '../rules/headers/dl.js'; +import * as h1Title from '../rules/headers/h1-title.js'; +import * as h2Toc from '../rules/headers/h2-toc.js'; +import * as hr from '../rules/headers/hr.js'; +import * as logo from '../rules/headers/logo.js'; +import * as olToc from '../rules/headers/ol-toc.js'; +import * as secno from '../rules/headers/secno.js'; +import * as w3cState from '../rules/headers/w3c-state.js'; +import * as dateFormat from '../rules/heuristic/date-format.js'; +import * as compound from '../rules/links/compound.js'; +/* import * as internal from '../rules/links/internal.js'; */ +import * as linkchecker from '../rules/links/linkchecker.js'; +import * as reliability from '../rules/links/reliability.js'; +import * as supersedable from '../rules/sotd/supersedable.js'; +import * as canonical from '../rules/structure/canonical.js'; +import * as displayOnly from '../rules/structure/display-only.js'; +import * as h2 from '../rules/structure/h2.js'; +import * as structureName from '../rules/structure/name.js'; +import * as neutral from '../rules/structure/neutral.js'; +import * as sectionIds from '../rules/structure/section-ids.js'; +import * as backToTop from '../rules/style/back-to-top.js'; +import * as bodyTocSidebar from '../rules/style/body-toc-sidebar.js'; +import * as meta from '../rules/style/meta.js'; +import * as script from '../rules/style/script.js'; +import * as sheet from '../rules/style/sheet.js'; +import * as html from '../rules/validation/html.js'; +import * as wcag from '../rules/validation/wcag.js'; -exports.rules = [ - require('../rules/headers/div-head'), - require('../rules/headers/hr'), - require('../rules/headers/logo'), - require('../rules/headers/h1-title'), - require('../rules/headers/details-summary'), - require('../rules/headers/dl'), - require('../rules/headers/w3c-state'), - require('../rules/headers/h2-toc'), - require('../rules/headers/ol-toc'), - require('../rules/headers/secno'), - - require('../rules/style/sheet'), - require('../rules/style/meta'), - require('../rules/style/body-toc-sidebar'), - require('../rules/style/script'), - require('../rules/style/back-to-top'), - - require('../rules/sotd/supersedable'), - - require('../rules/structure/name'), - require('../rules/structure/h2'), - require('../rules/structure/canonical'), - require('../rules/structure/section-ids'), - require('../rules/structure/display-only'), - require('../rules/structure/neutral'), - - // , require('../rules/links/internal') - require('../rules/links/linkchecker'), - require('../rules/links/compound'), - require('../rules/links/reliability'), - - require('../rules/validation/html'), - require('../rules/validation/wcag'), - require('../rules/heuristic/date-format'), +export const name = 'Base'; +export const rules = [ + divHead, + hr, + logo, + h1Title, + detailsSummary, + dl, + w3cState, + h2Toc, + olToc, + secno, + sheet, + meta, + bodyTocSidebar, + script, + backToTop, + supersedable, + structureName, + h2, + canonical, + sectionIds, + displayOnly, + neutral, + linkchecker, + compound, + reliability, + html, + wcag, + dateFormat, ]; diff --git a/lib/profiles/metadata.js b/lib/profiles/metadata.js index ddf0f5d72..c94477409 100644 --- a/lib/profiles/metadata.js +++ b/lib/profiles/metadata.js @@ -1,20 +1,32 @@ /** * Pseudo-profile for metadata extraction. */ +import * as charters from '../rules/metadata/charters.js'; +import * as deliverers from '../rules/metadata/deliverers.js'; +import * as dl from '../rules/metadata/dl.js'; +import * as docDate from '../rules/metadata/docDate.js'; +import * as editorIds from '../rules/metadata/editor-ids.js'; +import * as editorNames from '../rules/metadata/editor-names.js'; +import * as errata from '../rules/metadata/errata.js'; +import * as informative from '../rules/metadata/informative.js'; +import * as patentPolicy from '../rules/metadata/patent-policy.js'; +import * as process from '../rules/metadata/process.js'; +import * as profile from '../rules/metadata/profile.js'; +import * as title from '../rules/metadata/title.js'; -exports.name = 'Metadata'; +export const name = 'Metadata'; -exports.rules = [ - require('../rules/metadata/profile'), - require('../rules/metadata/title'), - require('../rules/metadata/docDate'), - require('../rules/metadata/dl'), - require('../rules/metadata/deliverers'), - require('../rules/metadata/patent-policy'), - require('../rules/metadata/charters'), - require('../rules/metadata/editor-ids'), - require('../rules/metadata/editor-names'), - require('../rules/metadata/informative'), - require('../rules/metadata/process'), - require('../rules/metadata/errata'), +export const rules = [ + profile, + title, + docDate, + dl, + deliverers, + patentPolicy, + charters, + editorIds, + editorNames, + informative, + process, + errata, ]; diff --git a/lib/profiles/profileUtil.js b/lib/profiles/profileUtil.js index 027db1eac..0e5608b46 100644 --- a/lib/profiles/profileUtil.js +++ b/lib/profiles/profileUtil.js @@ -1,5 +1,10 @@ // take an array of rules, return a copy with new rules added after a given named anchor -exports.insertAfter = function (original, anchor, rules) { +/** + * @param original + * @param anchor + * @param rules + */ +export function insertAfter(original, anchor, rules) { rules = Array.isArray(rules) ? rules : [rules]; original = original.slice(); const index = original.map(r => r.name).indexOf(anchor); @@ -15,11 +20,15 @@ exports.insertAfter = function (original, anchor, rules) { ); }); return original; -}; +} // take an array of rules, return a copy with specified rules removed // e.g. profileUtil.removeRules(rules, "sotd.pp") -exports.removeRules = function (original, rules) { +/** + * @param original + * @param rules + */ +export function removeRules(original, rules) { rules = Array.isArray(rules) ? rules : [rules]; original = original.slice(); rules.forEach(r => { @@ -33,4 +42,4 @@ exports.removeRules = function (original, rules) { } }); return original; -}; +} diff --git a/lib/rules/echidna/todays-date.js b/lib/rules/echidna/todays-date.js index d0481938a..8404f3f7d 100644 --- a/lib/rules/echidna/todays-date.js +++ b/lib/rules/echidna/todays-date.js @@ -5,9 +5,13 @@ const self = { rule: 'dateState', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { /** * Get the timestamp of a day, regardless the time of the day. * This function creates a new `Date` to avoid modifying the original one. @@ -26,4 +30,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/headers/copyright.js b/lib/rules/headers/copyright.js index c980b18f8..d17e385a0 100644 --- a/lib/rules/headers/copyright.js +++ b/lib/rules/headers/copyright.js @@ -7,6 +7,7 @@ * 4. For "copyright-software", the url is https://www.w3.org/Consortium/Legal/copyright-software, the dated url is https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document, they are both allowed. The name in the API is "W3C Software and Document License", but the document would use text "permissive document license". * 5. For "copyright-documents", the url is https://www.w3.org/Consortium/Legal/copyright-documents. The name in the API is "W3C Document License", but the document would use text "document use". */ +import { AB, TAG } from '../../util.js'; const self = { name: 'headers.copyright', @@ -14,8 +15,6 @@ const self = { rule: 'copyright', }; -const util = require('../../util'); - // W3C Software and Document License const LICENSE_CS_TEXT = 'permissive document license'; const LICENSE_CS_URL = 'https://www.w3.org/Consortium/Legal/copyright-software'; @@ -38,14 +37,18 @@ const linksToCheckBase = { trademark: 'https://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks', }; -exports.name = self.name; +export const { name } = self; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const copyright = sr.jsDocument.querySelector('body div.head p.copyright'); if (copyright) { // Skip check if the document is only published by TAG and/or AB - const TagID = util.TAG.id; - const AbID = util.AB.id; + const TagID = TAG.id; + const AbID = AB.id; const deliverers = await sr.getDelivererIDs(); // groupIds: a list of ids without TAG or AB const groupIds = deliverers.filter( @@ -150,4 +153,4 @@ exports.check = async function (sr, done) { }); } else sr.error(self, 'not-found'); return done(); -}; +} diff --git a/lib/rules/headers/details-summary.js b/lib/rules/headers/details-summary.js index eb1fbf361..3b7cf0d51 100644 --- a/lib/rules/headers/details-summary.js +++ b/lib/rules/headers/details-summary.js @@ -6,9 +6,13 @@ const self = { rule: 'docIDFormat', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const details = sr.jsDocument.querySelector('.head details'); if (!details) { sr.error(self, 'no-details'); @@ -37,4 +41,4 @@ exports.check = function (sr, done) { } return done(); -}; +} diff --git a/lib/rules/headers/div-head.js b/lib/rules/headers/div-head.js index 2b76ba606..89b4b97b5 100644 --- a/lib/rules/headers/div-head.js +++ b/lib/rules/headers/div-head.js @@ -6,8 +6,12 @@ const self = { rule: 'divClassHead', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { sr.checkSelector('body div.head', self, done); -}; +} diff --git a/lib/rules/headers/dl.js b/lib/rules/headers/dl.js index aece43660..5b708a176 100644 --- a/lib/rules/headers/dl.js +++ b/lib/rules/headers/dl.js @@ -7,7 +7,8 @@ // #w3c-state date and this version date must match // dt for editor or author -const superagent = require('superagent'); +import superagent from 'superagent'; +import doAsync from 'doasync'; const self = { name: 'headers.dl', @@ -34,7 +35,7 @@ const editorError = { section: 'front-matter', rule: 'editorSection', }; -exports.name = self.name; +export const name = self.name; /** * Check if link and href are consistent. @@ -52,7 +53,7 @@ function checkLink({ sr, rule = self, element, linkName, mustHave = true }) { return true; } -exports.check = async function (sr, done) { +export async function check(sr, done) { const { rescinds } = sr.config; const { obsoletes } = sr.config; const { supersedes } = sr.config; @@ -188,7 +189,6 @@ exports.check = async function (sr, done) { const historyHref = linkHistory.getAttribute('href'); // Check if the history link exist let historyStatusCode; - const doAsync = require('doasync'); try { const res = await doAsync(superagent).head(historyHref); historyStatusCode = res.statusCode; @@ -373,4 +373,4 @@ exports.check = async function (sr, done) { sr.error(editorError, 'editor-not-found'); } done(); -}; +} diff --git a/lib/rules/headers/errata.js b/lib/rules/headers/errata.js index e42c5bd3c..800ef5200 100644 --- a/lib/rules/headers/errata.js +++ b/lib/rules/headers/errata.js @@ -4,9 +4,13 @@ const self = { name: 'headers.errata', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const dts = sr.extractHeaders(); // Check 'Errata:' exist, don't check any further. if (!dts.Errata) { @@ -14,4 +18,4 @@ exports.check = function (sr, done) { return done(); } return done(); -}; +} diff --git a/lib/rules/headers/github-repo.js b/lib/rules/headers/github-repo.js index 2497485bd..0b3a5fafc 100644 --- a/lib/rules/headers/github-repo.js +++ b/lib/rules/headers/github-repo.js @@ -8,9 +8,13 @@ const self = { rule: 'docIDOrder', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const dts = sr.extractHeaders(); // Check 'Feedback:' exist if (!dts.Feedback) { @@ -38,4 +42,4 @@ exports.check = function (sr, done) { if (!foundRepo) sr.error(self, 'no-repo'); done(); -}; +} diff --git a/lib/rules/headers/h1-title.js b/lib/rules/headers/h1-title.js index 3538dc127..07fa4199c 100644 --- a/lib/rules/headers/h1-title.js +++ b/lib/rules/headers/h1-title.js @@ -6,9 +6,13 @@ const self = { rule: 'title', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const title = sr.jsDocument.querySelector('head > title'); const h1 = sr.jsDocument.querySelector('body div.head h1'); if (!title || !h1) { @@ -23,4 +27,4 @@ exports.check = function (sr, done) { sr.error(self, 'not-match', { titleText, h1Text }); } done(); -}; +} diff --git a/lib/rules/headers/h2-toc.js b/lib/rules/headers/h2-toc.js index 2e282b805..69e1cb430 100644 --- a/lib/rules/headers/h2-toc.js +++ b/lib/rules/headers/h2-toc.js @@ -10,9 +10,13 @@ const self = { rule: 'toc', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const EXPECTED_HEADING = /^table\s+of\s+contents$/i; const tocNav = sr.jsDocument.querySelectorAll('nav#toc > h2'); const tocDiv = sr.jsDocument.querySelectorAll('div#toc > h2'); @@ -36,4 +40,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/headers/hr.js b/lib/rules/headers/hr.js index 2a1e3e64e..57ed46f24 100644 --- a/lib/rules/headers/hr.js +++ b/lib/rules/headers/hr.js @@ -4,9 +4,13 @@ const self = { rule: 'hrAfterCopyright', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const hasHrLastChild = sr.jsDocument.querySelectorAll('body div.head > hr:last-child') .length === 1; @@ -18,4 +22,4 @@ exports.check = function (sr, done) { sr.error(self, 'not-found'); } done(); -}; +} diff --git a/lib/rules/headers/logo.js b/lib/rules/headers/logo.js index 05ddf1c18..af5275ff1 100644 --- a/lib/rules/headers/logo.js +++ b/lib/rules/headers/logo.js @@ -4,9 +4,13 @@ const self = { rule: 'logo', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const logo = sr.jsDocument.querySelector( "body div.head a[href] > img[src][height='48'][width='72'][alt='W3C']" ); @@ -22,4 +26,4 @@ exports.check = function (sr, done) { sr.error(self, 'not-found'); } done(); -}; +} diff --git a/lib/rules/headers/memsub-copyright.js b/lib/rules/headers/memsub-copyright.js index c6e737f00..e4b21bcb9 100644 --- a/lib/rules/headers/memsub-copyright.js +++ b/lib/rules/headers/memsub-copyright.js @@ -2,9 +2,13 @@ const self = { name: 'headers.memsub-copyright', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const copyright = sr.jsDocument.querySelector('body div.head p.copyright'); if (copyright) { // , "https://www.w3.org/Consortium/Legal/copyright-documents": "document use" @@ -20,4 +24,4 @@ exports.check = function (sr, done) { if (!seen) sr.error(self, 'not-found'); } else sr.error(self, 'not-found'); done(); -}; +} diff --git a/lib/rules/headers/ol-toc.js b/lib/rules/headers/ol-toc.js index dac39eb69..692c521da 100644 --- a/lib/rules/headers/ol-toc.js +++ b/lib/rules/headers/ol-toc.js @@ -9,9 +9,13 @@ const self = { rule: 'toc', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const toc = sr.jsDocument.querySelectorAll( 'nav#toc ol.toc, div#toc ol.toc' ); @@ -21,4 +25,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/headers/secno.js b/lib/rules/headers/secno.js index 5eebf2d89..f2e66cffe 100644 --- a/lib/rules/headers/secno.js +++ b/lib/rules/headers/secno.js @@ -6,9 +6,13 @@ const self = { name: 'headers.secno', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { // TODO: once supported, use: ":is(h2, h3, h4, h5, h6) :is(bdi.secno,span.secno)" const secnos = sr.jsDocument.querySelectorAll( 'h1 span.secno, h2 span.secno, h3 span.secno, h4 span.secno, h5 span.secno, h6 span.secno, #toc span.secno,' + @@ -20,4 +24,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/headers/subm-logo.js b/lib/rules/headers/subm-logo.js index 4e18dbbb2..1b91a6d20 100644 --- a/lib/rules/headers/subm-logo.js +++ b/lib/rules/headers/subm-logo.js @@ -2,9 +2,13 @@ const self = { name: 'headers.subm-logo', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const logo = sr.jsDocument.querySelector( "body div.head a[href] > img[src][height='48'][width='211'][alt]" ); @@ -27,4 +31,4 @@ exports.check = function (sr, done) { }); } done(); -}; +} diff --git a/lib/rules/headers/w3c-state.js b/lib/rules/headers/w3c-state.js index a336e5fc6..cc96d64ea 100644 --- a/lib/rules/headers/w3c-state.js +++ b/lib/rules/headers/w3c-state.js @@ -1,4 +1,6 @@ -const rules = require('../../rules.json'); +import { importJSON } from '../../util.js'; + +const rules = importJSON('../../rules.json', import.meta.url); const self = { name: 'headers.w3c-state', @@ -6,9 +8,13 @@ const self = { rule: 'dateState', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { let profileFound = false; if (!sr.config.longStatus) return done(); @@ -62,4 +68,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/heuristic/date-format.js b/lib/rules/heuristic/date-format.js index 77c116449..8363d95f1 100644 --- a/lib/rules/heuristic/date-format.js +++ b/lib/rules/heuristic/date-format.js @@ -4,9 +4,13 @@ const self = { rule: 'datesFormat', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { // Pseudo-constants: const MONTHS = 'jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|september|oct|october|nov|november|dec|december'; @@ -46,4 +50,4 @@ exports.check = function (sr, done) { } return done(); -}; +} diff --git a/lib/rules/links/compound.js b/lib/rules/links/compound.js index c99e6d640..19c21547c 100644 --- a/lib/rules/links/compound.js +++ b/lib/rules/links/compound.js @@ -1,14 +1,18 @@ -const url = require('url'); -const sua = require('../../throttled-ua'); +import url from 'url'; +import { get } from '../../throttled-ua.js'; const self = { name: 'links.compound', }; const TIMEOUT = 10000; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { if (sr.config.validation !== 'recursive') { sr.warning(self, 'skipped'); return done(); @@ -33,8 +37,7 @@ exports.check = function (sr, done) { if (sr.config.validation === 'recursive') { const ua = `W3C-Pubrules/${sr.version}`; let isMarkupValid = false; - const req = sua - .get(markupService) + const req = get(markupService) .set('User-Agent', ua) .query({ doc: l, out: 'json' }) .on('error', err => { @@ -82,4 +85,4 @@ exports.check = function (sr, done) { } }); } else return done(); -}; +} diff --git a/lib/rules/links/internal.js b/lib/rules/links/internal.js index 5a301cb75..7d179316e 100644 --- a/lib/rules/links/internal.js +++ b/lib/rules/links/internal.js @@ -4,9 +4,13 @@ const self = { rule: 'brokenLink', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { sr.jsDocument.querySelectorAll("a[href^='#']").forEach(element => { const id = element.getAttribute('href').replace('#', ''); const escId = id.replace(/([.()#:[\]+*])/g, '\\$1'); @@ -18,4 +22,4 @@ exports.check = function (sr, done) { } }); done(); -}; +} diff --git a/lib/rules/links/linkchecker.js b/lib/rules/links/linkchecker.js index ef1c29e56..921ce5b26 100644 --- a/lib/rules/links/linkchecker.js +++ b/lib/rules/links/linkchecker.js @@ -1,5 +1,5 @@ // Check every sources(img, stylesheets, scripts) are in same folder as spec document, and they are reachable. -const puppeteer = require('puppeteer'); +import puppeteer from 'puppeteer'; const self = { name: 'links.linkchecker', @@ -26,7 +26,7 @@ const noRespondAllowList = [ 'https://www.w3.org/analytics/piwik/matomo.js', ]; -exports.name = self.name; +export const { name } = self; /** * @param url @@ -57,7 +57,11 @@ function includedByReg(url, regArray = allowList) { }); } -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { // send out warning for /nu W3C link checker. sr.warning(self, 'display', { link: sr.url }); @@ -114,4 +118,4 @@ exports.check = async function (sr, done) { await browser.close(); done(); -}; +} diff --git a/lib/rules/links/reliability.js b/lib/rules/links/reliability.js index 18d0f456b..0da069c55 100644 --- a/lib/rules/links/reliability.js +++ b/lib/rules/links/reliability.js @@ -3,7 +3,7 @@ const self = { section: 'document-body', }; -exports.name = self.name; +export const { name } = self; const unreliableServices = [ { domain: 'w3.org', path: /^\/Bugs/ }, @@ -18,7 +18,11 @@ const unreliableServices = [ // { domain: 'w3.org', path: /track(er)?\/(actions|issues|resolutions)/} ]; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { Array.prototype.some.call(sr.jsDocument.querySelectorAll('a'), element => { let url; try { @@ -49,4 +53,4 @@ exports.check = function (sr, done) { }); }); done(); -}; +} diff --git a/lib/rules/metadata/charters.js b/lib/rules/metadata/charters.js index 52c6a4c5d..3727c7b15 100644 --- a/lib/rules/metadata/charters.js +++ b/lib/rules/metadata/charters.js @@ -4,10 +4,14 @@ // 'self.name' would be 'metadata.charters' -exports.name = 'metadata.charters'; +export const name = 'metadata.charters'; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const charters = await sr.getCharters(); return done({ charters }); -}; +} diff --git a/lib/rules/metadata/deliverers.js b/lib/rules/metadata/deliverers.js index 7efac0f91..d6e8884f1 100644 --- a/lib/rules/metadata/deliverers.js +++ b/lib/rules/metadata/deliverers.js @@ -3,10 +3,14 @@ */ // 'self.name' would be 'metadata.deliverers' -exports.name = 'metadata.deliverers'; +export const name = 'metadata.deliverers'; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const ids = await sr.getDelivererIDs(); done({ delivererIDs: ids }); -}; +} diff --git a/lib/rules/metadata/dl.js b/lib/rules/metadata/dl.js index ba543f8e6..85ce91f7c 100644 --- a/lib/rules/metadata/dl.js +++ b/lib/rules/metadata/dl.js @@ -2,15 +2,21 @@ * Pseudo-rule for metadata extraction: dl. */ +import { get } from '../../throttled-ua.js'; + const latestRule = { name: 'metadata.dl', section: 'front-matter', rule: 'docIDLatestVersion', }; -exports.name = 'metadata.dl'; +export const name = 'metadata.dl'; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const dts = sr.extractHeaders(); const result = {}; let shortname; @@ -69,9 +75,8 @@ exports.check = async function (sr, done) { (month[1] ? month : `0${month[0]}`) + (day[1] ? day : `0${day[0]}`); const endpoint = `https://api.w3.org/specifications/${latestShortname}/versions/${formattedDate}`; - const sua = require('../../throttled-ua'); - const req = sua.get(endpoint).set('User-Agent', ua); + const req = get(endpoint).set('User-Agent', ua); req.query({ apikey }); req.end((err, res) => { result.updated = !(err || !res.ok); @@ -80,4 +85,4 @@ exports.check = async function (sr, done) { } else { sr.throw('[EXCEPTION] The document date could not be parsed.'); } -}; +} diff --git a/lib/rules/metadata/docDate.js b/lib/rules/metadata/docDate.js index 41cb0a966..58565d89f 100644 --- a/lib/rules/metadata/docDate.js +++ b/lib/rules/metadata/docDate.js @@ -3,9 +3,13 @@ */ // 'self.name' would be 'metadata.docDate' -exports.name = 'metadata.docDate'; +export const name = 'metadata.docDate'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const docDate = sr.getDocumentDate(); if (!docDate) { return done(); @@ -16,4 +20,4 @@ exports.check = function (sr, done) { docDate.getDate(), ].join('-'); return done({ docDate: d }); -}; +} diff --git a/lib/rules/metadata/editor-ids.js b/lib/rules/metadata/editor-ids.js index 7865e065a..24632fdaf 100644 --- a/lib/rules/metadata/editor-ids.js +++ b/lib/rules/metadata/editor-ids.js @@ -3,8 +3,12 @@ */ // 'self.name' would be 'metadata.editor-ids' -exports.name = 'metadata.editor-ids'; +export const name = 'metadata.editor-ids'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { return done({ editorIDs: sr.getEditorIDs() }); -}; +} diff --git a/lib/rules/metadata/editor-names.js b/lib/rules/metadata/editor-names.js index d2eb13b9d..7cf6aff5e 100644 --- a/lib/rules/metadata/editor-names.js +++ b/lib/rules/metadata/editor-names.js @@ -3,9 +3,13 @@ */ // 'self.name' would be 'metadata.editor-names' -exports.name = 'metadata.editor-names'; +export const name = 'metadata.editor-names'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const dts = sr.extractHeaders(); const result = []; if (dts.Editor) { @@ -18,4 +22,4 @@ exports.check = function (sr, done) { }); } return done({ editorNames: result }); -}; +} diff --git a/lib/rules/metadata/errata.js b/lib/rules/metadata/errata.js index 608a30b9f..78b819657 100644 --- a/lib/rules/metadata/errata.js +++ b/lib/rules/metadata/errata.js @@ -4,9 +4,13 @@ // 'self.name' would be 'metadata.errata' -exports.name = 'metadata.errata'; +export const name = 'metadata.errata'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const errataRegex = /errata/i; const linkElement = sr.jsDocument.querySelectorAll( 'body div.head dl + p > a' @@ -16,4 +20,4 @@ exports.check = function (sr, done) { ); if (!errata.length || !errata[0].getAttribute('href')) done(); else done({ errata: errata[0].getAttribute('href') }); -}; +} diff --git a/lib/rules/metadata/informative.js b/lib/rules/metadata/informative.js index bdb6eb472..ad0438844 100644 --- a/lib/rules/metadata/informative.js +++ b/lib/rules/metadata/informative.js @@ -3,9 +3,13 @@ */ // 'self.name' would be 'metadata.informative' -exports.name = 'metadata.informative'; +export const name = 'metadata.informative'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); const expected = /This\s+document\s+is\s+informative\s+only\./; let isInformative = false; @@ -22,4 +26,4 @@ exports.check = function (sr, done) { return done({ informative: expected.test(sotd && sotd.textContent) || isInformative, }); -}; +} diff --git a/lib/rules/metadata/patent-policy.js b/lib/rules/metadata/patent-policy.js index f04c29ff4..88d98a6a7 100644 --- a/lib/rules/metadata/patent-policy.js +++ b/lib/rules/metadata/patent-policy.js @@ -4,9 +4,13 @@ // 'self.name' would be 'metadata.patent-policy' -exports.name = 'metadata.patent-policy'; +export const name = 'metadata.patent-policy'; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const patentPolicies = await sr.getPatentPolicies(); return done({ patentPolicy: patentPolicies[0] }); -}; +} diff --git a/lib/rules/metadata/process.js b/lib/rules/metadata/process.js index fc5ecaa3b..cc465667d 100644 --- a/lib/rules/metadata/process.js +++ b/lib/rules/metadata/process.js @@ -8,9 +8,13 @@ // , rule: 'whichProcess' // }; -exports.name = 'metadata.process'; +export const name = 'metadata.process'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const processDocument = sr.jsDocument.querySelector( 'a#w3c_process_revision' ); @@ -18,4 +22,4 @@ exports.check = function (sr, done) { return done(); } return done({ process: processDocument.getAttribute('href') }); -}; +} diff --git a/lib/rules/metadata/profile.js b/lib/rules/metadata/profile.js index 486a069b0..0d04ff7bd 100644 --- a/lib/rules/metadata/profile.js +++ b/lib/rules/metadata/profile.js @@ -3,16 +3,23 @@ */ // Internal packages: -const w3cApi = require('node-w3capi'); -const rules = require('../../rules.json'); -const util = require('../../util'); +import w3cApi from 'node-w3capi'; +import { allProfiles, importJSON } from '../../util.js'; +import { sortedProfiles } from '../../views.js'; +import { check as getTitle } from './title.js'; + +const rules = importJSON('../../rules.json', import.meta.url); w3cApi.apiKey = process.env.W3C_API_KEY; // 'self.name' would be 'metadata.profile' -exports.name = 'metadata.profile'; +export const name = 'metadata.profile'; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { let matchedLength = 0; let id; let profileNode; @@ -78,7 +85,6 @@ exports.check = async function (sr, done) { } // Get 'track/rectrack' of the document based on id - const { allProfiles } = util; const profileRex = new RegExp( `SUBM|(TR/(Registry|Recommendation|Note))/(${id}).js` ); @@ -123,7 +129,6 @@ exports.check = async function (sr, done) { } assembleMeta(id, sr); } else { - const getTitle = require('./title').check; let docTitle; await getTitle(sr, result => { docTitle = result && result.title; @@ -137,7 +142,6 @@ exports.check = async function (sr, done) { 'link[href^="https://www.w3.org/StyleSheets/TR/"]' ) ) { - const { sortedProfiles } = require('../../views'); let profileList = ''; sortedProfiles.forEach(category => { profileList += `${category.name}
    `; @@ -155,4 +159,4 @@ exports.check = async function (sr, done) { ); } } -}; +} diff --git a/lib/rules/metadata/title.js b/lib/rules/metadata/title.js index 5cf23e5b7..639e58cb1 100644 --- a/lib/rules/metadata/title.js +++ b/lib/rules/metadata/title.js @@ -4,9 +4,13 @@ // 'self.name' would be 'metadata.title' -exports.name = 'metadata.title'; +export const name = 'metadata.title'; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const title = sr.jsDocument.querySelector('body div.head h1'); if (!title) { return done(); @@ -17,4 +21,4 @@ exports.check = function (sr, done) { return done({ title: sr.norm(title.textContent), }); -}; +} diff --git a/lib/rules/sotd/ac-review.js b/lib/rules/sotd/ac-review.js index a7e3ca0c3..557d4086f 100644 --- a/lib/rules/sotd/ac-review.js +++ b/lib/rules/sotd/ac-review.js @@ -2,9 +2,13 @@ const self = { name: 'sotd.ac-review', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { let found = false; @@ -19,4 +23,4 @@ exports.check = function (sr, done) { if (!found) sr.error(self, 'not-found'); } done(); -}; +} diff --git a/lib/rules/sotd/candidate-review-end.js b/lib/rules/sotd/candidate-review-end.js index 8743a591e..f79c62c74 100644 --- a/lib/rules/sotd/candidate-review-end.js +++ b/lib/rules/sotd/candidate-review-end.js @@ -4,9 +4,13 @@ const self = { rule: 'reviewEndDate', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const isEditorial = (sr.config.editorial && /^true$/i.test(sr.config.editorial)) || false; if (isEditorial) { @@ -32,4 +36,4 @@ exports.check = function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/sotd/charter.js b/lib/rules/sotd/charter.js index 50d31c1fd..427a9d94c 100644 --- a/lib/rules/sotd/charter.js +++ b/lib/rules/sotd/charter.js @@ -1,18 +1,22 @@ /** * @file This rule checks if the Group have a current charter. For IG, also check if SOTD has certain text: $charterText. */ +import { AB, TAG } from '../../util.js'; + const self = { name: 'sotd.charter', }; -exports.name = self.name; - -const util = require('../../util'); +export const { name } = self; const charterText = /The disclosure obligations of the Participants of this group are described in the charter\./; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { const deliverIds = await sr.getDelivererIDs(); @@ -23,8 +27,8 @@ exports.check = async function (sr, done) { } // Skip check if the document is only published by TAG and/or AB - const TagID = util.TAG.id; - const AbID = util.AB.id; + const TagID = TAG.id; + const AbID = AB.id; // groupIds: a list of ids without TAG or AB const groupIds = deliverIds.filter( deliverer => ![TagID, AbID].includes(deliverer) @@ -70,4 +74,4 @@ exports.check = async function (sr, done) { return done(); } -}; +} diff --git a/lib/rules/sotd/deliverer-note.js b/lib/rules/sotd/deliverer-note.js index 27cc28629..c85f00b2b 100644 --- a/lib/rules/sotd/deliverer-note.js +++ b/lib/rules/sotd/deliverer-note.js @@ -4,11 +4,15 @@ const self = { rule: 'delivererID', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const deliverers = sr.getDataDelivererIDs(); if (deliverers.length === 0) sr.error(self, 'not-found'); done(); -}; +} diff --git a/lib/rules/sotd/deployment.js b/lib/rules/sotd/deployment.js index 8c2f703d0..0dd2b9efc 100644 --- a/lib/rules/sotd/deployment.js +++ b/lib/rules/sotd/deployment.js @@ -5,9 +5,13 @@ const self = { rule: 'deployment', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { @@ -24,4 +28,4 @@ exports.check = function (sr, done) { } } return done(); -}; +} diff --git a/lib/rules/sotd/diff.js b/lib/rules/sotd/diff.js index 526f2dc24..50b177449 100644 --- a/lib/rules/sotd/diff.js +++ b/lib/rules/sotd/diff.js @@ -4,9 +4,13 @@ const self = { rule: 'changesList', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { sr.info(self, 'note'); return done(); -}; +} diff --git a/lib/rules/sotd/draft-stability.js b/lib/rules/sotd/draft-stability.js index 3950fb88d..ebb00ca81 100644 --- a/lib/rules/sotd/draft-stability.js +++ b/lib/rules/sotd/draft-stability.js @@ -5,9 +5,13 @@ const self = { rule: 'draftStability', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); const { crType, cryType } = sr.config; const STABILITY = @@ -37,4 +41,4 @@ exports.check = function (sr, done) { }); } done(); -}; +} diff --git a/lib/rules/sotd/new-features.js b/lib/rules/sotd/new-features.js index c449f58a6..7d56e33ab 100644 --- a/lib/rules/sotd/new-features.js +++ b/lib/rules/sotd/new-features.js @@ -4,9 +4,13 @@ const self = { rule: 'newFeatures', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); const docType = sr.config.status === 'PR' ? 'specification' : 'Recommendation'; @@ -29,4 +33,4 @@ exports.check = function (sr, done) { sr.warning(self, 'no-warning'); } done(); -}; +} diff --git a/lib/rules/sotd/obsl-rescind.js b/lib/rules/sotd/obsl-rescind.js index bcfe6ee22..cdc8161cd 100644 --- a/lib/rules/sotd/obsl-rescind.js +++ b/lib/rules/sotd/obsl-rescind.js @@ -4,7 +4,7 @@ // replacement or alternative technologies, please refer to the explanation of // Obsoleting and Rescinding W3C Specifications.

    -const util = require('../../util'); +import { filter } from '../../util.js'; /** * @param candidates @@ -42,13 +42,17 @@ const self = { rule: 'rescindsRationale', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { const rationale = - findRscndRationale(util.filter(sotd, 'p'), sr) || + findRscndRationale(filter(sotd, 'p'), sr) || findRscndRationale(sotd.querySelectorAll('p'), sr); if (!rationale) { sr.error(self, 'no-rationale'); @@ -66,4 +70,4 @@ exports.check = function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/sotd/pp.js b/lib/rules/sotd/pp.js index fad7f5b79..b505e45de 100644 --- a/lib/rules/sotd/pp.js +++ b/lib/rules/sotd/pp.js @@ -1,4 +1,4 @@ -const util = require('../../util'); +import { filter } from '../../util.js'; const self = { name: 'sotd.pp', @@ -97,9 +97,13 @@ function findPP(candidates, sr, isIGDeliverable) { return { pp, expected }; } -exports.name = self.name; +export const { name } = self; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const groups = await sr.getDelivererGroups(); // Check if the document is published by WGs only. If IG/AB/TAG(s) are involved, the document cannot be on REC-track and should have a sentence meaning 'pp does not apply'. const publishedByWgOnly = groups.every(group => group.groupType === 'wg'); @@ -156,7 +160,7 @@ exports.check = async function (sr, done) { } const { pp, expected } = findPP( - util.filter(sotd, 'p').concat(...sotd.querySelectorAll('p')), + filter(sotd, 'p').concat(...sotd.querySelectorAll('p')), sr, patentPolicies[0] ); @@ -246,4 +250,4 @@ exports.check = async function (sr, done) { }); return done(); } -}; +} diff --git a/lib/rules/sotd/process-document.js b/lib/rules/sotd/process-document.js index 82a196651..8975cb0a2 100644 --- a/lib/rules/sotd/process-document.js +++ b/lib/rules/sotd/process-document.js @@ -4,9 +4,13 @@ const self = { rule: 'whichProcess', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); const docDate = sr.getDocumentDate(); const BOILERPLATE_PREFIX = 'This document is governed by the '; @@ -51,4 +55,4 @@ exports.check = function (sr, done) { if (!found) sr.error(self, 'not-found', { process: proc }); } done(); -}; +} diff --git a/lib/rules/sotd/publish.js b/lib/rules/sotd/publish.js index df6bddce8..88eec070b 100644 --- a/lib/rules/sotd/publish.js +++ b/lib/rules/sotd/publish.js @@ -4,9 +4,13 @@ const self = { rule: 'publish', }; -exports.name = self.name; +export const { name } = self; -exports.check = async function (sr, done) { +/** + * @param sr + * @param done + */ +export async function check(sr, done) { const sotd = sr.getSotDSection(); const { crType, cryType } = sr.config; let docType = sr.config.longStatus; @@ -114,4 +118,4 @@ exports.check = async function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/sotd/rec-addition.js b/lib/rules/sotd/rec-addition.js index d17e59324..17bb2d4ea 100644 --- a/lib/rules/sotd/rec-addition.js +++ b/lib/rules/sotd/rec-addition.js @@ -5,7 +5,7 @@ const self = { rule: 'recAddition', }; -exports.name = self.name; +export const { name } = self; const P_CORRECTION = 'Proposed correction(s)? are marked in the document.'; const P_ADDITION = 'Proposed addition(s)? are marked in the document.'; @@ -45,7 +45,11 @@ function checkSection(sr, options) { }); } -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { const recType = sr.getRecMetadata({}); @@ -91,4 +95,4 @@ exports.check = function (sr, done) { }); } return done(); -}; +} diff --git a/lib/rules/sotd/rec-comment-end.js b/lib/rules/sotd/rec-comment-end.js index b643d06cf..42e701059 100644 --- a/lib/rules/sotd/rec-comment-end.js +++ b/lib/rules/sotd/rec-comment-end.js @@ -4,9 +4,13 @@ const self = { rule: 'commentEnd', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { const recType = sr.getRecMetadata({}); @@ -49,4 +53,4 @@ exports.check = function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/sotd/review-end.js b/lib/rules/sotd/review-end.js index 898291bfc..8e4a55dfc 100644 --- a/lib/rules/sotd/review-end.js +++ b/lib/rules/sotd/review-end.js @@ -2,9 +2,13 @@ const self = { name: 'sotd.review-end', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { const txt = sr.norm(sotd.textContent); @@ -23,4 +27,4 @@ exports.check = function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/sotd/stability.js b/lib/rules/sotd/stability.js index 786f111c2..6fb750ad4 100644 --- a/lib/rules/sotd/stability.js +++ b/lib/rules/sotd/stability.js @@ -1,7 +1,7 @@ // SotD // stability warning //

    Publication as a Working Draft does not imply endorsement by W3C and its Members.

    -const util = require('../../util'); +import { filter } from '../../util.js'; /** * @param candidates @@ -71,9 +71,13 @@ const self = { rule: 'stability', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { if (sr.config.status === 'REC') { @@ -82,7 +86,7 @@ exports.check = function (sr, done) { const rex = new RegExp(wanted); if (!rex.test(txt)) sr.error(self, 'no-rec-review'); } else { - const paragraph = util.filter(sotd, 'p'); + const paragraph = filter(sotd, 'p'); const { sw, expected } = findSW( paragraph.length ? paragraph : sotd.querySelectorAll('p'), sr @@ -125,4 +129,4 @@ exports.check = function (sr, done) { } } return done(); -}; +} diff --git a/lib/rules/sotd/submission.js b/lib/rules/sotd/submission.js index 390521ee0..d5ce8d52f 100644 --- a/lib/rules/sotd/submission.js +++ b/lib/rules/sotd/submission.js @@ -1,4 +1,4 @@ -const util = require('../../util'); +import { filter } from '../../util.js'; const self = { name: 'sotd.submission', @@ -6,7 +6,7 @@ const self = { rule: 'boilerplateSUBM', }; -exports.name = self.name; +export const { name } = self; /** * @param candidates @@ -36,11 +36,15 @@ function findSubmText(candidates, sr) { return st; } -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { const st = - findSubmText(util.filter(sotd, 'p'), sr) || + findSubmText(filter(sotd, 'p'), sr) || findSubmText(sotd.querySelectorAll('p'), sr); if (!st) { sr.error(self, 'no-submission-text'); @@ -123,4 +127,4 @@ exports.check = function (sr, done) { if (!foundComment) sr.error(self, 'no-tc-link'); } done(); -}; +} diff --git a/lib/rules/sotd/supersedable.js b/lib/rules/sotd/supersedable.js index 755af0dad..2912d0bdc 100644 --- a/lib/rules/sotd/supersedable.js +++ b/lib/rules/sotd/supersedable.js @@ -5,7 +5,7 @@ // latest revision of this technical report can be found in the // W3C technical reports index at https://www.w3.org/TR/.

    -const util = require('../../util'); +import { filter } from '../../util.js'; const self = { name: 'sotd.supersedable', @@ -13,13 +13,17 @@ const self = { rule: 'boilerplateTRDoc', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { let em; - Array.prototype.some.call(util.filter(sotd, 'p'), paragraph => { + Array.prototype.some.call(filter(sotd, 'p'), paragraph => { if (paragraph.querySelector('em')) { em = paragraph.querySelector('em'); return true; @@ -41,4 +45,4 @@ exports.check = function (sr, done) { if (!a || !a.length) sr.error(self, 'no-sotd-tr'); } done(); -}; +} diff --git a/lib/rules/sotd/usage.js b/lib/rules/sotd/usage.js index 49dfda65f..ea8782883 100644 --- a/lib/rules/sotd/usage.js +++ b/lib/rules/sotd/usage.js @@ -5,9 +5,13 @@ const self = { rule: 'usage', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const sotd = sr.getSotDSection(); if (sotd) { @@ -23,4 +27,4 @@ exports.check = function (sr, done) { } } return done(); -}; +} diff --git a/lib/rules/structure/canonical.js b/lib/rules/structure/canonical.js index 79960ed9d..eff76d921 100644 --- a/lib/rules/structure/canonical.js +++ b/lib/rules/structure/canonical.js @@ -4,9 +4,13 @@ const self = { rule: 'canonical', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const checkCanonical = function () { const lnk = sr.jsDocument.querySelector('head > link[rel=canonical]'); if (!lnk || !lnk.getAttribute('href')) sr.error(self, 'not-found'); @@ -21,4 +25,4 @@ exports.check = function (sr, done) { }); done(); -}; +} diff --git a/lib/rules/structure/display-only.js b/lib/rules/structure/display-only.js index 4cf4da10a..cc90e01db 100644 --- a/lib/rules/structure/display-only.js +++ b/lib/rules/structure/display-only.js @@ -1,18 +1,20 @@ -const rule = 'structure.display-only'; +export const name = 'structure.display-only'; -exports.name = rule; - -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { // to pass test/l10n.js, who only recognise message in single line, so prettier is disabled for this file if (sr.config.status !== 'DISC') - sr.info({ name: rule, section: 'document-status', rule: 'customParagraph' }, 'customised-paragraph'); + sr.info({ name, section: 'document-status', rule: 'customParagraph' }, 'customised-paragraph'); - sr.info({ name: rule, section: 'document-status', rule: 'knownDisclosureNumber',}, 'known-disclosures'); - sr.info({ name: rule }, 'normative-representation'); - sr.info({ name: rule }, 'visual-style'); - sr.info({ name: rule }, 'alt-representation'); - sr.info({ name: rule }, 'special-box-markup'); - sr.info({ name: rule }, 'index-list-tables'); - sr.info({ name: rule }, 'fit-in-a4'); + sr.info({ name, section: 'document-status', rule: 'knownDisclosureNumber',}, 'known-disclosures'); + sr.info({ name }, 'normative-representation'); + sr.info({ name }, 'visual-style'); + sr.info({ name }, 'alt-representation'); + sr.info({ name }, 'special-box-markup'); + sr.info({ name }, 'index-list-tables'); + sr.info({ name }, 'fit-in-a4'); done(); -}; +} diff --git a/lib/rules/structure/h2.js b/lib/rules/structure/h2.js index 3cbf44ea6..e874affae 100644 --- a/lib/rules/structure/h2.js +++ b/lib/rules/structure/h2.js @@ -1,23 +1,26 @@ -const rule = 'structure.h2'; +export const name = 'structure.h2'; const abstract = { - name: rule, + name, section: 'front-matter', // @TODO: is there a better rule for this one? rule: 'divClassHead', }; const sotd = { - name: rule, + name, section: 'document-status', rule: 'sotd', }; const toc = { - name: rule, + name, section: 'navigation', rule: 'toc', }; -exports.name = rule; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const h2s = []; const excludeH2 = sr.jsDocument.querySelectorAll('.head h2'); sr.jsDocument.querySelectorAll('h2').forEach(h2 => { @@ -32,4 +35,4 @@ exports.check = function (sr, done) { if (!/^Table [Oo]f [Cc]ontents$/.test(h2s[2])) sr.error(toc, 'toc', { was: h2s[2] }); done(); -}; +} diff --git a/lib/rules/structure/name.js b/lib/rules/structure/name.js index 4c91f4f12..0bfa9d5e1 100644 --- a/lib/rules/structure/name.js +++ b/lib/rules/structure/name.js @@ -1,19 +1,24 @@ +import superagent from 'superagent'; + const self = { name: 'structure.name', section: 'compound', rule: 'compoundOverview', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { // Pseudo-constants: const EXPECTED_NAME = /\/Overview\.html$/; const OVERVIEW = 'Overview.html'; const ALTERNATIVE_ENDING = /\/$/; const FILE_NAME = /[^/]+$/; - const superagent = require('superagent'); let fileName; if (!sr || !sr.url || EXPECTED_NAME.test(sr.url)) { @@ -47,4 +52,4 @@ exports.check = function (sr, done) { return done(); }); }); -}; +} diff --git a/lib/rules/structure/neutral.js b/lib/rules/structure/neutral.js index e4a66e4bc..51f627b8d 100644 --- a/lib/rules/structure/neutral.js +++ b/lib/rules/structure/neutral.js @@ -1,7 +1,9 @@ +import { importJSON } from '../../util.js'; + /** * @file make sure specification use neutral words. */ -const badterms = require('../../../public/badterms.json'); +const badterms = importJSON('../../../public/badterms.json', import.meta.url); const self = { name: 'structure.neutral', @@ -16,9 +18,13 @@ badterms.forEach(item => { } }); -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const blocklistReg = new RegExp(`\\b${blocklist.join('\\b|\\b')}\\b`, 'ig'); const unneutralList = []; // Use a cloned body instead of the original one, prevent '.remove()' side effects. @@ -46,4 +52,4 @@ exports.check = function (sr, done) { sr.warning(self, 'neutral', { words: unneutralList.join('", "') }); } done(); -}; +} diff --git a/lib/rules/structure/section-ids.js b/lib/rules/structure/section-ids.js index 92a57d313..3deb00ab9 100644 --- a/lib/rules/structure/section-ids.js +++ b/lib/rules/structure/section-ids.js @@ -4,9 +4,13 @@ const self = { rule: 'headingWithoutID', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const headers = sr.jsDocument.querySelectorAll('h2, h3, h4, h5, h6'); const ignoreH3 = sr.jsDocument.querySelector('.head>h1+h2+h3'); @@ -43,4 +47,4 @@ exports.check = function (sr, done) { return true; }); done(); -}; +} diff --git a/lib/rules/structure/security-privacy.js b/lib/rules/structure/security-privacy.js index e7af60527..38c34ed51 100644 --- a/lib/rules/structure/security-privacy.js +++ b/lib/rules/structure/security-privacy.js @@ -4,9 +4,13 @@ const self = { rule: 'securityAndPrivacy', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { let security = false; let privacy = false; @@ -30,4 +34,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/style/back-to-top.js b/lib/rules/style/back-to-top.js index f61f2e4ab..ddc2b3685 100644 --- a/lib/rules/style/back-to-top.js +++ b/lib/rules/style/back-to-top.js @@ -6,9 +6,13 @@ const self = { name: 'style.back-to-top', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const candidates = sr.jsDocument.querySelectorAll( "body p#back-to-top[role='navigation'] a[href='#title']" ); @@ -18,4 +22,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/style/body-toc-sidebar.js b/lib/rules/style/body-toc-sidebar.js index 757e8f751..b87376fa7 100644 --- a/lib/rules/style/body-toc-sidebar.js +++ b/lib/rules/style/body-toc-sidebar.js @@ -2,9 +2,13 @@ const self = { name: 'style.body-toc-sidebar', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { try { const body = sr.jsDocument.querySelector('body'); if (body && body.classList.contains('toc-sidebar')) @@ -13,4 +17,4 @@ exports.check = function (sr, done) { sr.error(self, 'selector-fail'); } done(); -}; +} diff --git a/lib/rules/style/meta.js b/lib/rules/style/meta.js index fc822ea09..3f5f998d7 100644 --- a/lib/rules/style/meta.js +++ b/lib/rules/style/meta.js @@ -2,6 +2,7 @@ * Check the presence of this meta tag in the head of the page: * <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> */ +import mvp from 'metaviewport-parser'; const self = { name: 'style.meta', @@ -9,13 +10,16 @@ const self = { rule: 'viewport', }; -exports.name = self.name; - -const mvp = require('metaviewport-parser'); +export const { name } = self; const width = /^device-width$/i; const shrinkToFit = /^no$/i; -exports.check = function (sr, done) { + +/** + * @param sr + * @param done + */ +export function check(sr, done) { const meta = sr.jsDocument.querySelectorAll( "head > meta[name='viewport'][content]" ); @@ -41,4 +45,4 @@ exports.check = function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/style/script.js b/lib/rules/style/script.js index 0846a93e3..3dc5f56df 100644 --- a/lib/rules/style/script.js +++ b/lib/rules/style/script.js @@ -6,9 +6,13 @@ const self = { name: 'style.script', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { const PATTERN_SCRIPT = /^(https?:)?\/\/(www\.)?w3\.org\/scripts\/tr\/2021\/fixup\.js$/i; @@ -26,4 +30,4 @@ exports.check = function (sr, done) { } done(); -}; +} diff --git a/lib/rules/style/sheet.js b/lib/rules/style/sheet.js index 0247d1190..f15f0204d 100644 --- a/lib/rules/style/sheet.js +++ b/lib/rules/style/sheet.js @@ -1,20 +1,23 @@ -const util = require('../../util'); +import { nextAll } from '../../util.js'; -const rule = 'style.sheet'; +export const name = 'style.sheet'; const section = 'metadata'; const missing = { - name: rule, + name, section, rule: 'goodStylesheet', }; const notLast = { - name: rule, + name, section, rule: 'lastStylesheet', }; -exports.name = rule; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { if (!sr.config.styleSheet) return done(); const url = `https://www.w3.org/StyleSheets/TR/2021/${sr.config.styleSheet}`; const dark = 'https://www.w3.org/StyleSheets/TR/2021/dark'; @@ -25,7 +28,7 @@ exports.check = function (sr, done) { const lnk = sr.jsDocument.querySelectorAll(stylesheetLinks.join(', ')); if (!lnk.length) sr.error(missing, 'not-found', { url }); else { - const siblings = util.nextAll(lnk[0], 'link[rel=stylesheet], style'); + const siblings = nextAll(lnk[0], 'link[rel=stylesheet], style'); if ( siblings.length || (siblings.length === 1 && @@ -36,4 +39,4 @@ exports.check = function (sr, done) { } } done(); -}; +} diff --git a/lib/rules/validation/html.js b/lib/rules/validation/html.js index 2a0e16098..923d3dc88 100644 --- a/lib/rules/validation/html.js +++ b/lib/rules/validation/html.js @@ -1,4 +1,4 @@ -const sua = require('../../throttled-ua'); +import { get, post } from '../../throttled-ua.js'; const self = { name: 'validation.html', @@ -7,9 +7,13 @@ const self = { }; const TIMEOUT = 10000; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { let service = null; if (sr.config.htmlValidator !== undefined) { service = sr.config.htmlValidator; @@ -27,11 +31,10 @@ exports.check = function (sr, done) { let req; const ua = `W3C-Pubrules/${sr.version}`; if (sr.url) { - req = sua.get(service).set('User-Agent', ua); + req = get(service).set('User-Agent', ua); req.query({ doc: sr.url, out: 'json' }); } else { - req = sua - .post(service) + req = post(service) .set('User-Agent', ua) .set('Content-Type', 'text/html') .send(sr.source) @@ -102,4 +105,4 @@ exports.check = function (sr, done) { } done(); }); -}; +} diff --git a/lib/rules/validation/wcag.js b/lib/rules/validation/wcag.js index ad35497cd..d5c0f8e3a 100644 --- a/lib/rules/validation/wcag.js +++ b/lib/rules/validation/wcag.js @@ -4,9 +4,13 @@ const self = { rule: 'wcag', }; -exports.name = self.name; +export const { name } = self; -exports.check = function (sr, done) { +/** + * @param sr + * @param done + */ +export function check(sr, done) { sr.info(self, 'tools'); return done(); -}; +} diff --git a/lib/sink.js b/lib/sink.js index 2fc33d250..cbe37750d 100644 --- a/lib/sink.js +++ b/lib/sink.js @@ -3,8 +3,9 @@ */ // Native packages: -const util = require('util'); -const events = require('events'); +import events from 'events'; +import util from 'util'; + /** * Build a generic event handler that can be used by Specberus. * @@ -14,7 +15,7 @@ const events = require('events'); * @param {Function} inf - function to call in case of informative message. */ -const Sink = function (error, done, warn, inf) { +export const Sink = function (error, done, warn, inf) { this.ok = 0; this.errors = []; this.warnings = []; @@ -49,5 +50,3 @@ const Sink = function (error, done, warn, inf) { }; util.inherits(Sink, events.EventEmitter); - -exports.Sink = Sink; diff --git a/lib/throttled-ua.js b/lib/throttled-ua.js index aa8d78aaa..70a263ab7 100644 --- a/lib/throttled-ua.js +++ b/lib/throttled-ua.js @@ -1,4 +1,4 @@ -const sua = require('superagent'); +import sua from 'superagent'; const delay = 1000; let lastCall = Date.now() - delay * 2; @@ -26,7 +26,7 @@ function fixEnd(req) { // return fixEnd(req); // }; -exports.get = process.env.NO_THROTTLE +export const get = process.env.NO_THROTTLE ? sua.get : function () { // eslint-disable-next-line prefer-spread, prefer-rest-params @@ -34,7 +34,7 @@ exports.get = process.env.NO_THROTTLE return fixEnd(req); }; -exports.post = process.env.NO_THROTTLE +export const post = process.env.NO_THROTTLE ? sua.post : function () { // eslint-disable-next-line prefer-spread, prefer-rest-params diff --git a/lib/util.js b/lib/util.js index d93f0b358..f816a4c9d 100644 --- a/lib/util.js +++ b/lib/util.js @@ -2,11 +2,23 @@ * Miscellaneous utilities. */ -const fs = require('fs'); +import fs from 'fs'; +import { dirname, resolve } from 'path'; +import { fileURLToPath } from 'url'; + +// eslint-disable-next-line no-underscore-dangle +const __dirname = dirname(fileURLToPath(import.meta.url)); const filesTR = fs.readdirSync(`${__dirname}/profiles/TR/`); const filesSUBM = fs.readdirSync(`${__dirname}/profiles/SUBM/`); +export const importJSON = (relativeTo, importURL) => { + const dir = dirname(fileURLToPath(importURL)); + const pathname = resolve(dir, relativeTo); + + return JSON.parse(fs.readFileSync(pathname).toString()); +}; + /** * Build a JSON result (of validation, metadata extraction, etc). * @@ -16,7 +28,7 @@ const filesSUBM = fs.readdirSync(`${__dirname}/profiles/SUBM/`); * @param {object} metadata - dictionary with some found metadata. */ -const buildJSONresult = function (err, warn, inf, metadata) { +export const buildJSONresult = function (err, warn, inf, metadata) { return { success: err.length === 0, errors: err, @@ -26,6 +38,22 @@ const buildJSONresult = function (err, warn, inf, metadata) { }; }; +// Get rules of each profile +let TRProfiles = []; +filesTR.forEach(track => { + if (!track.startsWith('.')) { + const profileNames = fs + .readdirSync(`${__dirname}/profiles/TR/${track}/`) + .map(profileName => `${track}/${profileName}`); + TRProfiles = [...TRProfiles, ...profileNames]; + } +}); + +export const allProfiles = [ + ...TRProfiles.map(x => `TR/${x}`), + ...filesSUBM.map(x => `SUBM/${x}`), +]; + /** * Build a function that builds an “options” object based on certain parameters. * @@ -51,7 +79,7 @@ const buildProcessParamsFunction = function () { * @throws {Error} if there is an error in the parameters. */ - return function (params, base, constraints) { + return async function (params, base, constraints) { const result = base ? JSON.parse(JSON.stringify(base)) : {}; let originFound = false; // eslint-disable-next-line no-restricted-syntax @@ -75,13 +103,15 @@ const buildProcessParamsFunction = function () { throw new Error(`Parameter “${p}” is used more than once`); else if (typeof params[p] === 'string') { const subPath = `/${params[p]}.js`; - const profilePath = this.allProfiles.find(p => + const profilePath = allProfiles.find(p => p.endsWith(subPath) ); if (profilePath) - // eslint-disable-next-line import/no-dynamic-require - result[p] = require(`../lib/profiles/${profilePath}`); + // eslint-disable-next-line + result[p] = await import( + `../lib/profiles/${profilePath}` + ); else if (params[p] === 'auto') result[p] = 'auto'; else throw new Error(`Unknown profile “${params[p]}”`); } else result[p] = params[p]; @@ -142,24 +172,7 @@ const buildProcessParamsFunction = function () { }; }; -// Get rules of each profile -let TRProfiles = []; -filesTR.forEach(track => { - if (!track.startsWith('.')) { - const profileNames = fs - .readdirSync(`${__dirname}/profiles/TR/${track}/`) - .map(profileName => `${track}/${profileName}`); - TRProfiles = [...TRProfiles, ...profileNames]; - } -}); - -const allProfiles = [ - ...TRProfiles.map(x => `TR/${x}`), - ...filesSUBM.map(x => `SUBM/${x}`), -]; -exports.allProfiles = allProfiles; - -const nextUntil = function (elem, selector, filter) { +export const nextUntil = function (elem, selector, filter) { const siblings = []; elem = elem.nextElementSibling; while (elem) { @@ -174,7 +187,7 @@ const nextUntil = function (elem, selector, filter) { return siblings; }; -const nextAll = function (elem, selector, filter) { +export const nextAll = function (elem, selector, filter) { const siblings = []; elem = elem.nextElementSibling; while (elem) { @@ -190,7 +203,7 @@ const nextAll = function (elem, selector, filter) { return siblings; }; -const next = function (elem, selector) { +export const next = function (elem, selector) { elem = elem.nextElementSibling; while (elem) { if (elem.matches(selector)) { @@ -200,7 +213,7 @@ const next = function (elem, selector) { } }; -const filter = function (elements, tagName) { +export const filter = function (elements, tagName) { if (!elements || !elements.length) return []; return Array.prototype.filter.call( elements, @@ -208,15 +221,11 @@ const filter = function (elements, tagName) { ); }; -exports.buildJSONresult = buildJSONresult; -exports.processParams = buildProcessParamsFunction(); -exports.nextUntil = nextUntil; -exports.filter = filter; -exports.next = next; -exports.nextAll = nextAll; -exports.TAG = { id: 34270, type: 'other' }; -exports.AB = { id: 7756, type: 'other' }; -exports.REC_TEXT = { +export const processParams = buildProcessParamsFunction(); +export const TAG = { id: 34270, type: 'other' }; +export const AB = { id: 7756, type: 'other' }; + +export const REC_TEXT = { SOTD_P_COR: 'It includes proposed correction(s)?.', SOTD_P_ADD: 'It includes proposed addition(s)?, introducing new feature(s)? since the previous Recommendation.', diff --git a/lib/validator.js b/lib/validator.js index 80c9a2fb7..17c147e0b 100644 --- a/lib/validator.js +++ b/lib/validator.js @@ -5,17 +5,27 @@ * https://services.w3.org/xslt?xmlfile=https://www.w3.org/2005/07/13-pubrules-src.html&xslfile=https://www.w3.org/2005/07/13-pubrules-compare.xsl */ -const { JSDOM } = require('jsdom'); -const fs = require('fs'); -const w3cApi = require('node-w3capi'); -const sua = require('./throttled-ua'); -const { version } = require('../package.json'); -const { Exceptions } = require('./exceptions'); -const profileMetadata = require('./profiles/metadata'); -const util = require('./util'); -const l10n = require('./l10n'); - -l10n.setLanguage('en_GB'); +import fs from 'fs'; +import { JSDOM } from 'jsdom'; +import w3cApi from 'node-w3capi'; +import { Exceptions } from './exceptions.js'; +import { assembleData, setLanguage } from './l10n.js'; +import * as profileMetadata from './profiles/metadata.js'; +import { get } from './throttled-ua.js'; +import { + AB, + buildJSONresult, + importJSON, + nextUntil, + processParams, + REC_TEXT, + TAG, +} from './util.js'; + +const { rules } = profileMetadata; +const { version } = importJSON('../package.json', import.meta.url); + +setLanguage('en_GB'); w3cApi.apiKey = process.env.W3C_API_KEY; const Specberus = function (apiKey = process.env.W3C_API_KEY) { @@ -76,9 +86,9 @@ Specberus.prototype.extractMetadata = function (options) { if (err) return self.throw(err); self.jsDocument = jsDocument; self.sink.emit('start-all', profileMetadata); - const total = (profileMetadata.rules || []).length; + const total = (rules || []).length; let done = 0; - profileMetadata.rules.forEach(rule => { + rules.forEach(rule => { try { rule.check( self, @@ -93,7 +103,7 @@ Specberus.prototype.extractMetadata = function (options) { if (done === total) self.sink.emit( 'end-all', - util.buildJSONresult( + buildJSONresult( errors, warnings, infos, @@ -136,57 +146,58 @@ Specberus.prototype.validate = function (options) { if (!options.profile) return this.throw('Without a profile there is nothing to check.'); const { profile } = options; - try { - self.config = util.processParams(options, profile.config); - } catch (err) { - return this.throw(err.toString()); - } - self.config.lang = 'en_GB'; - const errors = []; - const warnings = []; - const infos = []; - self.sink.on('err', (...data) => { - errors.push(Object.assign({}, ...data)); - }); - self.sink.on('warning', (...data) => { - warnings.push(Object.assign({}, ...data)); - }); - self.sink.on('info', (...data) => { - infos.push(Object.assign({}, ...data)); - }); - const doValidation = function (err, jsDocument) { - if (err) return self.throw(err); - self.jsDocument = jsDocument; - self.sink.emit('start-all', profile.name); - const total = (profile.rules || []).length; - let done = 0; - profile.rules.forEach(rule => { - // XXX - // I would like to catch all exceptions here, but this derails the testing - // infrastructure which also uses exceptions that it expects aren't caught - rule.check( - self, - function () { - done += 1; - self.sink.emit('done', this.name); - if (done === total) - self.sink.emit( - 'end-all', - util.buildJSONresult(errors, warnings, infos, {}) - ); - }.bind(rule) - ); - }); - }; - if (options.url) this.loadURL(options.url, doValidation); - else if (options.source) this.loadSource(options.source, doValidation); - else if (options.file) this.loadFile(options.file, doValidation); - else if (options.document) - this.loadDocument(options.document, doValidation); - else - return this.throw( - 'At least one of url, source, file, or document must be specified.' - ); + processParams(options, profile.config) + .then(config => { + self.config = config; + self.config.lang = 'en_GB'; + const errors = []; + const warnings = []; + const infos = []; + self.sink.on('err', (...data) => { + errors.push(Object.assign({}, ...data)); + }); + self.sink.on('warning', (...data) => { + warnings.push(Object.assign({}, ...data)); + }); + self.sink.on('info', (...data) => { + infos.push(Object.assign({}, ...data)); + }); + const doValidation = function (err, jsDocument) { + if (err) return self.throw(err); + self.jsDocument = jsDocument; + self.sink.emit('start-all', profile.name); + const total = (profile.rules || []).length; + let done = 0; + profile.rules.forEach(rule => { + // XXX + // I would like to catch all exceptions here, but this derails the testing + // infrastructure which also uses exceptions that it expects aren't caught + rule.check( + self, + function () { + done += 1; + self.sink.emit('done', this.name); + if (done === total) + self.sink.emit( + 'end-all', + buildJSONresult(errors, warnings, infos, {}) + ); + }.bind(rule) + ); + }); + }; + if (options.url) this.loadURL(options.url, doValidation); + else if (options.source) + this.loadSource(options.source, doValidation); + else if (options.file) this.loadFile(options.file, doValidation); + else if (options.document) + this.loadDocument(options.document, doValidation); + else + return this.throw( + 'At least one of url, source, file, or document must be specified.' + ); + }) + .catch(err => this.throw(err.toString())); }; Specberus.prototype.error = function (rule, key, extra) { @@ -208,13 +219,13 @@ Specberus.prototype.error = function (rule, key, extra) { this.sink.emit('err', name, { key, extra, - detailMessage: l10n.assembleData(null, name, key, extra).message, + detailMessage: assembleData(null, name, key, extra).message, }); else this.sink.emit('err', rule, { key, extra, - detailMessage: l10n.assembleData(null, rule, key, extra).message, + detailMessage: assembleData(null, rule, key, extra).message, }); }; @@ -222,7 +233,7 @@ Specberus.prototype.warning = function (rule, key, extra) { this.sink.emit('warning', rule, { key, extra, - detailMessage: l10n.assembleData(null, rule, key, extra).message, + detailMessage: assembleData(null, rule, key, extra).message, }); }; @@ -230,7 +241,7 @@ Specberus.prototype.info = function (rule, key, extra) { this.sink.emit('info', rule, { key, extra, - detailMessage: l10n.assembleData(null, rule, key, extra).message, + detailMessage: assembleData(null, rule, key, extra).message, }); }; @@ -397,13 +408,13 @@ Specberus.prototype.extractHeaders = function (dl) { else if (/^feedback$/.test(txt)) { // feedback link can be multi-lines key = 'Feedback'; - dd = util.nextUntil(dt, 'dt', 'dd'); + dd = nextUntil(dt, 'dt', 'dd'); } else if (/^errata?$/.test(txt)) key = 'Errata'; if (EDITORS_DRAFT.test(txt) && dd.querySelector('a')) key = 'EditorDraft'; if (EDITORS.test(txt)) { key = 'Editor'; - dd = util.nextUntil(dt, 'dt', 'dd'); + dd = nextUntil(dt, 'dt', 'dd'); } if (key) dts[key] = { pos: idx, el: dt, dd }; }); @@ -491,7 +502,7 @@ Specberus.prototype.getDelivererGroups = async function () { /https?:\/\/www.w3.org\/2001\/tag\/disclosures/; const REGEX_DELIVERER_IPR_URL = /^https:\/\/www\.w3\.org\/groups\/([^/]+)\/([^/]+)\/ipr(#.*)?$/i; - const TagID = util.TAG.id; + const TagID = TAG.id; const sotd = this.getSotDSection(); const sotdLinks = sotd && sotd.querySelectorAll('a[href]'); @@ -541,7 +552,7 @@ Specberus.prototype.getDelivererGroups = async function () { const apikey = this.apiKey; promiseArray.push( new Promise(resolve => { - sua.get(groupApiUrl) + get(groupApiUrl) .set('User-Agent', `W3C-Pubrules/${version}`) .query({ apikey }) .end((err, data) => { @@ -591,7 +602,7 @@ Specberus.prototype.getDelivererIDs = async function () { /https?:\/\/www.w3.org\/2001\/tag\/disclosures/; const REGEX_DELIVERER_IPR_URL = /^https:\/\/www\.w3\.org\/groups\/([^/]+)\/([^/]+)\/ipr(#.*)?$/i; - const TagID = util.TAG.id; + const TagID = TAG.id; const ids = this.getDataDelivererIDs() || []; const sotd = this.getSotDSection(); const sotdLinks = sotd && sotd.querySelectorAll('a[href]'); @@ -620,7 +631,7 @@ Specberus.prototype.getDelivererIDs = async function () { const apikey = this.apiKey; promiseArray.push( new Promise(resolve => { - sua.get(groupApiUrl) + get(groupApiUrl) .set('User-Agent', `W3C-Pubrules/${version}`) .query({ apikey }) .end((err, data) => { @@ -672,8 +683,8 @@ Specberus.prototype.getChartersData = async function () { const chartersData = []; if (deliverers.length) { const delivererPromises = []; - const TagID = util.TAG.id; - const AbID = util.AB.id; + const TagID = TAG.id; + const AbID = AB.id; // Get charter data from W3C API // deliverers.forEach is for joint publication. deliverers.forEach(deliverer => { @@ -813,7 +824,7 @@ Specberus.prototype.getPreviousVersion = async function () { Specberus.prototype.loadURL = function (url, cb) { if (!cb) return this.throw('Missing callback to loadURL.'); const self = this; - sua.get(url) + get(url) .set('User-Agent', `W3C-Pubrules/${version}`) .end((err, res) => { if (err) return self.throw(err.message); @@ -869,18 +880,18 @@ Specberus.prototype.getRecMetadata = function (meta) { const sotdText = this.norm(this.getSotDSection().textContent); // proposed corrections, proposed additions, proposed amendments: - const { SOTD_P_COR } = util.REC_TEXT; - const { SOTD_P_ADD } = util.REC_TEXT; - const { SOTD_P_COR_ADD } = util.REC_TEXT; + const { SOTD_P_COR } = REC_TEXT; + const { SOTD_P_ADD } = REC_TEXT; + const { SOTD_P_COR_ADD } = REC_TEXT; if (sotdText.match(new RegExp(`${SOTD_P_COR}|${SOTD_P_COR_ADD}`, 'i'))) meta.pSubChanges = true; if (sotdText.match(new RegExp(`${SOTD_P_ADD}|${SOTD_P_COR_ADD}`, 'i'))) meta.pNewFeatures = true; // candidate corrections, candidate additions, candidate amendments: - const { SOTD_C_COR } = util.REC_TEXT; - const { SOTD_C_ADD } = util.REC_TEXT; - const { SOTD_C_COR_ADD } = util.REC_TEXT; + const { SOTD_C_COR } = REC_TEXT; + const { SOTD_C_ADD } = REC_TEXT; + const { SOTD_C_COR_ADD } = REC_TEXT; if (sotdText.match(new RegExp(`${SOTD_C_COR}|${SOTD_C_COR_ADD}`, 'i'))) meta.cSubChanges = true; if (sotdText.match(new RegExp(`${SOTD_C_ADD}|${SOTD_C_COR_ADD}`, 'i'))) @@ -889,4 +900,4 @@ Specberus.prototype.getRecMetadata = function (meta) { return meta; }; -exports.Specberus = Specberus; +export { Specberus }; diff --git a/lib/views.js b/lib/views.js index 22670de64..5888b8183 100644 --- a/lib/views.js +++ b/lib/views.js @@ -1,6 +1,9 @@ -/** - * Views. - */ +// Internal packages: +import handlebars from 'express-handlebars'; +import qs from 'querystring'; +import { importJSON } from './util.js'; + +const rules = importJSON('./rules.json', import.meta.url); // Settings: const DEBUG = process && process.env && process.env.DEBUG; @@ -8,13 +11,8 @@ const BASE_URI = `${process.env.BASE_URI ? process.env.BASE_URI : ''}/`.replace( /\/+$/, '/' ); -// Internal packages: -const handlebars = require('express-handlebars'); -const rules = require('./rules.json'); -const self = require('../package.json'); -// External packages: -const { version } = self; +const { version } = importJSON('../package.json', import.meta.url); const nav = `

    About · Site map · @@ -96,8 +94,7 @@ const listProfiles = function () { return result; }; -const sortedProfiles = listProfiles(); -exports.sortedProfiles = sortedProfiles; +export const sortedProfiles = listProfiles(); /** * @TODO Document. */ @@ -158,7 +155,6 @@ const formatRules = function (sections, common) { */ const retrieveProfile = function (query) { - const qs = require('querystring'); const result = {}; if (query && query.profile) { @@ -194,7 +190,7 @@ const retrieveProfile = function (query) { * @param {object} app - the Express application. */ -const setUp = function (app) { +export const setUp = function (app) { const hb = handlebars.create({ defaultLayout: 'main' }); app.engine('handlebars', hb.engine); app.set('view engine', 'handlebars'); @@ -243,5 +239,3 @@ const setUp = function (app) { // Catch-all: app.get('*', handleWrongPage); }; - -exports.setUp = setUp; diff --git a/package.json b/package.json index 7dd4e42fc..2c02cd423 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Specberus is a checker used at W3C to validate the compliance of Technical Reports with publication rules.", "license": "MIT", "main": "lib/validator", + "type": "module", "repository": { "type": "git", "url": "https://github.com/w3c/specberus.git" diff --git a/test/api.js b/test/api.js index 2ed978c68..f2f5d8175 100644 --- a/test/api.js +++ b/test/api.js @@ -2,24 +2,25 @@ * Test the REST API. */ -/* globals expect: true */ +// Native packages: +// External packages: +// eslint-disable-next-line node/no-unpublished-import +import chai, { expect } from 'chai'; +// eslint-disable-next-line node/no-unpublished-import +import chaiAsPromised from 'chai-as-promised'; +import express from 'express'; +import http from 'http'; +import superagent from 'superagent'; +import { setUp } from '../lib/api.js'; +import { importJSON } from '../lib/util.js'; +// Internal packages: +const meta = importJSON('../package.json', import.meta.url); // Settings: const DEFAULT_PORT = 8000; const PORT = process.env.PORT || DEFAULT_PORT; const ENDPOINT = `http://localhost:${PORT}/api/`; const TIMEOUT = 30000; -// Native packages: -const http = require('http'); - -// External packages: -const chai = require('chai'); -const chaiAsPromised = require('chai-as-promised'); -const express = require('express'); -const superagent = require('superagent'); -// Internal packages: -const meta = require('../package.json'); -const api = require('../lib/api'); let server; @@ -30,7 +31,7 @@ let server; const launchServer = function () { const app = express(); server = http.createServer(app); - api.setUp(app, process.env.W3C_API_KEY); + setUp(app, process.env.W3C_API_KEY); server.listen(PORT).on('error', err => { throw new Error(err); }); @@ -40,9 +41,8 @@ const launchServer = function () { * Set up the testing framework. */ -const setUp = function () { +const setUpTest = function () { chai.use(chaiAsPromised); - expect = chai.expect; }; /** @@ -88,7 +88,7 @@ describe('API', () => { before(() => { launchServer(); - setUp(); + setUpTest(); }); describe('Endpoint', () => { diff --git a/test/data/SUBM/MEM-SUBM.js b/test/data/SUBM/MEM-SUBM.js index a38e6e23b..7380854b2 100644 --- a/test/data/SUBM/MEM-SUBM.js +++ b/test/data/SUBM/MEM-SUBM.js @@ -1,9 +1,9 @@ -const { rules } = require('./SUBMBase'); +import { rules as baseRules } from './SUBMBase.js'; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, headers: { - ...rules.headers, + ...baseRules.headers, 'memsub-copyright': [ { data: 'noCopyright', @@ -199,7 +199,7 @@ exports.rules = { ], }, sotd: { - ...rules.sotd, + ...baseRules.sotd, submission: [ { data: 'noSubmissionText', diff --git a/test/data/SUBM/SUBMBase.js b/test/data/SUBM/SUBMBase.js index 972b48b1f..0db543b39 100644 --- a/test/data/SUBM/SUBMBase.js +++ b/test/data/SUBM/SUBMBase.js @@ -1,23 +1,23 @@ -const { rules } = require('../specBase'); +import { rules as baseRules } from '../specBase.js'; -exports.rules = { +export const rules = { headers: { - ...rules.headers, + ...baseRules.headers, }, style: { - ...rules.style, + ...baseRules.style, }, heuristic: { - ...rules.heuristic, + ...baseRules.heuristic, }, links: { - ...rules.links, + ...baseRules.links, }, structure: { - ...rules.structure, + ...baseRules.structure, }, sotd: {}, validation: { - ...rules.validation, + ...baseRules.validation, }, }; diff --git a/test/data/TR/Note/DNOTE-Echidna.js b/test/data/TR/Note/DNOTE-Echidna.js index 641747daf..0432bb5b9 100644 --- a/test/data/TR/Note/DNOTE-Echidna.js +++ b/test/data/TR/Note/DNOTE-Echidna.js @@ -1,9 +1,11 @@ -const { rules, draftStabilityRules, echidnaRules } = require('./noteBase'); +import noteBase from './noteBase.js'; -exports.rules = { - ...rules, +const { draftStabilityRules, echidnaRules, rules: baseRules } = noteBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRules, }, echidna: echidnaRules, diff --git a/test/data/TR/Note/DNOTE.js b/test/data/TR/Note/DNOTE.js index 3f4d4deb1..eb1cf56c5 100644 --- a/test/data/TR/Note/DNOTE.js +++ b/test/data/TR/Note/DNOTE.js @@ -1,9 +1,11 @@ -const { rules, draftStabilityRules } = require('./noteBase'); +import noteBase from './noteBase.js'; -exports.rules = { - ...rules, +const { draftStabilityRules, rules: baseRules } = noteBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRules, }, }; diff --git a/test/data/TR/Note/NOTE-Echidna.js b/test/data/TR/Note/NOTE-Echidna.js index 9ff33a124..909fcd86b 100644 --- a/test/data/TR/Note/NOTE-Echidna.js +++ b/test/data/TR/Note/NOTE-Echidna.js @@ -1,6 +1,8 @@ -const { rules, echidnaRules } = require('./noteBase'); +import noteBase from './noteBase.js'; -exports.rules = { - ...rules, +const { echidnaRules, rules: baseRules } = noteBase; + +export const rules = { + ...baseRules, echidna: echidnaRules, }; diff --git a/test/data/TR/Note/NOTE.js b/test/data/TR/Note/NOTE.js index 628a7fb0f..4cfd2564e 100644 --- a/test/data/TR/Note/NOTE.js +++ b/test/data/TR/Note/NOTE.js @@ -1,5 +1,3 @@ -const { rules } = require('./noteBase'); +import noteBase from './noteBase.js'; -exports.rules = { - ...rules, -}; +export const { rules } = noteBase; diff --git a/test/data/TR/Note/STMT.js b/test/data/TR/Note/STMT.js index 628a7fb0f..4cfd2564e 100644 --- a/test/data/TR/Note/STMT.js +++ b/test/data/TR/Note/STMT.js @@ -1,5 +1,3 @@ -const { rules } = require('./noteBase'); +import noteBase from './noteBase.js'; -exports.rules = { - ...rules, -}; +export const { rules } = noteBase; diff --git a/test/data/TR/Note/noteBase.js b/test/data/TR/Note/noteBase.js index 97daeac7c..a16cd024f 100644 --- a/test/data/TR/Note/noteBase.js +++ b/test/data/TR/Note/noteBase.js @@ -1,13 +1,15 @@ -const { rules, ...rest } = require('../TRBase'); +import * as TRBase from '../TRBase.js'; -module.exports = { +const { rules: baseRules, ...rest } = TRBase; + +export default { ...rest, rules: { - ...rules, + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, pp: [ - ...rules.sotd.pp.filter( + ...baseRules.sotd.pp.filter( v => !['noPP2017', 'jointPublication'].find( x => x === v.data diff --git a/test/data/TR/Recommendation/CR-Echidna.js b/test/data/TR/Recommendation/CR-Echidna.js index 11b4aaeec..d8cf1f242 100644 --- a/test/data/TR/Recommendation/CR-Echidna.js +++ b/test/data/TR/Recommendation/CR-Echidna.js @@ -1,20 +1,22 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, candidateReviewEndRules, echidnaRules, + rules: baseRules, securityPrivacyRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': [], 'candidate-review-end': candidateReviewEndRules, }, echidna: echidnaRules, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, }; diff --git a/test/data/TR/Recommendation/CR.js b/test/data/TR/Recommendation/CR.js index 42ef6dba4..8e8feb0a4 100644 --- a/test/data/TR/Recommendation/CR.js +++ b/test/data/TR/Recommendation/CR.js @@ -1,18 +1,20 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, candidateReviewEndRules, + rules: baseRules, securityPrivacyRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': [], 'candidate-review-end': candidateReviewEndRules, }, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, }; diff --git a/test/data/TR/Recommendation/CRD-Echidna.js b/test/data/TR/Recommendation/CRD-Echidna.js index 5337ac53c..0b9f33a17 100644 --- a/test/data/TR/Recommendation/CRD-Echidna.js +++ b/test/data/TR/Recommendation/CRD-Echidna.js @@ -1,19 +1,21 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, + rules: baseRules, echidnaRules, draftStabilityRulesForDraft, securityPrivacyRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRulesForDraft, }, echidna: echidnaRules, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, }; diff --git a/test/data/TR/Recommendation/CRD.js b/test/data/TR/Recommendation/CRD.js index 3b421c75d..bf6994c93 100644 --- a/test/data/TR/Recommendation/CRD.js +++ b/test/data/TR/Recommendation/CRD.js @@ -1,17 +1,19 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, + rules: baseRules, securityPrivacyRules, draftStabilityRulesForDraft, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRulesForDraft, }, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, }; diff --git a/test/data/TR/Recommendation/DISC.js b/test/data/TR/Recommendation/DISC.js index 736e668f1..d9aa9188b 100644 --- a/test/data/TR/Recommendation/DISC.js +++ b/test/data/TR/Recommendation/DISC.js @@ -1,11 +1,13 @@ -const { rules } = require('./recommendationBase'); +import recommendationBase from './recommendationBase.js'; -exports.rules = { - ...rules, +const { rules: baseRules } = recommendationBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, stability: [ - ...rules.sotd.stability, + ...baseRules.sotd.stability, { data: 'noCRReview', config: { diff --git a/test/data/TR/Recommendation/FPWD.js b/test/data/TR/Recommendation/FPWD.js index eefa44017..36c4dcfcc 100644 --- a/test/data/TR/Recommendation/FPWD.js +++ b/test/data/TR/Recommendation/FPWD.js @@ -1,9 +1,11 @@ -const { rules, draftStabilityRules } = require('./recommendationBase'); +import recommendationBase from './recommendationBase.js'; -exports.rules = { - ...rules, +const { rules: baseRules, draftStabilityRules } = recommendationBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRules, }, }; diff --git a/test/data/TR/Recommendation/PR.js b/test/data/TR/Recommendation/PR.js index 4c62f0f56..b77e0ce55 100644 --- a/test/data/TR/Recommendation/PR.js +++ b/test/data/TR/Recommendation/PR.js @@ -1,17 +1,19 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, + rules: baseRules, securityPrivacyRules, newFeaturesRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'ac-review': [ { data: 'noACReview', diff --git a/test/data/TR/Recommendation/REC-RSCND.js b/test/data/TR/Recommendation/REC-RSCND.js index a1a603180..65da8f307 100644 --- a/test/data/TR/Recommendation/REC-RSCND.js +++ b/test/data/TR/Recommendation/REC-RSCND.js @@ -1,11 +1,13 @@ -const { rules, recStabilityRules } = require('./recommendationBase'); +import recommendationBase from './recommendationBase.js'; -exports.rules = { - ...rules, +const { recStabilityRules, rules: baseRules } = recommendationBase; + +export const rules = { + ...baseRules, headers: { - ...rules.headers, + ...baseRules.headers, dl: [ - ...rules.headers.dl.filter( + ...baseRules.headers.dl.filter( v => ![ 'wrongThisVersionHead', @@ -66,7 +68,7 @@ exports.rules = { ], }, sotd: { - ...rules.sotd, + ...baseRules.sotd, stability: recStabilityRules, 'obsl-rescind': [ { diff --git a/test/data/TR/Recommendation/REC.js b/test/data/TR/Recommendation/REC.js index 8339f20ed..6469c7ffa 100644 --- a/test/data/TR/Recommendation/REC.js +++ b/test/data/TR/Recommendation/REC.js @@ -1,13 +1,15 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, + rules: baseRules, newFeaturesRules, recStabilityRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, stability: recStabilityRules, deployment: [ { @@ -46,7 +48,7 @@ exports.rules = { ], }, headers: { - ...rules.headers, + ...baseRules.headers, errata: [ { data: 'noErrata', diff --git a/test/data/TR/Recommendation/WD-Echidna.js b/test/data/TR/Recommendation/WD-Echidna.js index ad05a856d..85f7e415a 100644 --- a/test/data/TR/Recommendation/WD-Echidna.js +++ b/test/data/TR/Recommendation/WD-Echidna.js @@ -1,18 +1,20 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, + rules: baseRules, draftStabilityRules, securityPrivacyRules, echidnaRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRules, }, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, echidna: echidnaRules, diff --git a/test/data/TR/Recommendation/WD.js b/test/data/TR/Recommendation/WD.js index 3336eb7bd..d53bd4ca5 100644 --- a/test/data/TR/Recommendation/WD.js +++ b/test/data/TR/Recommendation/WD.js @@ -1,17 +1,19 @@ +import recommendationBase from './recommendationBase.js'; + const { - rules, + rules: baseRules, draftStabilityRules, securityPrivacyRules, -} = require('./recommendationBase'); +} = recommendationBase; -exports.rules = { - ...rules, +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRules, }, structure: { - ...rules.structure, + ...baseRules.structure, 'security-privacy': securityPrivacyRules, }, }; diff --git a/test/data/TR/Recommendation/recommendationBase.js b/test/data/TR/Recommendation/recommendationBase.js index 0e60ae8ff..0733709ed 100644 --- a/test/data/TR/Recommendation/recommendationBase.js +++ b/test/data/TR/Recommendation/recommendationBase.js @@ -1,6 +1,8 @@ -const { rules, ...rest } = require('../TRBase'); +import * as TRBase from '../TRBase.js'; -module.exports = { +const { rules: baseRules, ...rest } = TRBase; + +export default { ...rest, securityPrivacyRules: [ { @@ -27,11 +29,11 @@ module.exports = { }, ], rules: { - ...rules, + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, pp: [ - ...rules.sotd.pp, + ...baseRules.sotd.pp, { data: 'noDisclosures', config: { diff --git a/test/data/TR/Registry/CRY.js b/test/data/TR/Registry/CRY.js index 4efbce267..af214d3fe 100644 --- a/test/data/TR/Registry/CRY.js +++ b/test/data/TR/Registry/CRY.js @@ -1,9 +1,11 @@ -const { rules, candidateReviewEndRules } = require('./registryBase'); +import registryBase from './registryBase.js'; -exports.rules = { - ...rules, +const { rules: baseRules, candidateReviewEndRules } = registryBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'candidate-review-end': candidateReviewEndRules, }, }; diff --git a/test/data/TR/Registry/CRYD.js b/test/data/TR/Registry/CRYD.js index 8ecf9234a..51eba58fe 100644 --- a/test/data/TR/Registry/CRYD.js +++ b/test/data/TR/Registry/CRYD.js @@ -1,9 +1,11 @@ -const { rules, draftStabilityRulesForDraft } = require('./registryBase'); +import registryBase from './registryBase.js'; -exports.rules = { - ...rules, +const { rules: baseRules, draftStabilityRulesForDraft } = registryBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRulesForDraft, }, }; diff --git a/test/data/TR/Registry/DRY.js b/test/data/TR/Registry/DRY.js index 6ca4e66f1..5cc685c8d 100644 --- a/test/data/TR/Registry/DRY.js +++ b/test/data/TR/Registry/DRY.js @@ -1,9 +1,11 @@ -const { rules, draftStabilityRules } = require('./registryBase'); +import registryBase from './registryBase.js'; -exports.rules = { - ...rules, +const { rules: baseRules, draftStabilityRules } = registryBase; + +export const rules = { + ...baseRules, sotd: { - ...rules.sotd, + ...baseRules.sotd, 'draft-stability': draftStabilityRules, }, }; diff --git a/test/data/TR/Registry/RY.js b/test/data/TR/Registry/RY.js index 18060008b..810c564bf 100644 --- a/test/data/TR/Registry/RY.js +++ b/test/data/TR/Registry/RY.js @@ -1,5 +1,3 @@ -const { rules } = require('./registryBase'); +import registryBase from './registryBase.js'; -exports.rules = { - ...rules, -}; +export const { rules } = registryBase; diff --git a/test/data/TR/Registry/registryBase.js b/test/data/TR/Registry/registryBase.js index a4ee97624..72ff45b94 100644 --- a/test/data/TR/Registry/registryBase.js +++ b/test/data/TR/Registry/registryBase.js @@ -1,6 +1,8 @@ -const { rules, ...rest } = require('../TRBase'); +import * as TRBase from '../TRBase.js'; -module.exports = { +const { rules, ...rest } = TRBase; + +export default { ...rest, rules: { ...rules, diff --git a/test/data/TR/TRBase.js b/test/data/TR/TRBase.js index 908b85522..5ecc5a497 100644 --- a/test/data/TR/TRBase.js +++ b/test/data/TR/TRBase.js @@ -1,8 +1,8 @@ -const { rules } = require('../specBase'); +import { rules as baseRules } from '../specBase.js'; -exports.rules = { +export const rules = { headers: { - ...rules.headers, + ...baseRules.headers, 'github-repo': [ { data: 'noFeedback', @@ -21,16 +21,16 @@ exports.rules = { ], }, style: { - ...rules.style, + ...baseRules.style, }, heuristic: { - ...rules.heuristic, + ...baseRules.heuristic, }, links: { - ...rules.links, + ...baseRules.links, }, structure: { - ...rules.structure, + ...baseRules.structure, }, sotd: { supersedable: [ @@ -127,11 +127,11 @@ exports.rules = { ], }, validation: { - ...rules.validation, + ...baseRules.validation, }, }; -exports.candidateReviewEndRules = [ +export const candidateReviewEndRules = [ { data: 'noDateFound', errors: ['sotd.candidate-review-end.not-found'], @@ -146,7 +146,7 @@ exports.candidateReviewEndRules = [ }, ]; -exports.echidnaRules = { +export const echidnaRules = { 'todays-date': [ { data: 'noDateDetected', @@ -159,21 +159,21 @@ exports.echidnaRules = { ], }; -exports.draftStabilityRules = [ +export const draftStabilityRules = [ { data: 'noDraft', errors: ['sotd.draft-stability.not-found'], }, ]; -exports.draftStabilityRulesForDraft = [ +export const draftStabilityRulesForDraft = [ { data: 'noDraftEither', errors: ['sotd.draft-stability.not-found-either'], }, ]; -exports.newFeaturesRules = [ +export const newFeaturesRules = [ { data: 'noWarning', warnings: ['sotd.new-features.no-warning'], diff --git a/test/data/goodDocuments.js b/test/data/goodDocuments.js index da34fdbcf..ca1b15824 100644 --- a/test/data/goodDocuments.js +++ b/test/data/goodDocuments.js @@ -1,4 +1,4 @@ -exports.goodDocuments = { +export const goodDocuments = { // Note track DNOTE: { url: 'doc-views/TR/Note/DNOTE?type=good', diff --git a/test/data/specBase.js b/test/data/specBase.js index 467c92599..1d80f7a17 100644 --- a/test/data/specBase.js +++ b/test/data/specBase.js @@ -1,4 +1,4 @@ -exports.rules = { +export const rules = { headers: { 'div-head': [ { diff --git a/test/doc-views/SUBM/MEM-SUBM.js b/test/doc-views/SUBM/MEM-SUBM.js index afc374cd3..57ab2b901 100644 --- a/test/doc-views/SUBM/MEM-SUBM.js +++ b/test/doc-views/SUBM/MEM-SUBM.js @@ -1,8 +1,5 @@ -/* eslint-disable import/no-dynamic-require */ -const { buildCommonViewData, data } = require('../specBase'); - -const profile = 'MEM-SUBM'; -const { config } = require(`../../../lib/profiles/SUBM/${profile}`); +import { config } from '../../../lib/profiles/SUBM/MEM-SUBM.js'; +import { buildCommonViewData, data } from '../specBase.js'; // Used in http://localhost:8001/doc-views/TR/Recommendation/MEM-SUBM?type=good const good = { @@ -31,7 +28,7 @@ const good = { }, }; -module.exports = { +export default { good, ...buildCommonViewData(good), 'memsub-copyright': { diff --git a/test/doc-views/TR/Note/DNOTE-Echidna.js b/test/doc-views/TR/Note/DNOTE-Echidna.js index c23c8fdc4..c0fe77381 100644 --- a/test/doc-views/TR/Note/DNOTE-Echidna.js +++ b/test/doc-views/TR/Note/DNOTE-Echidna.js @@ -1,13 +1,11 @@ -/* eslint-disable import/no-dynamic-require */ -const data = require('./DNOTE').good; -const { - buildCommonViewData, - buildDraftStability, - buildTodaysDate, -} = require('./noteBase'); +import { config } from '../../../../lib/profiles/TR/Note/DNOTE-Echidna.js'; +import DNOTE from './DNOTE.js'; +import noteBase from './noteBase.js'; + +const { good: data } = DNOTE; +const { buildCommonViewData, buildDraftStability, buildTodaysDate } = noteBase; const profile = 'DNOTE-Echidna'; -const { config } = require(`../../../../lib/profiles/TR/Note/${profile}`); const customData = { config: { ...config, @@ -21,7 +19,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, dl: { diff --git a/test/doc-views/TR/Note/DNOTE.js b/test/doc-views/TR/Note/DNOTE.js index f440a8c62..f24a7337f 100644 --- a/test/doc-views/TR/Note/DNOTE.js +++ b/test/doc-views/TR/Note/DNOTE.js @@ -1,12 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildDraftStability, - data, -} = require('./noteBase'); +import { config } from '../../../../lib/profiles/TR/Note/DNOTE.js'; +import noteBase from './noteBase.js'; + +const { buildCommonViewData, buildDraftStability, data } = noteBase; const profile = 'DNOTE'; -const { config } = require(`../../../../lib/profiles/TR/Note/${profile}`); const customData = { ...data, config: { @@ -22,7 +19,7 @@ const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, stability: { diff --git a/test/doc-views/TR/Note/NOTE-Echidna.js b/test/doc-views/TR/Note/NOTE-Echidna.js index e7fea0dc4..dc4dfa52f 100644 --- a/test/doc-views/TR/Note/NOTE-Echidna.js +++ b/test/doc-views/TR/Note/NOTE-Echidna.js @@ -1,9 +1,11 @@ -/* eslint-disable import/no-dynamic-require */ -const data = require('./NOTE').good; -const { buildCommonViewData, buildTodaysDate } = require('./noteBase'); +import { config } from '../../../../lib/profiles/TR/Note/NOTE-Echidna.js'; +import NOTE from './NOTE.js'; +import noteBase from './noteBase.js'; + +const { good: data } = NOTE; +const { buildCommonViewData, buildTodaysDate } = noteBase; const profile = 'NOTE-Echidna'; -const { config } = require(`../../../../lib/profiles/TR/Note/${profile}`); const customData = { config: { ...config, @@ -18,7 +20,7 @@ const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, dl: { diff --git a/test/doc-views/TR/Note/NOTE.js b/test/doc-views/TR/Note/NOTE.js index 9821cdbc4..664a9758c 100644 --- a/test/doc-views/TR/Note/NOTE.js +++ b/test/doc-views/TR/Note/NOTE.js @@ -1,8 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { buildCommonViewData, data } = require('./noteBase'); +import { config } from '../../../../lib/profiles/TR/Note/NOTE.js'; +import noteBase from './noteBase.js'; + +const { buildCommonViewData, data } = noteBase; const profile = 'NOTE'; -const { config } = require(`../../../../lib/profiles/TR/Note/${profile}`); const customData = { config: { ...config, @@ -17,7 +18,7 @@ const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, }; diff --git a/test/doc-views/TR/Note/STMT.js b/test/doc-views/TR/Note/STMT.js index a3a2d8485..006d03798 100644 --- a/test/doc-views/TR/Note/STMT.js +++ b/test/doc-views/TR/Note/STMT.js @@ -1,8 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { buildCommonViewData, data } = require('./noteBase'); +import { config } from '../../../../lib/profiles/TR/Note/STMT.js'; +import noteBase from './noteBase.js'; + +const { buildCommonViewData, data } = noteBase; const profile = 'STMT'; -const { config } = require(`../../../../lib/profiles/TR/Note/${profile}`); const customData = { config: { ...config, @@ -16,7 +17,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, stability: { diff --git a/test/doc-views/TR/Note/noteBase.js b/test/doc-views/TR/Note/noteBase.js index b55e90819..ffeb22006 100644 --- a/test/doc-views/TR/Note/noteBase.js +++ b/test/doc-views/TR/Note/noteBase.js @@ -1,8 +1,6 @@ -const { - buildCommonViewData: _buildCommonViewData, - data, - ...rest -} = require('../TRBase'); +import * as TRBase from '../TRBase.js'; + +const { buildCommonViewData: _buildCommonViewData, data, ...rest } = TRBase; const buildCommonViewData = base => { const common = _buildCommonViewData(base); @@ -86,7 +84,7 @@ const buildCommonViewData = base => { }; }; -module.exports = { +export default { ...rest, buildCommonViewData, data: { diff --git a/test/doc-views/TR/Recommendation/CR-Echidna.js b/test/doc-views/TR/Recommendation/CR-Echidna.js index 9a649fadc..3d26ab614 100644 --- a/test/doc-views/TR/Recommendation/CR-Echidna.js +++ b/test/doc-views/TR/Recommendation/CR-Echidna.js @@ -1,16 +1,17 @@ -/* eslint-disable import/no-dynamic-require */ -const data = require('./CR').good; +import { config } from '../../../../lib/profiles/TR/Recommendation/CR-Echidna.js'; +import CR from './CR.js'; +import recommendationBase from './recommendationBase.js'; + const { - buildCommonViewData, buildCandidateReviewEnd, - buildTodaysDate, + buildCommonViewData, buildSecurityPrivacy, -} = require('./recommendationBase'); + buildTodaysDate, +} = recommendationBase; + +const { good: data } = CR; const profile = 'CR-Echidna'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -25,7 +26,7 @@ const good = { ...data, ...customData }; const common = buildCommonViewData(good); const creCommon = buildCandidateReviewEnd(good); -module.exports = { +export default { good, ...common, 'candidate-review-end': { diff --git a/test/doc-views/TR/Recommendation/CR.js b/test/doc-views/TR/Recommendation/CR.js index cccc88517..3d153edec 100644 --- a/test/doc-views/TR/Recommendation/CR.js +++ b/test/doc-views/TR/Recommendation/CR.js @@ -1,15 +1,15 @@ -/* eslint-disable import/no-dynamic-require */ +import { config } from '../../../../lib/profiles/TR/Recommendation/CR.js'; +import recommendationBase from './recommendationBase.js'; + const { - buildCommonViewData, buildCandidateReviewEnd, + buildCommonViewData, buildSecurityPrivacy, data, -} = require('./recommendationBase'); +} = recommendationBase; const profile = 'CR'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); + const customData = { config: { ...config, @@ -25,7 +25,7 @@ const customData = { // Used in http://localhost:8001/doc-views/TR/Recommendation/CR?type=good const good = { ...data, ...customData }; -module.exports = { +export default { good, ...buildCommonViewData(good), 'candidate-review-end': buildCandidateReviewEnd(good), diff --git a/test/doc-views/TR/Recommendation/CRD-Echidna.js b/test/doc-views/TR/Recommendation/CRD-Echidna.js index b2c4b8674..b268f6dc1 100644 --- a/test/doc-views/TR/Recommendation/CRD-Echidna.js +++ b/test/doc-views/TR/Recommendation/CRD-Echidna.js @@ -1,16 +1,16 @@ -/* eslint-disable import/no-dynamic-require */ -const data = require('./CRD').good; +import { config } from '../../../../lib/profiles/TR/Recommendation/CRD-Echidna.js'; +import CRD from './CRD.js'; +import recommendationBase from './recommendationBase.js'; + +const { good: data } = CRD; const { buildCommonViewData, - buildTodaysDate, buildDraftStability, buildSecurityPrivacy, -} = require('./recommendationBase'); + buildTodaysDate, +} = recommendationBase; const profile = 'CRD-Echidna'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -25,7 +25,7 @@ const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, dl: { diff --git a/test/doc-views/TR/Recommendation/CRD.js b/test/doc-views/TR/Recommendation/CRD.js index ddf23cf27..587da77fb 100644 --- a/test/doc-views/TR/Recommendation/CRD.js +++ b/test/doc-views/TR/Recommendation/CRD.js @@ -1,15 +1,10 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildSecurityPrivacy, - buildDraftStability, - data, -} = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/CRD.js'; +import recommendationBase from './recommendationBase.js'; + +const { buildCommonViewData, buildSecurityPrivacy, buildDraftStability, data } = + recommendationBase; const profile = 'CRD'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -37,7 +32,7 @@ const good2 = { }, }; -module.exports = { +export default { good, good2, ...buildCommonViewData(good), diff --git a/test/doc-views/TR/Recommendation/DISC.js b/test/doc-views/TR/Recommendation/DISC.js index 3f09e385a..1d54fcb80 100644 --- a/test/doc-views/TR/Recommendation/DISC.js +++ b/test/doc-views/TR/Recommendation/DISC.js @@ -1,10 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { buildCommonViewData, data } = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/DISC.js'; +import recommendationBase from './recommendationBase.js'; + +const { buildCommonViewData, data } = recommendationBase; const profile = 'DISC'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -19,7 +18,7 @@ const customData = { const good = { ...data, ...customData }; const commonData = buildCommonViewData(good); -module.exports = { +export default { good, ...commonData, stability: { diff --git a/test/doc-views/TR/Recommendation/FPWD.js b/test/doc-views/TR/Recommendation/FPWD.js index 182ab920a..beddf6db2 100644 --- a/test/doc-views/TR/Recommendation/FPWD.js +++ b/test/doc-views/TR/Recommendation/FPWD.js @@ -1,14 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildDraftStability, - data, -} = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/FPWD.js'; +import recommendationBase from './recommendationBase.js'; + +const { buildCommonViewData, buildDraftStability, data } = recommendationBase; const profile = 'FPWD'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -23,7 +18,7 @@ const customData = { // Used in http://localhost:8001/doc-views/TR/Recommendation/FPWD?type=good const good = { ...data, ...customData }; -module.exports = { +export default { // good data that used to generate 100% right documents. good, ...buildCommonViewData(good), diff --git a/test/doc-views/TR/Recommendation/PR.js b/test/doc-views/TR/Recommendation/PR.js index 0bb0aee40..03911b09c 100644 --- a/test/doc-views/TR/Recommendation/PR.js +++ b/test/doc-views/TR/Recommendation/PR.js @@ -1,15 +1,10 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildSecurityPrivacy, - buildNewFeatures, - data, -} = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/PR.js'; +import recommendationBase from './recommendationBase.js'; + +const { buildCommonViewData, buildNewFeatures, buildSecurityPrivacy, data } = + recommendationBase; const profile = 'PR'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -25,7 +20,7 @@ const customData = { // Used in http://localhost:8001/doc-views/TR/Recommendation/PR?type=good const good = { ...data, ...customData }; -module.exports = { +export default { good, ...buildCommonViewData(good), 'security-privacy': buildSecurityPrivacy(good), diff --git a/test/doc-views/TR/Recommendation/REC-RSCND.js b/test/doc-views/TR/Recommendation/REC-RSCND.js index 55787c1dd..7c7c3d811 100644 --- a/test/doc-views/TR/Recommendation/REC-RSCND.js +++ b/test/doc-views/TR/Recommendation/REC-RSCND.js @@ -1,14 +1,11 @@ -/* eslint-disable import/no-dynamic-require */ -const data = require('./REC').good; -const { - buildCommonViewData, - buildRecStability, -} = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/REC-RSCND.js'; +import REC from './REC.js'; +import recommendationBase from './recommendationBase.js'; + +const { good: data } = REC; +const { buildCommonViewData, buildRecStability } = recommendationBase; const profile = 'REC-RSCND'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...data.config, @@ -23,7 +20,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, stability: buildRecStability(good), diff --git a/test/doc-views/TR/Recommendation/REC.js b/test/doc-views/TR/Recommendation/REC.js index 8eb0a5cd4..21350bf9b 100644 --- a/test/doc-views/TR/Recommendation/REC.js +++ b/test/doc-views/TR/Recommendation/REC.js @@ -1,15 +1,10 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildNewFeatures, - data, - buildRecStability, -} = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/REC.js'; +import recommendationBase from './recommendationBase.js'; + +const { buildCommonViewData, buildNewFeatures, buildRecStability, data } = + recommendationBase; const profile = 'REC'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -27,7 +22,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, stability: buildRecStability(good), diff --git a/test/doc-views/TR/Recommendation/WD-Echidna.js b/test/doc-views/TR/Recommendation/WD-Echidna.js index 993c2d44b..72309f378 100644 --- a/test/doc-views/TR/Recommendation/WD-Echidna.js +++ b/test/doc-views/TR/Recommendation/WD-Echidna.js @@ -1,16 +1,16 @@ -/* eslint-disable import/no-dynamic-require */ -const data = require('./WD').good; +import { config } from '../../../../lib/profiles/TR/Recommendation/WD-Echidna.js'; +import recommendationBase from './recommendationBase.js'; +import WD from './WD.js'; + +const { good: data } = WD; const { buildCommonViewData, buildDraftStability, buildSecurityPrivacy, buildTodaysDate, -} = require('./recommendationBase'); +} = recommendationBase; const profile = 'WD-Echidna'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -24,7 +24,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, 'draft-stability': buildDraftStability(good), diff --git a/test/doc-views/TR/Recommendation/WD.js b/test/doc-views/TR/Recommendation/WD.js index d2b56cecd..97937a09f 100644 --- a/test/doc-views/TR/Recommendation/WD.js +++ b/test/doc-views/TR/Recommendation/WD.js @@ -1,15 +1,10 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildDraftStability, - buildSecurityPrivacy, - data, -} = require('./recommendationBase'); +import { config } from '../../../../lib/profiles/TR/Recommendation/WD.js'; +import recommendationBase from './recommendationBase.js'; + +const { buildCommonViewData, buildDraftStability, buildSecurityPrivacy, data } = + recommendationBase; const profile = 'WD'; -const { - config, -} = require(`../../../../lib/profiles/TR/Recommendation/${profile}`); const customData = { config: { ...config, @@ -23,7 +18,7 @@ const customData = { // Used in http://localhost:8001/doc-views/TR/Recommendation/WD?type=good const good = { ...data, ...customData }; -module.exports = { +export default { good, ...buildCommonViewData(good), 'draft-stability': buildDraftStability(good), diff --git a/test/doc-views/TR/Recommendation/recommendationBase.js b/test/doc-views/TR/Recommendation/recommendationBase.js index a80ee696a..d889a78ba 100644 --- a/test/doc-views/TR/Recommendation/recommendationBase.js +++ b/test/doc-views/TR/Recommendation/recommendationBase.js @@ -1,4 +1,6 @@ -const { data, ...rest } = require('../TRBase'); +import * as TRBase from '../TRBase.js'; + +const { data, ...rest } = TRBase; const buildSecurityPrivacy = base => ({ noSecurityPrivacy: { @@ -38,7 +40,7 @@ const buildRecStability = base => ({ }, }); -module.exports = { +export default { ...rest, buildSecurityPrivacy, buildRecStability, diff --git a/test/doc-views/TR/Registry/CRY.js b/test/doc-views/TR/Registry/CRY.js index 44b114952..64da96e07 100644 --- a/test/doc-views/TR/Registry/CRY.js +++ b/test/doc-views/TR/Registry/CRY.js @@ -1,8 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { buildCommonViewData, data } = require('./registryBase'); +import { config } from '../../../../lib/profiles/TR/Registry/CRY.js'; +import registryBase from './registryBase.js'; + +const { buildCommonViewData, data } = registryBase; const profile = 'CRY'; -const { config } = require(`../../../../lib/profiles/TR/Registry/${profile}`); const customData = { config: { ...config, @@ -19,7 +20,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, 'candidate-review-end': { diff --git a/test/doc-views/TR/Registry/CRYD.js b/test/doc-views/TR/Registry/CRYD.js index d09a9f434..93dea1d2d 100644 --- a/test/doc-views/TR/Registry/CRYD.js +++ b/test/doc-views/TR/Registry/CRYD.js @@ -1,12 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildDraftStability, - data, -} = require('./registryBase'); +import { config } from '../../../../lib/profiles/TR/Registry/CRYD.js'; +import registryBase from './registryBase.js'; + +const { buildCommonViewData, buildDraftStability, data } = registryBase; const profile = 'CRYD'; -const { config } = require(`../../../../lib/profiles/TR/Registry/${profile}`); const customData = { config: { ...config, @@ -23,7 +20,7 @@ const customData = { const good = { ...data, ...customData }; // Used in http://localhost:8001/doc-views/TR/Recommendation/CRYD?type=good2 -exports.good2 = { +export const good2 = { config: { ...good.config, }, @@ -36,7 +33,7 @@ exports.good2 = { const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, 'draft-stability': buildDraftStability(good), diff --git a/test/doc-views/TR/Registry/DRY.js b/test/doc-views/TR/Registry/DRY.js index 243ab307b..5270271ad 100644 --- a/test/doc-views/TR/Registry/DRY.js +++ b/test/doc-views/TR/Registry/DRY.js @@ -1,12 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { - buildCommonViewData, - buildDraftStability, - data, -} = require('./registryBase'); +import { config } from '../../../../lib/profiles/TR/Registry/DRY.js'; +import registryBase from './registryBase.js'; + +const { buildCommonViewData, buildDraftStability, data } = registryBase; const profile = 'DRY'; -const { config } = require(`../../../../lib/profiles/TR/Registry/${profile}`); const customData = { config: { ...config, @@ -23,7 +20,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, 'draft-stability': buildDraftStability(good), diff --git a/test/doc-views/TR/Registry/RY.js b/test/doc-views/TR/Registry/RY.js index d4e60f04e..528e1144f 100644 --- a/test/doc-views/TR/Registry/RY.js +++ b/test/doc-views/TR/Registry/RY.js @@ -1,8 +1,9 @@ -/* eslint-disable import/no-dynamic-require */ -const { buildCommonViewData, data } = require('./registryBase'); +import { config } from '../../../../lib/profiles/TR/Registry/RY.js'; +import registryBase from './registryBase.js'; + +const { buildCommonViewData, data } = registryBase; const profile = 'RY'; -const { config } = require(`../../../../lib/profiles/TR/Registry/${profile}`); const customData = { config: { ...config, @@ -17,7 +18,7 @@ const customData = { const good = { ...data, ...customData }; const common = buildCommonViewData(good); -module.exports = { +export default { good, ...common, stability: { diff --git a/test/doc-views/TR/Registry/registryBase.js b/test/doc-views/TR/Registry/registryBase.js index df9c5fd41..9e78c15ae 100644 --- a/test/doc-views/TR/Registry/registryBase.js +++ b/test/doc-views/TR/Registry/registryBase.js @@ -1,9 +1,6 @@ -const { - buildCommonViewData: _buildCommonViewData, - data, - ...rest -} = require('../TRBase'); +import * as TRBase from '../TRBase.js'; +const { buildCommonViewData: _buildCommonViewData, data, ...rest } = TRBase; const buildCommonViewData = base => { const common = _buildCommonViewData(base); return { @@ -52,7 +49,7 @@ const buildCommonViewData = base => { }; }; -module.exports = { +export default { ...rest, buildCommonViewData, data: { diff --git a/test/doc-views/TR/TRBase.js b/test/doc-views/TR/TRBase.js index 9f643b072..edf9fcd63 100644 --- a/test/doc-views/TR/TRBase.js +++ b/test/doc-views/TR/TRBase.js @@ -1,11 +1,11 @@ -const { - buildCommonViewData: _buildCommonViewData, +import { + buildCommonViewData as _buildCommonViewData, data, -} = require('../specBase'); +} from '../specBase.js'; -exports.data = data; +export { data }; -exports.buildCommonViewData = base => { +export function buildCommonViewData(base) { const common = _buildCommonViewData(base); return { ...common, @@ -189,92 +189,100 @@ exports.buildCommonViewData = base => { }, }, }; -}; +} -exports.buildCandidateReviewEnd = base => ({ - noDateFound: { - ...base, - sotd: { - ...base.sotd, - defaultCRDate: '', +export function buildCandidateReviewEnd(base) { + return { + noDateFound: { + ...base, + sotd: { + ...base.sotd, + defaultCRDate: '', + }, }, - }, - multipleDateFound: { - ...base, - sotd: { - ...base.sotd, - defaultCRDate: '04 October 2022. 05 October 2022.', + multipleDateFound: { + ...base, + sotd: { + ...base.sotd, + defaultCRDate: '04 October 2022. 05 October 2022.', + }, }, - }, - invalidDate: { - ...base, - sotd: { - ...base.sotd, - defaultCRDate: '02 December 2023', + invalidDate: { + ...base, + sotd: { + ...base.sotd, + defaultCRDate: '02 December 2023', + }, }, - }, -}); + }; +} -exports.buildTodaysDate = base => ({ - noDateDetected: { - ...base, - config: { - ...base.config, - isEchidna: false, - }, - header: { - ...base.header, - defaultDate: '', - }, - }, - wrongDate: { - ...base, - config: { - ...base.config, - isEchidna: false, +export function buildTodaysDate(base) { + return { + noDateDetected: { + ...base, + config: { + ...base.config, + isEchidna: false, + }, + header: { + ...base.header, + defaultDate: '', + }, }, - header: { - ...base.header, - defaultDate: '04 November 2019', + wrongDate: { + ...base, + config: { + ...base.config, + isEchidna: false, + }, + header: { + ...base.header, + defaultDate: '04 November 2019', + }, }, - }, -}); + }; +} -exports.buildDraftStability = base => ({ - noDraftEither: { - ...base, - sotd: { - ...base.sotd, - draftText: - 'This is a other document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.', +export function buildDraftStability(base) { + return { + noDraftEither: { + ...base, + sotd: { + ...base.sotd, + draftText: + 'This is a other document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.', + }, }, - }, - noDraft: { - ...base, - sotd: { - ...base.sotd, - draftText: - 'This is a other document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.', + noDraft: { + ...base, + sotd: { + ...base.sotd, + draftText: + 'This is a other document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.', + }, }, - }, -}); + }; +} -exports.buildNewFeatures = base => ({ - noWarning: { - ...base, - }, - noLink: { - ...base, - sotd: { - ...base.sotd, - newFeatures: { - show: true, - text: `Future updates to this ${ - base.config.status === 'PR' - ? 'specification' - : 'Recommendation' - } may incorporate new features.`, +export function buildNewFeatures(base) { + return { + noWarning: { + ...base, + }, + noLink: { + ...base, + sotd: { + ...base.sotd, + newFeatures: { + show: true, + text: `Future updates to this ${ + base.config.status === 'PR' + ? 'specification' + : 'Recommendation' + } may incorporate new features.`, + }, }, }, - }, -}); + }; +} diff --git a/test/doc-views/specBase.js b/test/doc-views/specBase.js index 0f6002765..edfd57ef7 100644 --- a/test/doc-views/specBase.js +++ b/test/doc-views/specBase.js @@ -1,4 +1,4 @@ -exports.data = { +export const data = { bodyClassNames: 'h-entry', scripts: ['https://www.w3.org/scripts/TR/2021/fixup.js'], head: { @@ -239,732 +239,734 @@ exports.data = { }, }; -exports.buildCommonViewData = base => ({ - 'div-head': { - noHead: { - ...base, - header: { - ...base.header, - headClassName: 'foo', - }, - }, - }, - hr: { - noHr: { - ...base, - header: { - ...base.header, - hr: { - show: false, - }, - }, - }, - duplicatedHr: { - ...base, - hr: { - ...base.header.hr, - show: true, - }, - }, - }, - logo: { - noLogo: { - ...base, - header: { - ...base.header, - logo: { - show: false, - }, - }, - }, - invalidSrc: { - ...base, - header: { - ...base.header, - logo: { - ...base.logo, - src: 'http://invalid/source', - }, - }, - }, - invalidHref: { - ...base, - header: { - ...base.header, - logo: { - ...base.logo, - href: 'http://invalid/href', - }, - }, - }, - }, - 'h1-title': { - noHeadTitle: { - ...base, - head: { - ...base.head, - title: { - show: false, - }, - }, - }, - noH1Title: { - ...base, - header: { - ...base.header, - title: { - show: false, - }, - }, - }, - noH1AndHeadTitle: { - ...base, - head: { - ...base.head, - title: { - show: false, - }, - }, - header: { - ...base.header, - title: { - show: false, - }, - }, - }, - titlesNotMatch: { - ...base, - head: { - ...base.head, - title: { - ...base.head.title, - suffix: 'not match to h1', +export function buildCommonViewData(base) { + return { + 'div-head': { + noHead: { + ...base, + header: { + ...base.header, + headClassName: 'foo', }, }, }, - }, - 'details-summary': { - noDetails: { - ...base, - header: { - ...base.header, - details: { - show: false, + hr: { + noHr: { + ...base, + header: { + ...base.header, + hr: { + show: false, + }, }, }, - }, - noDetailsOpen: { - ...base, - header: { - ...base.header, - details: { - ...base.header.details, - open: '', + duplicatedHr: { + ...base, + hr: { + ...base.header.hr, + show: true, }, }, }, - noDetailsDl: { - ...base, - dl: { - show: false, - }, - }, - noDetailsSummary: { - ...base, - header: { - ...base.header, - summary: { + logo: { + noLogo: { + ...base, + header: { + ...base.header, + logo: { + show: false, + }, + }, + }, + invalidSrc: { + ...base, + header: { + ...base.header, + logo: { + ...base.logo, + src: 'http://invalid/source', + }, + }, + }, + invalidHref: { + ...base, + header: { + ...base.header, + logo: { + ...base.logo, + href: 'http://invalid/href', + }, + }, + }, + }, + 'h1-title': { + noHeadTitle: { + ...base, + head: { + ...base.head, + title: { + show: false, + }, + }, + }, + noH1Title: { + ...base, + header: { + ...base.header, + title: { + show: false, + }, + }, + }, + noH1AndHeadTitle: { + ...base, + head: { + ...base.head, + title: { + show: false, + }, + }, + header: { + ...base.header, + title: { + show: false, + }, + }, + }, + titlesNotMatch: { + ...base, + head: { + ...base.head, + title: { + ...base.head.title, + suffix: 'not match to h1', + }, + }, + }, + }, + 'details-summary': { + noDetails: { + ...base, + header: { + ...base.header, + details: { + show: false, + }, + }, + }, + noDetailsOpen: { + ...base, + header: { + ...base.header, + details: { + ...base.header.details, + open: '', + }, + }, + }, + noDetailsDl: { + ...base, + dl: { show: false, }, }, - }, - wrongDetailsSummary: { - ...base, - header: { - ...base.header, - summary: { - ...base.header.summary, - text: 'wrong text', + noDetailsSummary: { + ...base, + header: { + ...base.header, + summary: { + show: false, + }, }, }, - }, - }, - dl: { - wrongThisVersionHead: { - ...base, - dl: { - ...base.dl, - thisVersion: { - ...base.dl.thisVersion, - text: 'wrong this version head', + wrongDetailsSummary: { + ...base, + header: { + ...base.header, + summary: { + ...base.header.summary, + text: 'wrong text', + }, + }, + }, + }, + dl: { + wrongThisVersionHead: { + ...base, + dl: { + ...base.dl, + thisVersion: { + ...base.dl.thisVersion, + text: 'wrong this version head', + }, + }, + }, + wrongLatestVersionHead: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.latestVersion, + text: 'wrong latest version key', + }, + }, + }, + wrongHistoryHead: { + ...base, + dl: { + ...base.dl, + historyText: 'wrong one', + }, + }, + rescinds: { + ...base, + config: { + ...base.config, + isRescinded: false, + }, + }, + noRescindsNeeded: { + ...base, + config: { + ...base.config, + isRescinded: true, + }, + }, + obsoletes: { + ...base, + }, + noObsoletesNeeded: { + ...base, + config: { + ...base.config, + isObsolete: true, + }, + }, + supersedes: { + ...base, + }, + noSupersedesNeeded: { + ...base, + config: { + ...base.config, + isSuperseded: true, + }, + }, + wrongThisAndLatestOrder: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + show: false, + showAhead: true, + }, + }, + }, + wrongLatestAndRescindsOrder: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + show: false, + showBehind: true, + }, + }, + config: { + ...base.config, + isRescinded: true, + }, + }, + wrongLatestAndObsoletesOrder: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + show: false, + showBehind: true, + }, + }, + config: { + ...base.config, + isObsolete: true, + }, + }, + wrongLatestAndSupersedesOrder: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + show: false, + showBehind: true, + }, + }, + config: { + ...base.config, + isSuperseded: true, + }, + }, + noThisLinkExist: { + ...base, + dl: { + ...base.dl, + thisVersion: { + ...base.dl.thisVersion, + showHref: false, + }, + }, + }, + wrongThisDate: { + ...base, + header: { + ...base.header, + defaultDate: '04 October 2021', + }, + }, + noDocDate: { + ...base, + config: { + ...base.config, + isEchidna: false, + }, + header: { + ...base.header, + defaultDate: '', + }, + }, + wrongThisSyntax: { + ...base, + config: { + ...base.config, + status: 'FWD', + }, + }, + noLatestLinkExist: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + showHref: false, + }, + }, + }, + wrongLatestSyntax: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + docType: 'FAKE', + textDocType: 'FAKE', + }, + }, + }, + linkDiff: { + ...base, + dl: { + ...base.dl, + latestVersion: { + ...base.dl.latestVersion, + textDocType: 'FAKE', + }, + }, + }, + diffThisAndLatestShortname: { + ...base, + dl: { + ...base.dl, + seriesShortName: 'fake-hr-time', + }, + }, + noHistoryLinkExist: { + ...base, + dl: { + ...base.dl, + history: { + ...base.dl.history, + showHref: false, + }, + }, + }, + wrongHistorySyntax: { + ...base, + dl: { + ...base.dl, + history: { + ...base.dl.history, + shortName: 'fake-name', + }, + }, + }, + noRescindLinkExist: { + ...base, + config: { + ...base.config, + isRescinded: true, + }, + dl: { + ...base.dl, + rescind: { + ...base.dl.rescind, + showHref: false, + }, + }, + }, + diffThisAndRescindShortname: { + ...base, + config: { + ...base.config, + isRescinded: true, + }, + dl: { + ...base.dl, + rescindLink: + 'https://www.w3.org/TR/2017/REC-fake-name-20170101/', + }, + }, + wrongRescindSyntax: { + ...base, + config: { + ...base.config, + isRescinded: true, + }, + dl: { + ...base.dl, + rescindLink: + 'https://www.w3.org/FAKE/2017/REC-fake-name-20170101/', + }, + }, + noObsoletesLinkExist: { + ...base, + config: { + ...base.config, + isObsolete: true, + }, + dl: { + ...base.dl, + obsolete: { + ...base.dl.obsolete, + showHref: false, + }, + }, + }, + diffThisAndObsoletesShortname: { + ...base, + config: { + ...base.config, + isObsolete: true, + }, + dl: { + ...base.dl, + obsoleteLink: + 'https://www.w3.org/TR/2017/REC-fake-name-20170101/', + }, + }, + wrongObsoletesSyntax: { + ...base, + config: { + ...base.config, + isObsolete: true, + }, + dl: { + ...base.dl, + obsoleteLink: + 'https://www.w3.org/FAKE/2017/REC-fake-name-20170101/', + }, + }, + noSupersedesLinkExist: { + ...base, + config: { + ...base.config, + isSuperseded: true, + }, + dl: { + ...base.dl, + supersede: { + ...base.dl.supersede, + showHref: false, + }, + }, + }, + diffThisAndSupersedesShortname: { + ...base, + config: { + ...base.config, + isSuperseded: true, + }, + dl: { + ...base.dl, + supersedeLink: + 'https://www.w3.org/TR/2017/REC-fake-name-20170101/', + }, + }, + wrongSupersedesSyntax: { + ...base, + config: { + ...base.config, + isSuperseded: true, + }, + dl: { + ...base.dl, + supersedeLink: + 'https://www.w3.org/FAKE/2017/REC-hr-time-20170101/', + }, + }, + noEditorDraftLinkExist: { + ...base, + dl: { + ...base.dl, + latestEditor: { + ...base.dl.latestEditor, + showHref: false, + }, + }, + }, + noSecureEditorDraftLink: { + ...base, + dl: { + ...base.dl, + latestEditor: { + ...base.dl.latestEditor, + linkProtocol: 'http', + }, + }, + }, + noEditor: { + ...base, + dl: { + ...base.dl, + editor: { + ...base.dl.editor, + show: false, + }, + }, + }, + missingEditorId: { + ...base, + dl: { + ...base.dl, + editor: { + ...base.dl.editor, + id: '', + }, + }, + }, + }, + secno: { + noSecno: { + ...base, + secno: '', + }, + }, + 'ol-toc': { + noToc: { + ...base, + tocs: [], + }, + }, + 'h2-toc': { + mixedTocs: { + ...base, + tocs: [ + base.tocs[0], + { + ...base.tocs[0], + tag: 'div', + }, + ], + }, + notHtml5: { + ...base, + tocs: [ + { + ...base.tocs[0], + tag: 'div', + }, + ], + }, + noTocs: { + ...base, + tocs: [], + }, + noTitles: { + ...base, + tocs: [ + { + ...base.tocs[0], + titles: [], + }, + ], + }, + duplicatedTitle: { + ...base, + tocs: [ + { + ...base.tocs[0], + titles: ['Table of Contents', 'Table of Contents'], + }, + ], + }, + }, + sheet: { + noSheet: { + ...base, + head: { + ...base.head, + styleSheet: { + show: false, + }, + }, + }, + notLast: { + ...base, + head: { + ...base.head, + styleSheet: { + ...base.head.styleSheet, + showAnother: true, + }, }, }, }, - wrongLatestVersionHead: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.latestVersion, - text: 'wrong latest version key', + meta: { + noMeta: { + ...base, + head: { + ...base.head, + meta: { + show: false, + }, }, }, - }, - wrongHistoryHead: { - ...base, - dl: { - ...base.dl, - historyText: 'wrong one', - }, - }, - rescinds: { - ...base, - config: { - ...base.config, - isRescinded: false, - }, - }, - noRescindsNeeded: { - ...base, - config: { - ...base.config, - isRescinded: true, - }, - }, - obsoletes: { - ...base, - }, - noObsoletesNeeded: { - ...base, - config: { - ...base.config, - isObsolete: true, - }, - }, - supersedes: { - ...base, - }, - noSupersedesNeeded: { - ...base, - config: { - ...base.config, - isSuperseded: true, - }, - }, - wrongThisAndLatestOrder: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, - show: false, - showAhead: true, + noWidth: { + ...base, + head: { + ...base.head, + meta: { + ...base.head.meta, + width: '', + }, }, }, }, - wrongLatestAndRescindsOrder: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, - show: false, - showBehind: true, - }, - }, - config: { - ...base.config, - isRescinded: true, + 'body-toc-sidebar': { + classFound: { + ...base, + bodyClassNames: 'toc-sidebar', }, }, - wrongLatestAndObsoletesOrder: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, - show: false, - showBehind: true, - }, - }, - config: { - ...base.config, - isObsolete: true, + script: { + noScript: { + ...base, + scripts: [], }, }, - wrongLatestAndSupersedesOrder: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, + 'back-to-top': { + noBackToTop: { + ...base, + backToTop: { show: false, - showBehind: true, - }, - }, - config: { - ...base.config, - isSuperseded: true, - }, - }, - noThisLinkExist: { - ...base, - dl: { - ...base.dl, - thisVersion: { - ...base.dl.thisVersion, - showHref: false, - }, - }, - }, - wrongThisDate: { - ...base, - header: { - ...base.header, - defaultDate: '04 October 2021', - }, - }, - noDocDate: { - ...base, - config: { - ...base.config, - isEchidna: false, - }, - header: { - ...base.header, - defaultDate: '', - }, - }, - wrongThisSyntax: { - ...base, - config: { - ...base.config, - status: 'FWD', - }, - }, - noLatestLinkExist: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, - showHref: false, }, }, }, - wrongLatestSyntax: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, - docType: 'FAKE', - textDocType: 'FAKE', - }, + 'date-format': { + wrongDateFormat: { + ...base, + showWrongDateFormat: true, }, }, - linkDiff: { - ...base, - dl: { - ...base.dl, - latestVersion: { - ...base.dl.latestVersion, - textDocType: 'FAKE', + wcag: {}, + reliability: { + hasUnreliableLinks: { + ...base, + header: { + ...base.header, + logo: { + ...base.header.logo, + href: 'http://www.w3c-test.org/foo/bar.jpg', + }, }, }, }, - diffThisAndLatestShortname: { - ...base, - dl: { - ...base.dl, - seriesShortName: 'fake-hr-time', - }, - }, - noHistoryLinkExist: { - ...base, - dl: { - ...base.dl, - history: { - ...base.dl.history, - showHref: false, - }, - }, - }, - wrongHistorySyntax: { - ...base, - dl: { - ...base.dl, - history: { - ...base.dl.history, - shortName: 'fake-name', - }, - }, - }, - noRescindLinkExist: { - ...base, - config: { - ...base.config, - isRescinded: true, - }, - dl: { - ...base.dl, - rescind: { - ...base.dl.rescind, - showHref: false, - }, - }, - }, - diffThisAndRescindShortname: { - ...base, - config: { - ...base.config, - isRescinded: true, - }, - dl: { - ...base.dl, - rescindLink: - 'https://www.w3.org/TR/2017/REC-fake-name-20170101/', - }, - }, - wrongRescindSyntax: { - ...base, - config: { - ...base.config, - isRescinded: true, - }, - dl: { - ...base.dl, - rescindLink: - 'https://www.w3.org/FAKE/2017/REC-fake-name-20170101/', - }, - }, - noObsoletesLinkExist: { - ...base, - config: { - ...base.config, - isObsolete: true, - }, - dl: { - ...base.dl, - obsolete: { - ...base.dl.obsolete, - showHref: false, - }, - }, - }, - diffThisAndObsoletesShortname: { - ...base, - config: { - ...base.config, - isObsolete: true, - }, - dl: { - ...base.dl, - obsoleteLink: - 'https://www.w3.org/TR/2017/REC-fake-name-20170101/', - }, - }, - wrongObsoletesSyntax: { - ...base, - config: { - ...base.config, - isObsolete: true, - }, - dl: { - ...base.dl, - obsoleteLink: - 'https://www.w3.org/FAKE/2017/REC-fake-name-20170101/', - }, - }, - noSupersedesLinkExist: { - ...base, - config: { - ...base.config, - isSuperseded: true, - }, - dl: { - ...base.dl, - supersede: { - ...base.dl.supersede, - showHref: false, - }, - }, - }, - diffThisAndSupersedesShortname: { - ...base, - config: { - ...base.config, - isSuperseded: true, - }, - dl: { - ...base.dl, - supersedeLink: - 'https://www.w3.org/TR/2017/REC-fake-name-20170101/', - }, - }, - wrongSupersedesSyntax: { - ...base, - config: { - ...base.config, - isSuperseded: true, - }, - dl: { - ...base.dl, - supersedeLink: - 'https://www.w3.org/FAKE/2017/REC-hr-time-20170101/', - }, - }, - noEditorDraftLinkExist: { - ...base, - dl: { - ...base.dl, - latestEditor: { - ...base.dl.latestEditor, - showHref: false, - }, - }, - }, - noSecureEditorDraftLink: { - ...base, - dl: { - ...base.dl, - latestEditor: { - ...base.dl.latestEditor, - linkProtocol: 'http', - }, - }, - }, - noEditor: { - ...base, - dl: { - ...base.dl, - editor: { - ...base.dl.editor, - show: false, - }, - }, - }, - missingEditorId: { - ...base, - dl: { - ...base.dl, - editor: { - ...base.dl.editor, + 'section-ids': { + noSectionId: { + ...base, + sotd: { + ...base.sotd, id: '', }, }, }, - }, - secno: { - noSecno: { - ...base, - secno: '', - }, - }, - 'ol-toc': { - noToc: { - ...base, - tocs: [], - }, - }, - 'h2-toc': { - mixedTocs: { - ...base, - tocs: [ - base.tocs[0], - { - ...base.tocs[0], - tag: 'div', - }, - ], - }, - notHtml5: { - ...base, - tocs: [ - { - ...base.tocs[0], - tag: 'div', - }, - ], - }, - noTocs: { - ...base, - tocs: [], - }, - noTitles: { - ...base, - tocs: [ - { - ...base.tocs[0], - titles: [], - }, - ], - }, - duplicatedTitle: { - ...base, - tocs: [ - { - ...base.tocs[0], - titles: ['Table of Contents', 'Table of Contents'], - }, - ], - }, - }, - sheet: { - noSheet: { - ...base, - head: { - ...base.head, - styleSheet: { - show: false, + h2: { + wrongAbstractH2: { + ...base, + abstract: { + ...base.abstract, + abstractText: 'foo', }, }, - }, - notLast: { - ...base, - head: { - ...base.head, - styleSheet: { - ...base.head.styleSheet, - showAnother: true, + wrongSotdH2: { + ...base, + sotd: { + ...base.sotd, + title: 'wrong sotd title', }, }, - }, - }, - meta: { - noMeta: { - ...base, - head: { - ...base.head, - meta: { - show: false, - }, + wrongTocH2: { + ...base, + tocs: [ + { + ...base.tocs[0], + titles: ['wrong toc title'], + }, + ], }, }, - noWidth: { - ...base, - head: { - ...base.head, - meta: { - ...base.head.meta, - width: '', + canonical: { + noCanonical: { + ...base, + head: { + ...base.head, + showCanonical: false, }, }, }, - }, - 'body-toc-sidebar': { - classFound: { - ...base, - bodyClassNames: 'toc-sidebar', - }, - }, - script: { - noScript: { - ...base, - scripts: [], - }, - }, - 'back-to-top': { - noBackToTop: { - ...base, - backToTop: { - show: false, - }, - }, - }, - 'date-format': { - wrongDateFormat: { - ...base, - showWrongDateFormat: true, - }, - }, - wcag: {}, - reliability: { - hasUnreliableLinks: { - ...base, - header: { - ...base.header, - logo: { - ...base.header.logo, - href: 'http://www.w3c-test.org/foo/bar.jpg', + supersedable: { + noIntro: { + ...base, + sotd: { + ...base.sotd, + emHTML: 'This section not the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.', }, }, - }, - }, - 'section-ids': { - noSectionId: { - ...base, - sotd: { - ...base.sotd, - id: '', - }, - }, - }, - h2: { - wrongAbstractH2: { - ...base, - abstract: { - ...base.abstract, - abstractText: 'foo', - }, - }, - wrongSotdH2: { - ...base, - sotd: { - ...base.sotd, - title: 'wrong sotd title', - }, - }, - wrongTocH2: { - ...base, - tocs: [ - { - ...base.tocs[0], - titles: ['wrong toc title'], + noTr: { + ...base, + sotd: { + ...base.sotd, + emHTML: "This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.", }, - ], - }, - }, - canonical: { - noCanonical: { - ...base, - head: { - ...base.head, - showCanonical: false, - }, - }, - }, - supersedable: { - noIntro: { - ...base, - sotd: { - ...base.sotd, - emHTML: 'This section not the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.', }, }, - noTr: { - ...base, - sotd: { - ...base.sotd, - emHTML: "This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.", + html: { + skipValidation: { + ...base, }, }, - }, - html: { - skipValidation: { - ...base, - }, - }, - neutral: { - hasNeutral: { - ...base, - header: { - ...base.header, - summary: { - ...base.header.summary, - text: 'More details about this document master', + neutral: { + hasNeutral: { + ...base, + header: { + ...base.header, + summary: { + ...base.header.summary, + text: 'More details about this document master', + }, }, }, }, - }, -}); + }; +} diff --git a/test/l10n.js b/test/l10n.js index 146905455..97858e650 100644 --- a/test/l10n.js +++ b/test/l10n.js @@ -2,18 +2,20 @@ * Test L10n features. */ -/* globals expect: true */ - // Native packages: -const fs = require('fs'); - // External packages: -const chai = require('chai'); -const chaiAsPromised = require('chai-as-promised'); +// eslint-disable-next-line node/no-unpublished-import +import chai from 'chai'; +// eslint-disable-next-line node/no-unpublished-import +import chaiAsPromised from 'chai-as-promised'; +import fs from 'fs'; +import * as l10n from '../lib/l10n-en_GB.js'; +import { importJSON } from '../lib/util.js'; // Internal packages: -const rules = require('../lib/rules.json'); -const l10n = require('../lib/l10n-en_GB'); +const rules = importJSON('../lib/rules.json', import.meta.url); + +const { expect } = chai; // Constants: const { messages } = l10n; @@ -27,7 +29,6 @@ const exceptionFinder = /emits\s*:\s*["']([^()"'{}]+)["']/g; const setUp = function () { chai.use(chaiAsPromised); - expect = chai.expect; }; /** @@ -204,8 +205,9 @@ describe('L10n', () => { describe('UI messages module', () => { it('“lib/rules-wrapper” should be a valid object', () => expect(rules).to.be.an('object')); - it('“lib/l10n-en_GB” should be a valid object', () => - expect(l10n).to.be.an('object')); + it('“lib/l10n-en_GB” should be a valid object', () => { + expect(typeof l10n).to.equal('object'); + }); }); describe('Consistency between rules and L10n messages', () => { diff --git a/test/rules.js b/test/rules.js index f048b0393..186e93e75 100644 --- a/test/rules.js +++ b/test/rules.js @@ -1,4 +1,28 @@ -/* eslint-disable import/no-dynamic-require */ +// Native packages: +// eslint-disable-next-line node/no-unpublished-import +import { expect as chai } from 'chai'; +// eslint-disable-next-line node/no-unpublished-import +import expect from 'expect.js'; +// External packages: +import express from 'express'; +import exphbs from 'express-handlebars'; +import { lstatSync, readdirSync } from 'fs'; +// eslint-disable-next-line node/no-unpublished-import +import nock from 'nock'; +import pth, { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { Sink } from '../lib/sink.js'; +import { allProfiles } from '../lib/util.js'; +// Internal packages: +import { Specberus } from '../lib/validator.js'; +// A list of good documents to be tested, using all rules configured in the profiles. +// Shouldn't cause any error. +import { goodDocuments } from './data/goodDocuments.js'; +import { samples } from './samples.js'; + +// eslint-disable-next-line no-underscore-dangle +const __dirname = dirname(fileURLToPath(import.meta.url)); + /** * Test the rules. */ @@ -8,21 +32,6 @@ const DEBUG = process.env.DEBUG || false; const DEFAULT_PORT = 8001; const PORT = process.env.PORT || DEFAULT_PORT; const ENDPOINT = `http://localhost:${PORT}`; -// Native packages: -const pth = require('path'); -const { readdirSync, lstatSync } = require('fs'); - -// External packages: -const express = require('express'); -const expect = require('expect.js'); -const chai = require('chai').expect; -const exphbs = require('express-handlebars'); - -// Internal packages: -const { Specberus } = require('../lib/validator'); -const { Sink } = require('../lib/sink'); -const util = require('../lib/util'); -const { samples } = require('./samples'); /** * Compare two arrays of "deliverer IDs" and check that they're equivalent. @@ -197,26 +206,33 @@ function renderByConfig(req, res) { : req.params.profile; // get data for template from json (.js) - const data = require(pth.join( + const path = pth.join( __dirname, `./doc-views/${req.params.docType}/${suffix}.js` - )); - - let finalData; - if (!type) - res.send('

    Error: please add the parameter "type" in the URL

    '); - else if (type.startsWith('good')) { - finalData = data[type]; - } else { - if (!rule) + ); + + // eslint-disable-next-line node/no-unsupported-features/es-syntax + import(path).then(module => { + const data = module.default; + + let finalData; + if (!type) res.send( - '

    Error: please add the parameter "rule" in the URL

    ' + '

    Error: please add the parameter "type" in the URL

    ' ); - - // for data causes error, make rule and the type of error specific. - finalData = data[rule][type]; - } - res.render(pth.join(__dirname, './doc-views/layout/spec'), finalData); + else if (type.startsWith('good')) { + finalData = data[type]; + } else { + if (!rule) + res.send( + '

    Error: please add the parameter "rule" in the URL

    ' + ); + + // for data causes error, make rule and the type of error specific. + finalData = data[rule][type]; + } + res.render(pth.join(__dirname, './doc-views/layout/spec'), finalData); + }); } app.get('/doc-views/:docType/:track/:profile', renderByConfig); @@ -243,20 +259,19 @@ app.get('/docs/links/image/logo-redirection-3', (req, res) => { let server; -before(() => { - server = app.listen(PORT); +before(done => { + server = app.listen(PORT, done); }); -after(() => { +after(done => { if (server) { - server.close(); + server.close(done); } }); function buildHandler(test, mock, done) { const handler = new Sink(); - const nock = require('nock'); if (mock) { // Mock some external calls to speed up the test suite nock('https://www.w3.org', { allowUnmocked: true }) @@ -431,10 +446,6 @@ function buildHandler(test, mock, done) { return handler; } -// A list of good documents to be tested, using all rules configured in the profiles. -// Shouldn't cause any error. -const { goodDocuments } = require('./data/goodDocuments'); - const testsGoodDoc = goodDocuments; // The next check is running each profile using the rules configured. @@ -445,64 +456,90 @@ describe('Making sure good documents pass Specberus...', () => { const url = `${ENDPOINT}/${testsGoodDoc[docProfile].url}`; it(`should pass for ${docProfile} doc with ${url}`, done => { - const profilePath = util.allProfiles.find(p => + const profilePath = allProfiles.find(p => p.endsWith(`/${docProfile}.js`) ); - const profile = require(`../lib/profiles/${profilePath}`); - - // add custom config to test - profile.config = { - patentPolicy: 'pp2020', // default config for all docs. - ...profile.config, - ...testsGoodDoc[docProfile].config, - }; - - // remove unnecessary rules from test - const { removeRules } = require('../lib/profiles/profileUtil'); - const rules = removeRules(profile.rules, [ - 'validation.html', - 'validation.wcag', - 'links.linkchecker', // too slow. will check separately. - ]); - - const options = { - profile: { + // eslint-disable-next-line node/no-unsupported-features/es-syntax + import(`../lib/profiles/${profilePath}`).then(profile => { + // add custom config to test + const extendedProfile = { ...profile, - rules, // do not change profile.rules - }, - events: buildHandler({ ignoreWarnings: true }, false, done), - url, - }; - - // for (const o in test.options) options[o] = test.options[o]; - new Specberus(process.env.W3C_API_KEY).validate(options); + config: { + patentPolicy: 'pp2020', // default config for all docs. + ...profile.config, + ...testsGoodDoc[docProfile].config, + }, + }; + + // remove unnecessary rules from test + // eslint-disable-next-line node/no-unsupported-features/es-syntax + import('../lib/profiles/profileUtil.js').then( + ({ removeRules }) => { + const rules = removeRules(extendedProfile.rules, [ + 'validation.html', + 'validation.wcag', + 'links.linkchecker', // too slow. will check separately. + ]); + + const options = { + profile: { + ...extendedProfile, + rules, // do not change profile.rules + }, + events: buildHandler( + { ignoreWarnings: true }, + false, + done + ), + url, + }; + + // for (const o in test.options) options[o] = test.options[o]; + new Specberus(process.env.W3C_API_KEY).validate( + options + ); + } + ); + }); }); }); }); function checkRule(tests, options) { const { docType, track, profile, category, rule } = options; + tests.forEach(test => { const passOrFail = !test.errors ? 'pass' : 'fail'; const suffix = track ? `${track}/${profile}` : profile; const url = `${ENDPOINT}/doc-views/${docType}/${suffix}?rule=${rule}&type=${test.data}`; - const { config } = require(`../lib/profiles/${docType}/${suffix}`); it(`should ${passOrFail} for ${url}`, done => { - const options = { - url, - profile: { - name: `Synthetic ${profile}/${rule}`, - rules: [require(`../lib/rules/${category}/${rule}`)], - config: { - ...config, - ...test.config, - }, - }, - events: buildHandler(test, true, done), - ...test.options, - }; - new Specberus(process.env.W3C_API_KEY).validate(options); + // eslint-disable-next-line node/no-unsupported-features/es-syntax + import(`../lib/profiles/${docType}/${suffix}.js`).then( + ({ config }) => { + // eslint-disable-next-line node/no-unsupported-features/es-syntax + import(`../lib/rules/${category}/${rule}.js`).then( + ruleModule => { + const options = { + url, + profile: { + name: `Synthetic ${profile}/${rule}`, + rules: [ruleModule], + config: { + ...config, + ...test.config, + }, + }, + events: buildHandler(test, true, done), + ...test.options, + }; + new Specberus(process.env.W3C_API_KEY).validate( + options + ); + } + ); + } + ); }); }); } @@ -515,24 +552,63 @@ function listFilesOf(dir) { return files.filter(v => !blocklist.find(b => v.includes(b))); } -function runTestsForProfile(file, { docType, track }) { +const flat = objs => objs.reduce((acc, cur) => ({ ...acc, ...cur }), {}); + +const buildProfileTestCases = async path => { + // eslint-disable-next-line node/no-unsupported-features/es-syntax + const { rules } = await import(path); + return rules; +}; + +const buildTrackTestCases = async path => { + if (lstatSync(path).isFile()) { + const profile = await buildProfileTestCases(path); + return profile; + } + + const profiles = await Promise.all( + listFilesOf(path).map(async profile => ({ + [profile]: await buildProfileTestCases(`${path}/${profile}`), + })) + ); + + return flat(profiles); +}; + +const buildDocTypeTestCases = async path => { + const tracks = await Promise.all( + listFilesOf(path).map(async track => ({ + [track]: await buildTrackTestCases(`${path}/${track}`), + })) + ); + + return flat(tracks); +}; + +const buildBadTestCases = async () => { const base = `${process.cwd()}/test/data`; - const lastDot = file.lastIndexOf('.'); - const profile = file.substring(0, lastDot); + const docTypes = await Promise.all( + listFilesOf(base) + .filter(v => lstatSync(`${base}/${v}`).isDirectory()) + .map(async docType => ({ + [docType]: await buildDocTypeTestCases(`${base}/${docType}`), + })) + ); + + return flat(docTypes); +}; +function runTestsForProfile({ docType, track, profile, rules }) { // Profile: CR/NOTE/RY ... describe(`Profile: ${profile}`, () => { - const suffix = track ? `${track}/${file}` : file; - const config = require(`${base}/${docType}/${suffix}`); - - Object.entries(config.rules).forEach(([category, rules]) => { + Object.entries(rules).forEach(([category, rules]) => { Object.entries(rules).forEach(([rule, tests]) => { // Rule: hr/logo ... describe(`Rule: ${category}.${rule}`, () => { checkRule(tests, { docType, track, - profile, + profile: profile.substring(0, profile.lastIndexOf('.')), category, rule, }); @@ -542,31 +618,39 @@ function runTestsForProfile(file, { docType, track }) { }); } +const badTestCases = await buildBadTestCases(); + // The next check runs every rule for each profile, one rule at a time, and should trigger every existing errors and warnings in lib/l10n-en_GB.js describe('Making sure Specberus is not broken...', () => { - const base = `${process.cwd()}/test/data`; - listFilesOf(base) - .filter(v => lstatSync(`${base}/${v}`).isDirectory()) - .forEach(docType => { - // DocType: TR/SUMB - describe(`DocType: ${docType}:`, () => { - listFilesOf(`${base}/${docType}`).forEach(track => { - const isProfile = lstatSync( - `${base}/${docType}/${track}` - ).isFile(); - + Object.entries(badTestCases).forEach(([docType, tracksOrProfiles]) => { + // DocType: TR/SUMB + describe(`DocType: ${docType}`, () => { + Object.entries(tracksOrProfiles).forEach( + ([trackOrProfile, profilesOrRules]) => { // Profile: SUBM - if (isProfile) { - runTestsForProfile(track, { docType }); + if (trackOrProfile === 'MEM-SUBM.js') { + runTestsForProfile({ + docType, + profile: trackOrProfile, + rules: profilesOrRules, + }); return; } + // Track: Note/Recommendation/Registry - describe(`Track: ${track}`, () => { - listFilesOf(`${base}/${docType}/${track}`).forEach( - file => runTestsForProfile(file, { docType, track }) + describe(`Track: ${trackOrProfile}`, () => { + Object.entries(profilesOrRules).forEach( + ([profile, rules]) => + runTestsForProfile({ + docType, + track: trackOrProfile, + profile, + rules, + }) ); }); - }); - }); + } + ); }); + }); }); diff --git a/test/samples.js b/test/samples.js index 5558baf4c..7cdecba2c 100644 --- a/test/samples.js +++ b/test/samples.js @@ -1,4 +1,4 @@ -exports.samples = [ +export const samples = [ { file: '2021-fpwd', profile: 'FPWD', diff --git a/test/validation.js b/test/validation.js index b98fc19dd..bf67436f7 100644 --- a/test/validation.js +++ b/test/validation.js @@ -9,13 +9,14 @@ * Travis documentation. */ -if ( +const shouldExportHTML = !process || !process.env || - (process.env.TRAVIS !== 'true' && !process.env.SKIP_NETWORK) -) { - exports.html = [ - { doc: 'validation/simple.html' }, - { doc: 'validation/invalid.html', errors: ['validation.html.error'] }, - ]; -} + (process.env.TRAVIS !== 'true' && !process.env.SKIP_NETWORK); + +export const html = shouldExportHTML + ? [ + { doc: 'validation/simple.html' }, + { doc: 'validation/invalid.html', errors: ['validation.html.error'] }, + ] + : []; diff --git a/tools/fetch-groups-db.js b/tools/fetch-groups-db.js index 522b53ea8..ed4228e22 100644 --- a/tools/fetch-groups-db.js +++ b/tools/fetch-groups-db.js @@ -3,10 +3,14 @@ // XXX also look at https://cvs.w3.org/Team/WWW/2000/04/mem-news/groups.rdf -const fs = require('fs'); -const pth = require('path'); -const ua = require('superagent'); -const { JSDOM } = require('jsdom'); +import fs from 'fs'; +import { JSDOM } from 'jsdom'; +import pth, { dirname } from 'path'; +import ua from 'superagent'; +import { fileURLToPath } from 'url'; + +// eslint-disable-next-line no-underscore-dangle +const __dirname = dirname(fileURLToPath(import.meta.url)); const user = process.argv[2]; const pass = process.argv[3]; diff --git a/tools/make-groups-db.js b/tools/make-groups-db.js index 3f0373980..dba5e538f 100644 --- a/tools/make-groups-db.js +++ b/tools/make-groups-db.js @@ -15,9 +15,15 @@ 'use strict'; -const fs = require('fs'); -const pth = require('path'); -const src = require('./groups-sparql.json'); +import fs from 'fs'; +import pth, { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { importJSON } from '../lib/util.js'; + +const src = importJSON('./groups-sparql.json'); + +// eslint-disable-next-line no-underscore-dangle +const __dirname = dirname(fileURLToPath(import.meta.url)); const res = {}; for (let i = 0, n = src.results.bindings.length; i < n; i += 1) {