diff --git a/src/constants.mjs b/src/constants.mjs index 473cf35b..040a8c10 100644 --- a/src/constants.mjs +++ b/src/constants.mjs @@ -6,423 +6,3 @@ export const DOC_NODE_VERSION = process.version; // This is the Node.js CHANGELOG to be consumed to generate a list of all major Node.js versions export const DOC_NODE_CHANGELOG_URL = 'https://raw.githubusercontent.com/nodejs/node/HEAD/CHANGELOG.md'; - -// This is the Node.js Base URL for viewing a file within GitHub UI -export const DOC_NODE_BLOB_BASE_URL = - 'https://github.com/nodejs/node/blob/HEAD/'; - -// This is the Node.js API docs base URL for editing a file on GitHub UI -export const DOC_API_BLOB_EDIT_BASE_URL = - 'https://github.com/nodejs/node/edit/main/doc/api/'; - -// Base URL for a specific Node.js version within the Node.js API docs -export const DOC_API_BASE_URL_VERSION = 'https://nodejs.org/docs/latest-v'; - -// This is the perma-link within the API docs that reference the Stability Index -export const DOC_API_STABILITY_SECTION_REF_URL = - 'documentation.html#stability-index'; - -// This is the base URL of the MDN Web documentation -export const DOC_MDN_BASE_URL = 'https://developer.mozilla.org/en-US/docs/Web/'; - -// This is the base URL for the MDN JavaScript documentation -export const DOC_MDN_BASE_URL_JS = `${DOC_MDN_BASE_URL}JavaScript/`; - -// This is the base URL for the MDN JavaScript primitives documentation -export const DOC_MDN_BASE_URL_JS_PRIMITIVES = `${DOC_MDN_BASE_URL_JS}Data_structures`; - -// This is the base URL for the MDN JavaScript global objects documentation -export const DOC_MDN_BASE_URL_JS_GLOBALS = `${DOC_MDN_BASE_URL_JS}Reference/Global_Objects/`; - -// These are YAML keys from the Markdown YAML metadata that should be -// removed and appended to the `update` key -export const DOC_API_YAML_KEYS_UPDATE = [ - 'added', - 'removed', - 'deprecated', - 'introduced_in', - 'napiVersion', -]; - -// These are string replacements specific to Node.js API docs for anchor IDs -export const DOC_API_SLUGS_REPLACEMENTS = [ - { from: /node.js/i, to: 'nodejs' }, // Replace Node.js - { from: /&/, to: '-and-' }, // Replace & - { from: /[/_,:;\\ ]/g, to: '-' }, // Replace /_,:;\. and whitespace - { from: /--+/g, to: '-' }, // Replace multiple hyphens with single - { from: /^-/, to: '' }, // Remove any leading hyphen - { from: /-$/, to: '' }, // Remove any trailing hyphen -]; - -// These are regular expressions used to determine if a given Markdown heading -// is a specific type of API Doc entry (e.g., Event, Class, Method, etc) -// and to extract the inner content of said Heading to be used as the API doc entry name -export const DOC_API_HEADING_TYPES = [ - { - type: 'method', - regex: - // Group 1: foo[bar]() - // Group 2: foo.bar() - // Group 3: foobar() - /^`?(?:\w*(?:(\[[^\]]+\])|(?:\.(\w+)))|(\w+))\([^)]*\)`?$/i, - }, - { type: 'event', regex: /^Event: +`?['"]?([^'"]+)['"]?`?$/i }, - { - type: 'class', - regex: - /^Class: +`?([A-Z]\w+(?:\.[A-Z]\w+)*(?: +extends +[A-Z]\w+(?:\.[A-Z]\w+)*)?)`?$/i, - }, - { - type: 'ctor', - regex: /^(?:Constructor: +)?`?new +([A-Z]\w+(?:\.[A-Z]\w+)*)\([^)]*\)`?$/i, - }, - { - type: 'classMethod', - regex: - /^Static method: +`?[A-Z]\w+(?:\.[A-Z]\w+)*(?:(\[\w+\.\w+\])|\.(\w+))\([^)]*\)`?$/i, - }, - { - type: 'property', - regex: - /^(?:Class property: +)?`?[A-Z]\w+(?:\.[A-Z]\w+)*(?:(\[\w+\.\w+\])|\.(\w+))`?$/i, - }, -]; - -// This is a mapping for the `API` updates within the Markdown content and their respective -// content that should be mapping into `changes` property for better mapping on HTML -export const DOC_API_UPDATE_MAPPING = { - added: 'Added in', - removed: 'Removed in', - deprecated: 'Deprecated since', - introduced_in: 'Introduced in', - napiVersion: 'N-API Version', -}; - -// This is a mapping for types within the Markdown content and their respective -// JavaScript primitive types within the MDN JavaScript docs -// @see DOC_MDN_BASE_URL_JS_PRIMITIVES -export const DOC_TYPES_MAPPING_PRIMITIVES = { - boolean: 'Boolean', - integer: 'Number', // Not a primitive, used for clarification. - null: 'Null', - number: 'Number', - string: 'String', - symbol: 'Symbol', - undefined: 'Undefined', -}; - -// https://github.com/nodejs/node/blob/main/doc/api/cli.md#options -// This slug should reference the section where the available -// options are defined. -export const DOC_SLUG_OPTIONS = 'options'; - -// https://github.com/nodejs/node/blob/main/doc/api/cli.md#environment-variables-1 -// This slug should reference the section where the available -// environment variables are defined. -export const DOC_SLUG_ENVIRONMENT = 'environment-variables-1'; - -// This is a mapping for types within the Markdown content and their respective -// JavaScript globals types within the MDN JavaScript docs -// @see DOC_MDN_BASE_URL_JS_GLOBALS -export const DOC_TYPES_MAPPING_GLOBALS = { - ...Object.fromEntries( - [ - 'AggregateError', - 'Array', - 'ArrayBuffer', - 'DataView', - 'Date', - 'Error', - 'EvalError', - 'Function', - 'Map', - 'NaN', - 'Object', - 'Promise', - 'Proxy', - 'RangeError', - 'ReferenceError', - 'RegExp', - 'Set', - 'SharedArrayBuffer', - 'SyntaxError', - 'Symbol', - 'TypeError', - 'URIError', - 'WeakMap', - 'WeakSet', - - 'TypedArray', - 'Float32Array', - 'Float64Array', - 'Int8Array', - 'Int16Array', - 'Int32Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'Uint16Array', - 'Uint32Array', - ].map(e => [e, e]) - ), - bigint: 'BigInt', - 'WebAssembly.Instance': 'WebAssembly/Instance', -}; - -// This is a mapping for types within the Markdown content and their respective -// Node.js types within the Node.js API docs (refers to a different API doc page) -// Note: These hashes are generated with the GitHub Slugger -export const DOC_TYPES_MAPPING_NODE_MODULES = { - AbortController: 'globals.html#class-abortcontroller', - AbortSignal: 'globals.html#class-abortsignal', - - AlgorithmIdentifier: 'webcrypto.html#class-algorithmidentifier', - AsyncHook: 'async_hooks.html#async_hookscreatehookcallbacks', - AsyncLocalStorage: 'async_context.html#class-asynclocalstorage', - AsyncResource: 'async_hooks.html#class-asyncresource', - - AesCbcParams: 'webcrypto.html#class-aescbcparams', - AesCtrParams: 'webcrypto.html#class-aesctrparams', - AesGcmParams: 'webcrypto.html#class-aesgcmparams', - AesKeyGenParams: 'webcrypto.html#class-aeskeygenparams', - - Blob: 'buffer.html#class-blob', - BroadcastChannel: - 'worker_threads.html#class-broadcastchannel-extends-eventtarget', - Buffer: 'buffer.html#class-buffer', - - ByteLengthQueuingStrategy: 'webstreams.html#class-bytelengthqueuingstrategy', - - Channel: 'diagnostics_channel.html#class-channel', - ChildProcess: 'child_process.html#class-childprocess', - Cipher: 'crypto.html#class-cipher', - ClientHttp2Session: 'http2.html#class-clienthttp2session', - ClientHttp2Stream: 'http2.html#class-clienthttp2stream', - - CountQueuingStrategy: 'webstreams.html#class-countqueuingstrategy', - - Crypto: 'webcrypto.html#class-crypto', - CryptoKey: 'webcrypto.html#class-cryptokey', - CryptoKeyPair: 'webcrypto.html#class-cryptokeypair', - - CustomEvent: 'events.html#class-customevent', - - Decipher: 'crypto.html#class-decipher', - DiffieHellman: 'crypto.html#class-diffiehellman', - DiffieHellmanGroup: 'crypto.html#class-diffiehellmangroup', - Domain: 'domain.html#class-domain', - - Duplex: 'stream.html#class-streamduplex', - - ECDH: 'crypto.html#class-ecdh', - EcdhKeyDeriveParams: 'webcrypto.html#class-ecdhkeyderiveparams', - EcdsaParams: 'webcrypto.html#class-ecdsaparams', - EcKeyGenParams: 'webcrypto.html#class-eckeygenparams', - EcKeyImportParams: 'webcrypto.html#class-eckeyimportparams', - Ed448Params: 'webcrypto.html#class-ed448params', - - Event: 'events.html#class-event', - EventEmitter: 'events.html#class-eventemitter', - EventListener: 'events.html#event-listener', - EventTarget: 'events.html#class-eventtarget', - - File: 'buffer.html#class-file', - FileHandle: 'fs.html#class-filehandle', - - Handle: 'net.html#serverlistenhandle-backlog-callback', - Hash: 'crypto.html#class-hash', - Histogram: 'perf_hooks.html#class-histogram', - HkdfParams: 'webcrypto.html#class-hkdfparams', - Hmac: 'crypto.html#class-hmac', - HmacImportParams: 'webcrypto.html#class-hmacimportparams', - HmacKeyGenParams: 'webcrypto.html#class-hmackeygenparams', - - Http2SecureServer: 'http2.html#class-http2secureserver', - Http2Server: 'http2.html#class-http2server', - Http2Session: 'http2.html#class-http2session', - Http2Stream: 'http2.html#class-http2stream', - - Immediate: 'timers.html#class-immediate', - - IntervalHistogram: - 'perf_hooks.html#class-intervalhistogram-extends-histogram', - - KeyObject: 'crypto.html#class-keyobject', - - MIMEParams: 'util.html#class-utilmimeparams', - MessagePort: 'worker_threads.html#class-messageport', - - MockModuleContext: 'test.html#class-mockmodulecontext', - - NodeEventTarget: 'events.html#class-nodeeventtarget', - - Pbkdf2Params: 'webcrypto.html#class-pbkdf2params', - PerformanceEntry: 'perf_hooks.html#class-performanceentry', - PerformanceNodeTiming: 'perf_hooks.html#class-performancenodetiming', - PerformanceObserver: 'perf_hooks.html#class-performanceobserver', - PerformanceObserverEntryList: - 'perf_hooks.html#class-performanceobserverentrylist', - - Readable: 'stream.html#class-streamreadable', - ReadableByteStreamController: - 'webstreams.html#class-readablebytestreamcontroller', - ReadableStream: 'webstreams.html#class-readablestream', - ReadableStreamBYOBReader: 'webstreams.html#class-readablestreambyobreader', - ReadableStreamBYOBRequest: 'webstreams.html#class-readablestreambyobrequest', - ReadableStreamDefaultController: - 'webstreams.html#class-readablestreamdefaultcontroller', - ReadableStreamDefaultReader: - 'webstreams.html#class-readablestreamdefaultreader', - - RecordableHistogram: - 'perf_hooks.html#class-recordablehistogram-extends-histogram', - - RsaHashedImportParams: 'webcrypto.html#class-rsahashedimportparams', - RsaHashedKeyGenParams: 'webcrypto.html#class-rsahashedkeygenparams', - RsaOaepParams: 'webcrypto.html#class-rsaoaepparams', - RsaPssParams: 'webcrypto.html#class-rsapssparams', - - ServerHttp2Session: 'http2.html#class-serverhttp2session', - ServerHttp2Stream: 'http2.html#class-serverhttp2stream', - - Sign: 'crypto.html#class-sign', - - StatementSync: 'sqlite.html#class-statementsync', - - Stream: 'stream.html#stream', - - SubtleCrypto: 'webcrypto.html#class-subtlecrypto', - - TestsStream: 'test.html#class-testsstream', - - TextDecoderStream: 'webstreams.html#class-textdecoderstream', - TextEncoderStream: 'webstreams.html#class-textencoderstream', - - Timeout: 'timers.html#class-timeout', - Timer: 'timers.html#timers', - - Tracing: 'tracing.html#tracing-object', - TracingChannel: 'diagnostics_channel.html#class-tracingchannel', - - Transform: 'stream.html#class-streamtransform', - TransformStream: 'webstreams.html#class-transformstream', - TransformStreamDefaultController: - 'webstreams.html#class-transformstreamdefaultcontroller', - - URL: 'url.html#the-whatwg-url-api', - URLSearchParams: 'url.html#class-urlsearchparams', - - Verify: 'crypto.html#class-verify', - - Writable: 'stream.html#class-streamwritable', - WritableStream: 'webstreams.html#class-writablestream', - WritableStreamDefaultController: - 'webstreams.html#class-writablestreamdefaultcontroller', - WritableStreamDefaultWriter: - 'webstreams.html#class-writablestreamdefaultwriter', - - Worker: 'worker_threads.html#class-worker', - - X509Certificate: 'crypto.html#class-x509certificate', - - 'brotli options': 'zlib.html#class-brotlioptions', - - 'cluster.Worker': 'cluster.html#class-worker', - - 'crypto.constants': 'crypto.html#cryptoconstants', - - 'dgram.Socket': 'dgram.html#class-dgramsocket', - - 'errors.Error': 'errors.html#class-error', - - 'fs.Dir': 'fs.html#class-fsdir', - 'fs.Dirent': 'fs.html#class-fsdirent', - 'fs.FSWatcher': 'fs.html#class-fsfswatcher', - 'fs.ReadStream': 'fs.html#class-fsreadstream', - 'fs.StatFs': 'fs.html#class-fsstatfs', - 'fs.Stats': 'fs.html#class-fsstats', - 'fs.StatWatcher': 'fs.html#class-fsstatwatcher', - 'fs.WriteStream': 'fs.html#class-fswritestream', - - 'http.Agent': 'http.html#class-httpagent', - 'http.ClientRequest': 'http.html#class-httpclientrequest', - 'http.IncomingMessage': 'http.html#class-httpincomingmessage', - 'http.OutgoingMessage': 'http.html#class-httpoutgoingmessage', - 'http.Server': 'http.html#class-httpserver', - 'http.ServerResponse': 'http.html#class-httpserverresponse', - - 'http2.Http2ServerRequest': 'http2.html#class-http2http2serverrequest', - 'http2.Http2ServerResponse': 'http2.html#class-http2http2serverresponse', - - 'import.meta': 'esm.html#importmeta', - - 'module.SourceMap': 'module.html#class-modulesourcemap', - - 'net.BlockList': 'net.html#class-netblocklist', - 'net.Server': 'net.html#class-netserver', - 'net.Socket': 'net.html#class-netsocket', - 'net.SocketAddress': 'net.html#class-netsocketaddress', - - 'os.constants.dlopen': 'os.html#dlopen-constants', - - 'readline.Interface': 'readline.html#class-readlineinterface', - 'readline.InterfaceConstructor': 'readline.html#class-interfaceconstructor', - 'readlinePromises.Interface': 'readline.html#class-readlinepromisesinterface', - - 'repl.REPLServer': 'repl.html#class-replserver', - - require: 'modules.html#requireid', - - 'stream.Duplex': 'stream.html#class-streamduplex', - 'stream.Readable': 'stream.html#class-streamreadable', - 'stream.Transform': 'stream.html#class-streamtransform', - 'stream.Writable': 'stream.html#class-streamwritable', - - 'tls.SecureContext': 'tls.html#tlscreatesecurecontextoptions', - 'tls.Server': 'tls.html#class-tlsserver', - 'tls.TLSSocket': 'tls.html#class-tlstlssocket', - - 'tty.ReadStream': 'tty.html#class-ttyreadstream', - 'tty.WriteStream': 'tty.html#class-ttywritestream', - - 'vm.Module': 'vm.html#class-vmmodule', - 'vm.Script': 'vm.html#class-vmscript', - 'vm.SourceTextModule': 'vm.html#class-vmsourcetextmodule', - 'vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER': - 'vm.html#vmconstantsuse_main_context_default_loader', - - 'zlib options': 'zlib.html#class-options', -}; - -// This is a mapping for miscellaneous types within the Markdown content and their respective -// external reference on appropriate 3rd-party vendors/documentation sites. -export const DOC_TYPES_MAPPING_OTHER = { - any: `${DOC_MDN_BASE_URL_JS_PRIMITIVES}#Data_types`, - this: `${DOC_MDN_BASE_URL_JS}Reference/Operators/this`, - - ArrayBufferView: - 'https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView', - - AsyncIterator: 'https://tc39.github.io/ecma262/#sec-asynciterator-interface', - AsyncIterable: 'https://tc39.github.io/ecma262/#sec-asynciterable-interface', - AsyncFunction: 'https://tc39.es/ecma262/#sec-async-function-constructor', - - 'Module Namespace Object': - 'https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects', - - AsyncGeneratorFunction: - 'https://tc39.es/proposal-async-iteration/#sec-asyncgeneratorfunction-constructor', - - Iterable: `${DOC_MDN_BASE_URL_JS}Reference/Iteration_protocols#The_iterable_protocol`, - Iterator: `${DOC_MDN_BASE_URL_JS}Reference/Iteration_protocols#The_iterator_protocol`, - - FormData: `${DOC_MDN_BASE_URL}API/FormData`, - Headers: `${DOC_MDN_BASE_URL}/API/Headers`, - Response: `${DOC_MDN_BASE_URL}/API/Response`, - Request: `${DOC_MDN_BASE_URL}/API/Request`, -}; - -export const LINT_MESSAGES = { - missingIntroducedIn: "Missing 'introduced_in' field in the API doc entry", - missingChangeVersion: 'Missing version field in the API doc entry', - invalidChangeVersion: 'Invalid version number: {{version}}', -}; diff --git a/src/generators/json-simple/index.mjs b/src/generators/json-simple/index.mjs index a551593c..2ec4fa43 100644 --- a/src/generators/json-simple/index.mjs +++ b/src/generators/json-simple/index.mjs @@ -5,7 +5,7 @@ import { join } from 'node:path'; import { remove } from 'unist-util-remove'; -import createQueries from '../../queries.mjs'; +import createQueries from '../../utils/queries/index.mjs'; import { getRemark } from '../../utils/remark.mjs'; /** diff --git a/src/generators/legacy-html/constants.mjs b/src/generators/legacy-html/constants.mjs new file mode 100644 index 00000000..a6e6c6cd --- /dev/null +++ b/src/generators/legacy-html/constants.mjs @@ -0,0 +1,12 @@ +'use strict'; + +// This is the Node.js Base URL for viewing a file within GitHub UI +export const DOC_NODE_BLOB_BASE_URL = + 'https://github.com/nodejs/node/blob/HEAD/'; + +// This is the Node.js API docs base URL for editing a file on GitHub UI +export const DOC_API_BLOB_EDIT_BASE_URL = + 'https://github.com/nodejs/node/edit/main/doc/api/'; + +// Base URL for a specific Node.js version within the Node.js API docs +export const DOC_API_BASE_URL_VERSION = 'https://nodejs.org/docs/latest-v'; diff --git a/src/generators/legacy-html/utils/buildContent.mjs b/src/generators/legacy-html/utils/buildContent.mjs index 315f87c9..51eadafa 100644 --- a/src/generators/legacy-html/utils/buildContent.mjs +++ b/src/generators/legacy-html/utils/buildContent.mjs @@ -6,9 +6,9 @@ import { SKIP, visit } from 'unist-util-visit'; import buildExtraContent from './buildExtraContent.mjs'; -import createQueries from '../../../queries.mjs'; +import createQueries from '../../../utils/queries/index.mjs'; -import { DOC_NODE_BLOB_BASE_URL } from '../../../constants.mjs'; +import { DOC_NODE_BLOB_BASE_URL } from '../constants.mjs'; /** * Builds a Markdown heading for a given node diff --git a/src/generators/legacy-html/utils/buildDropdowns.mjs b/src/generators/legacy-html/utils/buildDropdowns.mjs index 22d9cb01..01b76f78 100644 --- a/src/generators/legacy-html/utils/buildDropdowns.mjs +++ b/src/generators/legacy-html/utils/buildDropdowns.mjs @@ -10,7 +10,7 @@ import { import { DOC_API_BASE_URL_VERSION, DOC_API_BLOB_EDIT_BASE_URL, -} from '../../../constants.mjs'; +} from '../constants.mjs'; /** * Builds the Dropdown for the current Table of Contents diff --git a/src/generators/man-page/constants.mjs b/src/generators/man-page/constants.mjs new file mode 100644 index 00000000..a4ae9458 --- /dev/null +++ b/src/generators/man-page/constants.mjs @@ -0,0 +1,11 @@ +'use strict'; + +// https://github.com/nodejs/node/blob/main/doc/api/cli.md#options +// This slug should reference the section where the available +// options are defined. +export const DOC_SLUG_OPTIONS = 'options'; + +// https://github.com/nodejs/node/blob/main/doc/api/cli.md#environment-variables-1 +// This slug should reference the section where the available +// environment variables are defined. +export const DOC_SLUG_ENVIRONMENT = 'environment-variables-1'; diff --git a/src/generators/man-page/index.mjs b/src/generators/man-page/index.mjs index 8ee045aa..fd92a453 100644 --- a/src/generators/man-page/index.mjs +++ b/src/generators/man-page/index.mjs @@ -8,7 +8,7 @@ import { convertEnvVarToMandoc, } from './utils/converter.mjs'; -import { DOC_SLUG_ENVIRONMENT, DOC_SLUG_OPTIONS } from '../../constants.mjs'; +import { DOC_SLUG_ENVIRONMENT, DOC_SLUG_OPTIONS } from './constants.mjs'; /** * This generator generates a man page version of the CLI.md file. diff --git a/src/linter/constants.mjs b/src/linter/constants.mjs new file mode 100644 index 00000000..b70ba653 --- /dev/null +++ b/src/linter/constants.mjs @@ -0,0 +1,7 @@ +'use strict'; + +export const LINT_MESSAGES = { + missingIntroducedIn: "Missing 'introduced_in' field in the API doc entry", + missingChangeVersion: 'Missing version field in the API doc entry', + invalidChangeVersion: 'Invalid version number: {{version}}', +}; diff --git a/src/linter/rules/invalid-change-version.mjs b/src/linter/rules/invalid-change-version.mjs index 779901aa..927f35f1 100644 --- a/src/linter/rules/invalid-change-version.mjs +++ b/src/linter/rules/invalid-change-version.mjs @@ -1,4 +1,4 @@ -import { LINT_MESSAGES } from '../../constants.mjs'; +import { LINT_MESSAGES } from '../constants.mjs'; import { valid } from 'semver'; /** diff --git a/src/linter/rules/missing-introduced-in.mjs b/src/linter/rules/missing-introduced-in.mjs index 80224c9d..8dc79891 100644 --- a/src/linter/rules/missing-introduced-in.mjs +++ b/src/linter/rules/missing-introduced-in.mjs @@ -1,4 +1,4 @@ -import { LINT_MESSAGES } from '../../constants.mjs'; +import { LINT_MESSAGES } from '../constants.mjs'; /** * Checks if `introduced_in` field is missing diff --git a/src/parsers/markdown.mjs b/src/parsers/markdown.mjs index 800a51b6..3617baca 100644 --- a/src/parsers/markdown.mjs +++ b/src/parsers/markdown.mjs @@ -7,10 +7,10 @@ import { selectAll } from 'unist-util-select'; import { SKIP, visit } from 'unist-util-visit'; import createMetadata from '../metadata.mjs'; -import createQueries from '../queries.mjs'; +import createQueries from '../utils/queries/index.mjs'; import { getRemark } from '../utils/remark.mjs'; -import { createNodeSlugger } from '../utils/slugger.mjs'; +import { createNodeSlugger } from '../utils/slugger/index.mjs'; /** * Creates an API doc parser for a given Markdown API doc file diff --git a/src/utils/parser/constants.mjs b/src/utils/parser/constants.mjs new file mode 100644 index 00000000..65812ea2 --- /dev/null +++ b/src/utils/parser/constants.mjs @@ -0,0 +1,360 @@ +'use strict'; + +// This is the base URL of the MDN Web documentation +export const DOC_MDN_BASE_URL = 'https://developer.mozilla.org/en-US/docs/Web/'; + +// This is the base URL for the MDN JavaScript documentation +export const DOC_MDN_BASE_URL_JS = `${DOC_MDN_BASE_URL}JavaScript/`; + +// This is the base URL for the MDN JavaScript primitives documentation +export const DOC_MDN_BASE_URL_JS_PRIMITIVES = `${DOC_MDN_BASE_URL_JS}Data_structures`; + +// This is the base URL for the MDN JavaScript global objects documentation +export const DOC_MDN_BASE_URL_JS_GLOBALS = `${DOC_MDN_BASE_URL_JS}Reference/Global_Objects/`; + +// These are regular expressions used to determine if a given Markdown heading +// is a specific type of API Doc entry (e.g., Event, Class, Method, etc) +// and to extract the inner content of said Heading to be used as the API doc entry name +export const DOC_API_HEADING_TYPES = [ + { + type: 'method', + regex: + // Group 1: foo[bar]() + // Group 2: foo.bar() + // Group 3: foobar() + /^`?(?:\w*(?:(\[[^\]]+\])|(?:\.(\w+)))|(\w+))\([^)]*\)`?$/i, + }, + { type: 'event', regex: /^Event: +`?['"]?([^'"]+)['"]?`?$/i }, + { + type: 'class', + regex: + /^Class: +`?([A-Z]\w+(?:\.[A-Z]\w+)*(?: +extends +[A-Z]\w+(?:\.[A-Z]\w+)*)?)`?$/i, + }, + { + type: 'ctor', + regex: /^(?:Constructor: +)?`?new +([A-Z]\w+(?:\.[A-Z]\w+)*)\([^)]*\)`?$/i, + }, + { + type: 'classMethod', + regex: + /^Static method: +`?[A-Z]\w+(?:\.[A-Z]\w+)*(?:(\[\w+\.\w+\])|\.(\w+))\([^)]*\)`?$/i, + }, + { + type: 'property', + regex: + /^(?:Class property: +)?`?[A-Z]\w+(?:\.[A-Z]\w+)*(?:(\[\w+\.\w+\])|\.(\w+))`?$/i, + }, +]; + +// This is a mapping for types within the Markdown content and their respective +// JavaScript primitive types within the MDN JavaScript docs +// @see DOC_MDN_BASE_URL_JS_PRIMITIVES +export const DOC_TYPES_MAPPING_PRIMITIVES = { + boolean: 'Boolean', + integer: 'Number', // Not a primitive, used for clarification. + null: 'Null', + number: 'Number', + string: 'String', + symbol: 'Symbol', + undefined: 'Undefined', +}; + +// This is a mapping for types within the Markdown content and their respective +// JavaScript globals types within the MDN JavaScript docs +// @see DOC_MDN_BASE_URL_JS_GLOBALS +export const DOC_TYPES_MAPPING_GLOBALS = { + ...Object.fromEntries( + [ + 'AggregateError', + 'Array', + 'ArrayBuffer', + 'DataView', + 'Date', + 'Error', + 'EvalError', + 'Function', + 'Map', + 'NaN', + 'Object', + 'Promise', + 'Proxy', + 'RangeError', + 'ReferenceError', + 'RegExp', + 'Set', + 'SharedArrayBuffer', + 'SyntaxError', + 'Symbol', + 'TypeError', + 'URIError', + 'WeakMap', + 'WeakSet', + + 'TypedArray', + 'Float32Array', + 'Float64Array', + 'Int8Array', + 'Int16Array', + 'Int32Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Uint16Array', + 'Uint32Array', + ].map(e => [e, e]) + ), + bigint: 'BigInt', + 'WebAssembly.Instance': 'WebAssembly/Instance', +}; + +// This is a mapping for types within the Markdown content and their respective +// Node.js types within the Node.js API docs (refers to a different API doc page) +// Note: These hashes are generated with the GitHub Slugger +export const DOC_TYPES_MAPPING_NODE_MODULES = { + AbortController: 'globals.html#class-abortcontroller', + AbortSignal: 'globals.html#class-abortsignal', + + AlgorithmIdentifier: 'webcrypto.html#class-algorithmidentifier', + AsyncHook: 'async_hooks.html#async_hookscreatehookcallbacks', + AsyncLocalStorage: 'async_context.html#class-asynclocalstorage', + AsyncResource: 'async_hooks.html#class-asyncresource', + + AesCbcParams: 'webcrypto.html#class-aescbcparams', + AesCtrParams: 'webcrypto.html#class-aesctrparams', + AesGcmParams: 'webcrypto.html#class-aesgcmparams', + AesKeyGenParams: 'webcrypto.html#class-aeskeygenparams', + + Blob: 'buffer.html#class-blob', + BroadcastChannel: + 'worker_threads.html#class-broadcastchannel-extends-eventtarget', + Buffer: 'buffer.html#class-buffer', + + ByteLengthQueuingStrategy: 'webstreams.html#class-bytelengthqueuingstrategy', + + Channel: 'diagnostics_channel.html#class-channel', + ChildProcess: 'child_process.html#class-childprocess', + Cipher: 'crypto.html#class-cipher', + ClientHttp2Session: 'http2.html#class-clienthttp2session', + ClientHttp2Stream: 'http2.html#class-clienthttp2stream', + + CountQueuingStrategy: 'webstreams.html#class-countqueuingstrategy', + + Crypto: 'webcrypto.html#class-crypto', + CryptoKey: 'webcrypto.html#class-cryptokey', + CryptoKeyPair: 'webcrypto.html#class-cryptokeypair', + + CustomEvent: 'events.html#class-customevent', + + Decipher: 'crypto.html#class-decipher', + DiffieHellman: 'crypto.html#class-diffiehellman', + DiffieHellmanGroup: 'crypto.html#class-diffiehellmangroup', + Domain: 'domain.html#class-domain', + + Duplex: 'stream.html#class-streamduplex', + + ECDH: 'crypto.html#class-ecdh', + EcdhKeyDeriveParams: 'webcrypto.html#class-ecdhkeyderiveparams', + EcdsaParams: 'webcrypto.html#class-ecdsaparams', + EcKeyGenParams: 'webcrypto.html#class-eckeygenparams', + EcKeyImportParams: 'webcrypto.html#class-eckeyimportparams', + Ed448Params: 'webcrypto.html#class-ed448params', + + Event: 'events.html#class-event', + EventEmitter: 'events.html#class-eventemitter', + EventListener: 'events.html#event-listener', + EventTarget: 'events.html#class-eventtarget', + + File: 'buffer.html#class-file', + FileHandle: 'fs.html#class-filehandle', + + Handle: 'net.html#serverlistenhandle-backlog-callback', + Hash: 'crypto.html#class-hash', + Histogram: 'perf_hooks.html#class-histogram', + HkdfParams: 'webcrypto.html#class-hkdfparams', + Hmac: 'crypto.html#class-hmac', + HmacImportParams: 'webcrypto.html#class-hmacimportparams', + HmacKeyGenParams: 'webcrypto.html#class-hmackeygenparams', + + Http2SecureServer: 'http2.html#class-http2secureserver', + Http2Server: 'http2.html#class-http2server', + Http2Session: 'http2.html#class-http2session', + Http2Stream: 'http2.html#class-http2stream', + + Immediate: 'timers.html#class-immediate', + + IntervalHistogram: + 'perf_hooks.html#class-intervalhistogram-extends-histogram', + + KeyObject: 'crypto.html#class-keyobject', + + MIMEParams: 'util.html#class-utilmimeparams', + MessagePort: 'worker_threads.html#class-messageport', + + MockModuleContext: 'test.html#class-mockmodulecontext', + + NodeEventTarget: 'events.html#class-nodeeventtarget', + + Pbkdf2Params: 'webcrypto.html#class-pbkdf2params', + PerformanceEntry: 'perf_hooks.html#class-performanceentry', + PerformanceNodeTiming: 'perf_hooks.html#class-performancenodetiming', + PerformanceObserver: 'perf_hooks.html#class-performanceobserver', + PerformanceObserverEntryList: + 'perf_hooks.html#class-performanceobserverentrylist', + + Readable: 'stream.html#class-streamreadable', + ReadableByteStreamController: + 'webstreams.html#class-readablebytestreamcontroller', + ReadableStream: 'webstreams.html#class-readablestream', + ReadableStreamBYOBReader: 'webstreams.html#class-readablestreambyobreader', + ReadableStreamBYOBRequest: 'webstreams.html#class-readablestreambyobrequest', + ReadableStreamDefaultController: + 'webstreams.html#class-readablestreamdefaultcontroller', + ReadableStreamDefaultReader: + 'webstreams.html#class-readablestreamdefaultreader', + + RecordableHistogram: + 'perf_hooks.html#class-recordablehistogram-extends-histogram', + + RsaHashedImportParams: 'webcrypto.html#class-rsahashedimportparams', + RsaHashedKeyGenParams: 'webcrypto.html#class-rsahashedkeygenparams', + RsaOaepParams: 'webcrypto.html#class-rsaoaepparams', + RsaPssParams: 'webcrypto.html#class-rsapssparams', + + ServerHttp2Session: 'http2.html#class-serverhttp2session', + ServerHttp2Stream: 'http2.html#class-serverhttp2stream', + + Sign: 'crypto.html#class-sign', + + StatementSync: 'sqlite.html#class-statementsync', + + Stream: 'stream.html#stream', + + SubtleCrypto: 'webcrypto.html#class-subtlecrypto', + + TestsStream: 'test.html#class-testsstream', + + TextDecoderStream: 'webstreams.html#class-textdecoderstream', + TextEncoderStream: 'webstreams.html#class-textencoderstream', + + Timeout: 'timers.html#class-timeout', + Timer: 'timers.html#timers', + + Tracing: 'tracing.html#tracing-object', + TracingChannel: 'diagnostics_channel.html#class-tracingchannel', + + Transform: 'stream.html#class-streamtransform', + TransformStream: 'webstreams.html#class-transformstream', + TransformStreamDefaultController: + 'webstreams.html#class-transformstreamdefaultcontroller', + + URL: 'url.html#the-whatwg-url-api', + URLSearchParams: 'url.html#class-urlsearchparams', + + Verify: 'crypto.html#class-verify', + + Writable: 'stream.html#class-streamwritable', + WritableStream: 'webstreams.html#class-writablestream', + WritableStreamDefaultController: + 'webstreams.html#class-writablestreamdefaultcontroller', + WritableStreamDefaultWriter: + 'webstreams.html#class-writablestreamdefaultwriter', + + Worker: 'worker_threads.html#class-worker', + + X509Certificate: 'crypto.html#class-x509certificate', + + 'brotli options': 'zlib.html#class-brotlioptions', + + 'cluster.Worker': 'cluster.html#class-worker', + + 'crypto.constants': 'crypto.html#cryptoconstants', + + 'dgram.Socket': 'dgram.html#class-dgramsocket', + + 'errors.Error': 'errors.html#class-error', + + 'fs.Dir': 'fs.html#class-fsdir', + 'fs.Dirent': 'fs.html#class-fsdirent', + 'fs.FSWatcher': 'fs.html#class-fsfswatcher', + 'fs.ReadStream': 'fs.html#class-fsreadstream', + 'fs.StatFs': 'fs.html#class-fsstatfs', + 'fs.Stats': 'fs.html#class-fsstats', + 'fs.StatWatcher': 'fs.html#class-fsstatwatcher', + 'fs.WriteStream': 'fs.html#class-fswritestream', + + 'http.Agent': 'http.html#class-httpagent', + 'http.ClientRequest': 'http.html#class-httpclientrequest', + 'http.IncomingMessage': 'http.html#class-httpincomingmessage', + 'http.OutgoingMessage': 'http.html#class-httpoutgoingmessage', + 'http.Server': 'http.html#class-httpserver', + 'http.ServerResponse': 'http.html#class-httpserverresponse', + + 'http2.Http2ServerRequest': 'http2.html#class-http2http2serverrequest', + 'http2.Http2ServerResponse': 'http2.html#class-http2http2serverresponse', + + 'import.meta': 'esm.html#importmeta', + + 'module.SourceMap': 'module.html#class-modulesourcemap', + + 'net.BlockList': 'net.html#class-netblocklist', + 'net.Server': 'net.html#class-netserver', + 'net.Socket': 'net.html#class-netsocket', + 'net.SocketAddress': 'net.html#class-netsocketaddress', + + 'os.constants.dlopen': 'os.html#dlopen-constants', + + 'readline.Interface': 'readline.html#class-readlineinterface', + 'readline.InterfaceConstructor': 'readline.html#class-interfaceconstructor', + 'readlinePromises.Interface': 'readline.html#class-readlinepromisesinterface', + + 'repl.REPLServer': 'repl.html#class-replserver', + + require: 'modules.html#requireid', + + 'stream.Duplex': 'stream.html#class-streamduplex', + 'stream.Readable': 'stream.html#class-streamreadable', + 'stream.Transform': 'stream.html#class-streamtransform', + 'stream.Writable': 'stream.html#class-streamwritable', + + 'tls.SecureContext': 'tls.html#tlscreatesecurecontextoptions', + 'tls.Server': 'tls.html#class-tlsserver', + 'tls.TLSSocket': 'tls.html#class-tlstlssocket', + + 'tty.ReadStream': 'tty.html#class-ttyreadstream', + 'tty.WriteStream': 'tty.html#class-ttywritestream', + + 'vm.Module': 'vm.html#class-vmmodule', + 'vm.Script': 'vm.html#class-vmscript', + 'vm.SourceTextModule': 'vm.html#class-vmsourcetextmodule', + 'vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER': + 'vm.html#vmconstantsuse_main_context_default_loader', + + 'zlib options': 'zlib.html#class-options', +}; + +// This is a mapping for miscellaneous types within the Markdown content and their respective +// external reference on appropriate 3rd-party vendors/documentation sites. +export const DOC_TYPES_MAPPING_OTHER = { + any: `${DOC_MDN_BASE_URL_JS_PRIMITIVES}#Data_types`, + this: `${DOC_MDN_BASE_URL_JS}Reference/Operators/this`, + + ArrayBufferView: + 'https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView', + + AsyncIterator: 'https://tc39.github.io/ecma262/#sec-asynciterator-interface', + AsyncIterable: 'https://tc39.github.io/ecma262/#sec-asynciterable-interface', + AsyncFunction: 'https://tc39.es/ecma262/#sec-async-function-constructor', + + 'Module Namespace Object': + 'https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects', + + AsyncGeneratorFunction: + 'https://tc39.es/proposal-async-iteration/#sec-asyncgeneratorfunction-constructor', + + Iterable: `${DOC_MDN_BASE_URL_JS}Reference/Iteration_protocols#The_iterable_protocol`, + Iterator: `${DOC_MDN_BASE_URL_JS}Reference/Iteration_protocols#The_iterator_protocol`, + + FormData: `${DOC_MDN_BASE_URL}API/FormData`, + Headers: `${DOC_MDN_BASE_URL}/API/Headers`, + Response: `${DOC_MDN_BASE_URL}/API/Response`, + Request: `${DOC_MDN_BASE_URL}/API/Request`, +}; diff --git a/src/utils/parser.mjs b/src/utils/parser/index.mjs similarity index 99% rename from src/utils/parser.mjs rename to src/utils/parser/index.mjs index 42458064..a58ae14f 100644 --- a/src/utils/parser.mjs +++ b/src/utils/parser/index.mjs @@ -10,7 +10,7 @@ import { DOC_TYPES_MAPPING_NODE_MODULES, DOC_TYPES_MAPPING_OTHER, DOC_TYPES_MAPPING_PRIMITIVES, -} from '../constants.mjs'; +} from './constants.mjs'; /** * This method replaces plain text Types within the Markdown content into Markdown links diff --git a/src/utils/queries/constants.mjs b/src/utils/queries/constants.mjs new file mode 100644 index 00000000..4e6a22b9 --- /dev/null +++ b/src/utils/queries/constants.mjs @@ -0,0 +1,5 @@ +'use strict'; + +// This is the perma-link within the API docs that reference the Stability Index +export const DOC_API_STABILITY_SECTION_REF_URL = + 'documentation.html#stability-index'; diff --git a/src/queries.mjs b/src/utils/queries/index.mjs similarity index 94% rename from src/queries.mjs rename to src/utils/queries/index.mjs index d160f060..8b203c83 100644 --- a/src/queries.mjs +++ b/src/utils/queries/index.mjs @@ -5,14 +5,14 @@ import { SKIP } from 'unist-util-visit'; import { DOC_API_STABILITY_SECTION_REF_URL } from './constants.mjs'; -import { transformNodesToString } from './utils/unist.mjs'; +import { transformNodesToString } from '../unist.mjs'; import { parseHeadingIntoMetadata, parseYAMLIntoMetadata, transformTypeToReferenceLink, -} from './utils/parser.mjs'; -import { getRemark } from './utils/remark.mjs'; +} from '../parser/index.mjs'; +import { getRemark } from '../remark.mjs'; /** * Creates an instance of the Query Manager, which allows to do multiple sort @@ -25,7 +25,7 @@ const createQueries = () => { * and then parsing it into an API Metadata object and updating the current Metadata * * @param {import('@types/mdast').Html} node A HTML node containing the YAML content - * @param {ReturnType} apiEntryMetadata The API entry Metadata + * @param {ReturnType} apiEntryMetadata The API entry Metadata */ const addYAMLMetadata = (node, apiEntryMetadata) => { const sanitizedString = node.value.replace( @@ -43,7 +43,7 @@ const createQueries = () => { * Parse a Heading node into metadata and updates the current metadata * * @param {import('@types/mdast').Heading} node A Markdown heading node - * @param {ReturnType} apiEntryMetadata The API entry Metadata + * @param {ReturnType} apiEntryMetadata The API entry Metadata */ const setHeadingMetadata = (node, apiEntryMetadata) => { const stringifiedHeading = transformNodesToString(node.children); @@ -122,7 +122,7 @@ const createQueries = () => { * Parses a Stability Index Entry and updates the current Metadata * * @param {import('@types/mdast').Blockquote} node Thead Link Reference Node - * @param {ReturnType} apiEntryMetadata The API entry Metadata + * @param {ReturnType} apiEntryMetadata The API entry Metadata */ const addStabilityMetadata = (node, apiEntryMetadata) => { // `node` is a `blockquote` node, and the first child will always be diff --git a/src/utils/slugger/constants.mjs b/src/utils/slugger/constants.mjs new file mode 100644 index 00000000..99b84e91 --- /dev/null +++ b/src/utils/slugger/constants.mjs @@ -0,0 +1,11 @@ +'use strict'; + +// These are string replacements specific to Node.js API docs for anchor IDs +export const DOC_API_SLUGS_REPLACEMENTS = [ + { from: /node.js/i, to: 'nodejs' }, // Replace Node.js + { from: /&/, to: '-and-' }, // Replace & + { from: /[/_,:;\\ ]/g, to: '-' }, // Replace /_,:;\. and whitespace + { from: /--+/g, to: '-' }, // Replace multiple hyphens with single + { from: /^-/, to: '' }, // Remove any leading hyphen + { from: /-$/, to: '' }, // Remove any trailing hyphen +]; diff --git a/src/utils/slugger.mjs b/src/utils/slugger/index.mjs similarity index 93% rename from src/utils/slugger.mjs rename to src/utils/slugger/index.mjs index fc0eb933..883513d6 100644 --- a/src/utils/slugger.mjs +++ b/src/utils/slugger/index.mjs @@ -2,7 +2,7 @@ import GitHubSlugger from 'github-slugger'; -import { DOC_API_SLUGS_REPLACEMENTS } from '../constants.mjs'; +import { DOC_API_SLUGS_REPLACEMENTS } from './constants.mjs'; /** * Creates a modified version of the GitHub Slugger diff --git a/src/utils/tests/parser.test.mjs b/src/utils/tests/parser.test.mjs index 3d51097e..cf3a4ae2 100644 --- a/src/utils/tests/parser.test.mjs +++ b/src/utils/tests/parser.test.mjs @@ -5,7 +5,7 @@ import { parseYAMLIntoMetadata, transformTypeToReferenceLink, parseHeadingIntoMetadata, -} from '../parser.mjs'; +} from '../parser/index.mjs'; describe('transformTypeToReferenceLink', () => { it('should transform a JavaScript primitive type into a Markdown link', () => { diff --git a/src/test/queries.test.mjs b/src/utils/tests/queries.test.mjs similarity index 98% rename from src/test/queries.test.mjs rename to src/utils/tests/queries.test.mjs index 398b190d..685c9178 100644 --- a/src/test/queries.test.mjs +++ b/src/utils/tests/queries.test.mjs @@ -1,6 +1,6 @@ import { strictEqual, deepStrictEqual } from 'node:assert'; import { describe, it } from 'node:test'; -import createQueries from '../queries.mjs'; +import createQueries from '../queries/index.mjs'; describe('createQueries', () => { it('should add YAML metadata correctly', () => { diff --git a/src/utils/tests/slugger.test.mjs b/src/utils/tests/slugger.test.mjs index d4c0dc37..61628e31 100644 --- a/src/utils/tests/slugger.test.mjs +++ b/src/utils/tests/slugger.test.mjs @@ -1,7 +1,7 @@ import { strictEqual } from 'node:assert'; import { describe, it } from 'node:test'; -import { createNodeSlugger } from '../slugger.mjs'; +import { createNodeSlugger } from '../slugger/index.mjs'; describe('createNodeSlugger', () => { it('should create a new instance of the GitHub Slugger', () => {