From ef91832df7a24b3f81d26260c06271a48be8caa8 Mon Sep 17 00:00:00 2001 From: Stephen Li Date: Tue, 2 Jul 2024 00:06:03 -0400 Subject: [PATCH] Move assertNode to independent utils function --- src/Generator/RstGeneratorState.ts | 23 ++++++++--------------- src/Plugins/Domains/Js/JsPropGroup.ts | 3 ++- src/Plugins/Table/TablePlugin.ts | 9 +++++---- src/Plugins/Tabs/TabsPlugin.ts | 3 ++- src/RstNode/Table/Table.ts | 15 ++++++++------- src/utils/assertNode.ts | 18 ++++++++++++++++++ 6 files changed, 43 insertions(+), 28 deletions(-) create mode 100644 src/utils/assertNode.ts diff --git a/src/Generator/RstGeneratorState.ts b/src/Generator/RstGeneratorState.ts index 5cbd03c..cb6f760 100644 --- a/src/Generator/RstGeneratorState.ts +++ b/src/Generator/RstGeneratorState.ts @@ -15,7 +15,6 @@ import { RstNodeType } from '@/RstNode/RstNodeType.js' import { HtmlAttributeStore } from './HtmlAttributeStore.js' import { RstGeneratorError } from './RstGeneratorError.js' import { sha1 } from '@/utils/sha1.js' -import { RstNodeMap } from '@/RstNode/RstNodeMap.js' import { SimpleNameResolver } from '@/Parser/Resolver/SimpleNameResolver.js' import { RstFootnoteDef } from '@/RstNode/ExplicitMarkup/FootnoteDef.js' import { RstFootnoteRef } from '@/RstNode/Inline/FootnoteRef.js' @@ -140,6 +139,10 @@ export class RstGeneratorState implements SimpleNameResolverProxy { } } + // ------------------------------------------------------------------------ + // MARK: Getters + // ------------------------------------------------------------------------ + get generatorOutput(): RstGeneratorOutput { if (this._outputBuffers.length !== 1) { throw new RstGeneratorError(this, 'Corrupt outputBuffer') @@ -180,6 +183,10 @@ export class RstGeneratorState implements SimpleNameResolverProxy { return this._currentParserOutput.htmlAttrResolver } + // ------------------------------------------------------------------------ + // MARK: Resolvers + // ------------------------------------------------------------------------ + resolveExternalDoc(srcNode: RstNode, targetPath: string): { externalUrl: string; externalLabel?: string } { const docFilePath = targetPath.startsWith('/') ? joinFilePath(this._basePath, targetPath) // If given abs path, assume we want to search from basePath @@ -295,20 +302,6 @@ export class RstGeneratorState implements SimpleNameResolverProxy { return footnoteDef } - assertNode(node: RstNode | null | undefined, expectedNodeType: T, expectedNumChildren?: number): asserts node is RstNodeMap[T] { - if (!node) { - throw new RstGeneratorError(this, 'Invalid node') - } - - if (node.nodeType !== expectedNodeType) { - throw new RstGeneratorError(this, node, `Is not ${expectedNodeType}`) - } - - if (expectedNumChildren !== undefined && node.children.length !== expectedNumChildren) { - throw new RstGeneratorError(this, node, `Does not have exactly ${expectedNumChildren} child`) - } - } - // ------------------------------------------------------------------------ // MARK: Visit // ------------------------------------------------------------------------ diff --git a/src/Plugins/Domains/Js/JsPropGroup.ts b/src/Plugins/Domains/Js/JsPropGroup.ts index 8e01376..a1439f1 100644 --- a/src/Plugins/Domains/Js/JsPropGroup.ts +++ b/src/Plugins/Domains/Js/JsPropGroup.ts @@ -5,6 +5,7 @@ import { RstFieldList } from '@/RstNode/List/FieldList.js' import { RstFieldListItem } from '@/RstNode/List/FieldListItem.js' import { RstNodeType } from '@/RstNode/RstNodeType.js' import { normalizeSimpleName } from '@/SimpleName.js' +import { assertNode } from '@/utils/assertNode.js' import { sanitizeHtml } from '@/utils/sanitizeHtml.js' export type JsPropGroupType = Brand // "param", "throw", "return", etc. @@ -19,7 +20,7 @@ export function getJsPropGroups(generatorState: RstGeneratorState, fieldList: Rs const jsProps = new Map>() // Maps prop type ("param", "throw", "return") to corresponding FieldListItems that describe them for (const fieldListItem of fieldList.children) { - generatorState.assertNode(fieldListItem, RstNodeType.FieldListItem) + assertNode(generatorState, fieldListItem, RstNodeType.FieldListItem) const fieldName = fieldListItem.name.map((textNode) => textNode.textContent).join(' ') const fieldNameParts = fieldName.split(' ') diff --git a/src/Plugins/Table/TablePlugin.ts b/src/Plugins/Table/TablePlugin.ts index 78bbf2d..fd04c75 100644 --- a/src/Plugins/Table/TablePlugin.ts +++ b/src/Plugins/Table/TablePlugin.ts @@ -5,6 +5,7 @@ import { RstDirective } from '@/RstNode/ExplicitMarkup/Directive.js' import { RstBulletList } from '@/RstNode/List/BulletList.js' import { RstNodeType } from '@/RstNode/RstNodeType.js' import { RstTable, listTableGenerators, tableGenerators } from '@/RstNode/Table/Table.js' +import { assertNode } from '@/utils/assertNode.js' // ---------------------------------------------------------------------------- // MARK: Directive @@ -67,19 +68,19 @@ export const tableDirectivePlugin = createRstCompilerPlugins({ // ---------------------------------------------------------------------------- function getTableNode(generatorState: RstGeneratorState, directiveNode: RstDirective): RstTable { - generatorState.assertNode(directiveNode, RstNodeType.Directive, 1) + assertNode(generatorState, directiveNode, RstNodeType.Directive, 1) const table = directiveNode.children[0] - generatorState.assertNode(table, RstNodeType.Table) + assertNode(generatorState, table, RstNodeType.Table) return table } function getListTableNode(generatorState: RstGeneratorState, directiveNode: RstDirective): RstBulletList { - generatorState.assertNode(directiveNode, RstNodeType.Directive, 1) + assertNode(generatorState, directiveNode, RstNodeType.Directive, 1) const list = directiveNode.children[0] - generatorState.assertNode(list, RstNodeType.BulletList) + assertNode(generatorState, list, RstNodeType.BulletList) return list } diff --git a/src/Plugins/Tabs/TabsPlugin.ts b/src/Plugins/Tabs/TabsPlugin.ts index e92be3f..21ac87a 100644 --- a/src/Plugins/Tabs/TabsPlugin.ts +++ b/src/Plugins/Tabs/TabsPlugin.ts @@ -9,6 +9,7 @@ import browserCode from './Tabs.browser.js?raw' with { type: 'text' } import { renderCodeBlockHtml } from '../Code/renderCodeBlockHtml.js' import { renderCodeBlockMd } from '../Code/renderCodeBlockMd.js' import { bundledLanguagesInfo } from 'shiki' +import { assertNode } from '@/utils/assertNode.js' // ---------------------------------------------------------------------------- // MARK: Constants @@ -89,7 +90,7 @@ function getTabsGroupKey(generatorState: RstGeneratorState, node: RstDirective): let childrenDirective: string | null = null for (const child of node.children) { - generatorState.assertNode(child, RstNodeType.Directive) + assertNode(generatorState, child, RstNodeType.Directive) if (childrenDirective !== null && childrenDirective !== child.directive) { throw new Error(`Child [${child.toShortString()}] does not match other childrens' directive:"${childrenDirective}"`) diff --git a/src/RstNode/Table/Table.ts b/src/RstNode/Table/Table.ts index 6ec7bd5..50b5d81 100644 --- a/src/RstNode/Table/Table.ts +++ b/src/RstNode/Table/Table.ts @@ -8,6 +8,7 @@ import { RstDirective } from '../ExplicitMarkup/Directive.js' import { RstGeneratorState } from '@/Generator/RstGeneratorState.js' import { HtmlAttributeStore } from '@/Generator/HtmlAttributeStore.js' import { RstGeneratorError } from '@/Generator/RstGeneratorError.js' +import { assertNode } from '@/utils/assertNode.js' // ---------------------------------------------------------------------------- // MARK: Node @@ -179,13 +180,13 @@ function getColWidths(generatorState: RstGeneratorState, directiveNode: RstDirec if (allowGridValue && rawWidths === 'grid') { const table = directiveNode?.children.at(0) - generatorState.assertNode(table, RstNodeType.Table) + assertNode(generatorState, table, RstNodeType.Table) let totalWidth = 0 const cellWidths = new Array() for (const cell of table.children[0].children) { - generatorState.assertNode(cell, RstNodeType.TableCell) + assertNode(generatorState, cell, RstNodeType.TableCell) totalWidth += cell.characterWidth cellWidths.push(cell.characterWidth) @@ -199,11 +200,11 @@ function getColWidths(generatorState: RstGeneratorState, directiveNode: RstDirec function generateTableRows(generatorState: RstGeneratorState, rowNodes: ReadonlyArray, cellTag: 'th' | 'td', colWidths: Array, tableAlign: string | null): void { for (const rowNode of rowNodes) { - generatorState.assertNode(rowNode, RstNodeType.TableRow) + assertNode(generatorState, rowNode, RstNodeType.TableRow) generatorState.writeLineHtmlTag('tr', rowNode, () => { for (const [idx, cellNode] of rowNode.children.entries()) { - generatorState.assertNode(cellNode, RstNodeType.TableCell) + assertNode(generatorState, cellNode, RstNodeType.TableCell) const attrs = new HtmlAttributeStore() @@ -230,10 +231,10 @@ function generateTableRows(generatorState: RstGeneratorState, rowNodes: Readonly function generateListTableRows(generatorState: RstGeneratorState, rowNodes: ReadonlyArray, cellTag: 'th' | 'td', colWidths: Array, tableAlign: string | null): void { for (const rowNode of rowNodes) { - generatorState.assertNode(rowNode, RstNodeType.BulletListItem, 1) + assertNode(generatorState, rowNode, RstNodeType.BulletListItem, 1) - const colList: RstNode = rowNode.children[0] - generatorState.assertNode(colList, RstNodeType.BulletList) + const colList = rowNode.children[0] + assertNode(generatorState, colList, RstNodeType.BulletList) if (colWidths.length > 0 && colList.children.length !== colWidths.length) { throw new RstGeneratorError(generatorState, `Expected ${colList.children.length} widths but only got ${colWidths.length}`) diff --git a/src/utils/assertNode.ts b/src/utils/assertNode.ts new file mode 100644 index 0000000..9a3a98b --- /dev/null +++ b/src/utils/assertNode.ts @@ -0,0 +1,18 @@ +import { RstGeneratorError } from '@/Generator/RstGeneratorError.js' +import { RstGeneratorState } from '@/Generator/RstGeneratorState.js' +import { RstNode } from '@/RstNode/RstNode.js' +import { RstNodeMap } from '@/RstNode/RstNodeMap.js' + +export function assertNode(generatorState: RstGeneratorState, node: RstNode | null | undefined, expectedNodeType: T, expectedNumChildren?: number): asserts node is RstNodeMap[T] { + if (!node) { + throw new RstGeneratorError(generatorState, 'Is not a node') + } + + if (node.nodeType !== expectedNodeType) { + throw new RstGeneratorError(generatorState, node, `Is not ${expectedNodeType}`) + } + + if (expectedNumChildren !== undefined && node.children.length !== expectedNumChildren) { + throw new RstGeneratorError(generatorState, node, `Does not have exactly ${expectedNumChildren} child`) + } +}