From 805b2a0d25e05ab3d965e7712c33a72c9d127914 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 6 Oct 2024 17:10:40 +0000 Subject: [PATCH] [ci] release --- .changeset/gentle-flies-try.md | 5 - packages/aik-mod/CHANGELOG.md | 6 + packages/aik-mod/package.json | 2 +- packages/aik-route-config/CHANGELOG.md | 7 + packages/aik-route-config/package.json | 2 +- packages/astro-tests/CHANGELOG.md | 7 + packages/astro-tests/package.json | 2 +- packages/content-utils/CHANGELOG.md | 8 + packages/content-utils/package.json | 2 +- packages/cut-short/CHANGELOG.md | 7 + packages/cut-short/package.json | 2 +- packages/inline-mod/CHANGELOG.md | 7 + packages/inline-mod/package.json | 2 +- packages/modular-station/CHANGELOG.md | 7 + packages/modular-station/package.json | 2 +- packages/portal-gun/CHANGELOG.md | 9 + packages/portal-gun/package.json | 2 +- packages/portal-gun/tests/basic.test.ts | 6 +- packages/portal-gun/tests/common.ts | 48 +- .../tests/fixture/basic/astro.config.ts | 4 +- .../tests/fixture/basic/tsconfig.json | 2 +- packages/portal-gun/tests/server.test.ts | 24 +- packages/portal-gun/virtual.d.ts | 10 +- packages/request-nanostores/CHANGELOG.md | 8 + packages/request-nanostores/package.json | 2 +- packages/request-state/CHANGELOG.md | 7 + packages/request-state/package.json | 2 +- packages/runtime-logger/CHANGELOG.md | 8 + packages/runtime-logger/package.json | 2 +- packages/sitemap-ext/CHANGELOG.md | 6 + packages/sitemap-ext/package.json | 2 +- packages/star-warp/CHANGELOG.md | 7 + packages/star-warp/package.json | 2 +- packages/utils/CHANGELOG.md | 6 + packages/utils/package.json | 2 +- packages/utils/src/unist/visit.ts | 328 ++--- packages/utils/tests/unist/visit.test.ts | 1076 ++++++++--------- 37 files changed, 863 insertions(+), 768 deletions(-) delete mode 100644 .changeset/gentle-flies-try.md create mode 100644 packages/portal-gun/CHANGELOG.md diff --git a/.changeset/gentle-flies-try.md b/.changeset/gentle-flies-try.md deleted file mode 100644 index 850e3289..00000000 --- a/.changeset/gentle-flies-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@inox-tools/utils': minor ---- - -Add unist visitor with support for postorder traversal diff --git a/packages/aik-mod/CHANGELOG.md b/packages/aik-mod/CHANGELOG.md index 986b078f..9a27726c 100644 --- a/packages/aik-mod/CHANGELOG.md +++ b/packages/aik-mod/CHANGELOG.md @@ -1,5 +1,11 @@ # @inox-tools/aik-mod +## 0.8.4 + +### Patch Changes + +- @inox-tools/inline-mod@1.5.2 + ## 0.8.3 ### Patch Changes diff --git a/packages/aik-mod/package.json b/packages/aik-mod/package.json index ea22da21..17776ed7 100644 --- a/packages/aik-mod/package.json +++ b/packages/aik-mod/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/aik-mod", - "version": "0.8.3", + "version": "0.8.4", "description": "AIK Plugin for inline modules", "keywords": [ "aik", diff --git a/packages/aik-route-config/CHANGELOG.md b/packages/aik-route-config/CHANGELOG.md index 99a825fa..419a9e6f 100644 --- a/packages/aik-route-config/CHANGELOG.md +++ b/packages/aik-route-config/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/aik-route-config +## 0.7.4 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 0.7.3 ### Patch Changes diff --git a/packages/aik-route-config/package.json b/packages/aik-route-config/package.json index a8d39823..07c5c6cb 100644 --- a/packages/aik-route-config/package.json +++ b/packages/aik-route-config/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/aik-route-config", - "version": "0.7.3", + "version": "0.7.4", "description": "", "keywords": [ "aik", diff --git a/packages/astro-tests/CHANGELOG.md b/packages/astro-tests/CHANGELOG.md index 750cd24c..0824e428 100644 --- a/packages/astro-tests/CHANGELOG.md +++ b/packages/astro-tests/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/astro-tests +## 0.1.4 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 0.1.3 ### Patch Changes diff --git a/packages/astro-tests/package.json b/packages/astro-tests/package.json index 88747a55..c039c202 100644 --- a/packages/astro-tests/package.json +++ b/packages/astro-tests/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/astro-tests", - "version": "0.1.3", + "version": "0.1.4", "license": "MIT", "author": "Luiz Ferraz ", "type": "module", diff --git a/packages/content-utils/CHANGELOG.md b/packages/content-utils/CHANGELOG.md index 2daeaa7b..4a192bf8 100644 --- a/packages/content-utils/CHANGELOG.md +++ b/packages/content-utils/CHANGELOG.md @@ -1,5 +1,13 @@ # @inox-tools/content-utils +## 0.7.3 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + - @inox-tools/modular-station@0.3.3 + ## 0.7.2 ### Patch Changes diff --git a/packages/content-utils/package.json b/packages/content-utils/package.json index 653f8fa6..0bdd0aba 100644 --- a/packages/content-utils/package.json +++ b/packages/content-utils/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/content-utils", - "version": "0.7.2", + "version": "0.7.3", "description": "Utilities to work with content collections on an Astro project from an integration or library.", "keywords": [ "lifecycle", diff --git a/packages/cut-short/CHANGELOG.md b/packages/cut-short/CHANGELOG.md index aebbdef7..52c6cce2 100644 --- a/packages/cut-short/CHANGELOG.md +++ b/packages/cut-short/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/cut-short +## 0.1.2 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 0.1.1 ### Patch Changes diff --git a/packages/cut-short/package.json b/packages/cut-short/package.json index 4b0ab40b..a25ee61d 100644 --- a/packages/cut-short/package.json +++ b/packages/cut-short/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/cut-short", - "version": "0.1.1", + "version": "0.1.2", "description": "Immediately halt request processing and return custom responses effortlessly.", "keywords": [ "astro-integration", diff --git a/packages/inline-mod/CHANGELOG.md b/packages/inline-mod/CHANGELOG.md index 022c6fe0..0c99fb03 100644 --- a/packages/inline-mod/CHANGELOG.md +++ b/packages/inline-mod/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/inline-mod +## 1.5.2 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 1.5.1 ### Patch Changes diff --git a/packages/inline-mod/package.json b/packages/inline-mod/package.json index 53379811..caab0dd0 100644 --- a/packages/inline-mod/package.json +++ b/packages/inline-mod/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/inline-mod", - "version": "1.5.1", + "version": "1.5.2", "description": "Define a virtual module inline with any reference to buildtime values", "keywords": [ "vite-plugin" diff --git a/packages/modular-station/CHANGELOG.md b/packages/modular-station/CHANGELOG.md index 4bbd8f66..9e1bf444 100644 --- a/packages/modular-station/CHANGELOG.md +++ b/packages/modular-station/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/modular-station +## 0.3.3 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 0.3.2 ### Patch Changes diff --git a/packages/modular-station/package.json b/packages/modular-station/package.json index 52e95e85..fa1961c8 100644 --- a/packages/modular-station/package.json +++ b/packages/modular-station/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/modular-station", - "version": "0.3.2", + "version": "0.3.3", "description": "Simplifying Astro integrations with a flexible docking system.", "keywords": [ "astro-integration", diff --git a/packages/portal-gun/CHANGELOG.md b/packages/portal-gun/CHANGELOG.md new file mode 100644 index 00000000..0b86e211 --- /dev/null +++ b/packages/portal-gun/CHANGELOG.md @@ -0,0 +1,9 @@ +# @inox-tools/portal-gun + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + - @inox-tools/runtime-logger@0.3.4 diff --git a/packages/portal-gun/package.json b/packages/portal-gun/package.json index 7c9439f4..8c1c60d6 100644 --- a/packages/portal-gun/package.json +++ b/packages/portal-gun/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/portal-gun", - "version": "0.0.0", + "version": "0.0.1", "description": "Transport HTML elements through your page during rendering using Portals.", "keywords": [ "astro-integration", diff --git a/packages/portal-gun/tests/basic.test.ts b/packages/portal-gun/tests/basic.test.ts index 72767b53..dfaae45d 100644 --- a/packages/portal-gun/tests/basic.test.ts +++ b/packages/portal-gun/tests/basic.test.ts @@ -3,12 +3,12 @@ import { beforeAll } from 'vitest'; import { defineCommonTests } from './common.js'; const fixture = await loadFixture({ - root: './fixture/basic', - outDir: 'dist/static', + root: './fixture/basic', + outDir: 'dist/static', }); beforeAll(async () => { - await fixture.build({}); + await fixture.build({}); }); defineCommonTests((path) => fixture.readFile(`${path}/index.html`)); diff --git a/packages/portal-gun/tests/common.ts b/packages/portal-gun/tests/common.ts index 1a042bdf..c048e50f 100644 --- a/packages/portal-gun/tests/common.ts +++ b/packages/portal-gun/tests/common.ts @@ -1,10 +1,10 @@ import { expect, test } from 'vitest'; export const defineCommonTests = (loadPath: (path: string) => Promise) => { - test('elements are sent across Astro Components', async () => { - const html = await loadPath('header-footer'); + test('elements are sent across Astro Components', async () => { + const html = await loadPath('header-footer'); - expect(html).toEqualIgnoringWhitespace(` + expect(html).toEqualIgnoringWhitespace(` @@ -24,12 +24,12 @@ export const defineCommonTests = (loadPath: (path: string) => Promise) = `); - }); + }); - test('portals entries without a landing portal get voided', async () => { - const html = await loadPath('missing-portal'); + test('portals entries without a landing portal get voided', async () => { + const html = await loadPath('missing-portal'); - expect(html).toEqualIgnoringWhitespace(` + expect(html).toEqualIgnoringWhitespace(` @@ -43,12 +43,12 @@ export const defineCommonTests = (loadPath: (path: string) => Promise) = `); - }); + }); - test('portal to start and end of identified element', async () => { - const html = await loadPath('id-boundary'); + test('portal to start and end of identified element', async () => { + const html = await loadPath('id-boundary'); - expect(html).toEqualIgnoringWhitespace(` + expect(html).toEqualIgnoringWhitespace(` @@ -66,12 +66,12 @@ export const defineCommonTests = (loadPath: (path: string) => Promise) = `); - }); + }); - test('portal to start and end of head and body', async () => { - const html = await loadPath('global-boundary'); + test('portal to start and end of head and body', async () => { + const html = await loadPath('global-boundary'); - expect(html).toEqualIgnoringWhitespace(` + expect(html).toEqualIgnoringWhitespace(` @@ -94,12 +94,12 @@ export const defineCommonTests = (loadPath: (path: string) => Promise) = `); - }); + }); - test('portal entries from within UI framework component', async () => { - const html = await loadPath('ui-frameworks'); + test('portal entries from within UI framework component', async () => { + const html = await loadPath('ui-frameworks'); - expect(html).toEqualIgnoringWhitespace(` + expect(html).toEqualIgnoringWhitespace(` @@ -117,12 +117,12 @@ export const defineCommonTests = (loadPath: (path: string) => Promise) = `); - }); + }); - test('portals can go through portals', async () => { - const html = await loadPath('nested-portals'); + test('portals can go through portals', async () => { + const html = await loadPath('nested-portals'); - expect(html).toEqualIgnoringWhitespace(` + expect(html).toEqualIgnoringWhitespace(` @@ -140,5 +140,5 @@ export const defineCommonTests = (loadPath: (path: string) => Promise) = `); - }); + }); }; diff --git a/packages/portal-gun/tests/fixture/basic/astro.config.ts b/packages/portal-gun/tests/fixture/basic/astro.config.ts index 5ae4032f..fd2acc6d 100644 --- a/packages/portal-gun/tests/fixture/basic/astro.config.ts +++ b/packages/portal-gun/tests/fixture/basic/astro.config.ts @@ -4,5 +4,5 @@ import portalGun from '@inox-tools/portal-gun'; import preact from '@astrojs/preact'; export default defineConfig({ - integrations: [portalGun(), preact()], -}); \ No newline at end of file + integrations: [portalGun(), preact()], +}); diff --git a/packages/portal-gun/tests/fixture/basic/tsconfig.json b/packages/portal-gun/tests/fixture/basic/tsconfig.json index 99df2e61..41799edc 100644 --- a/packages/portal-gun/tests/fixture/basic/tsconfig.json +++ b/packages/portal-gun/tests/fixture/basic/tsconfig.json @@ -4,4 +4,4 @@ "jsx": "react-jsx", "jsxImportSource": "preact" } -} \ No newline at end of file +} diff --git a/packages/portal-gun/tests/server.test.ts b/packages/portal-gun/tests/server.test.ts index d1df2d33..c5b0fb82 100644 --- a/packages/portal-gun/tests/server.test.ts +++ b/packages/portal-gun/tests/server.test.ts @@ -4,24 +4,24 @@ import { beforeAll } from 'vitest'; import { defineCommonTests } from './common.js'; const fixture = await loadFixture({ - root: './fixture/basic', - outDir: 'dist/server', - build: { - server: 'dist/server/server', - client: 'dist/server/client', - }, - output: 'server', - adapter: testAdapter(), + root: './fixture/basic', + outDir: 'dist/server', + build: { + server: 'dist/server/server', + client: 'dist/server/client', + }, + output: 'server', + adapter: testAdapter(), }); let app: TestApp; beforeAll(async () => { - await fixture.build({}); - app = await fixture.loadTestAdapterApp(); + await fixture.build({}); + app = await fixture.loadTestAdapterApp(); }); defineCommonTests(async (path) => { - const res = await app.render(new Request(`http://example.com/${path}`)); - return res.text(); + const res = await app.render(new Request(`http://example.com/${path}`)); + return res.text(); }); diff --git a/packages/portal-gun/virtual.d.ts b/packages/portal-gun/virtual.d.ts index a8fcd025..c5549a42 100644 --- a/packages/portal-gun/virtual.d.ts +++ b/packages/portal-gun/virtual.d.ts @@ -10,27 +10,27 @@ import 'astro/astro-jsx'; declare module 'astro/astro-jsx' { export namespace astroHTML { export namespace JSX { - export interface IntrinsicElements extends ITAstroPortalGun.NewElements { } + export interface IntrinsicElements extends ITAstroPortalGun.NewElements {} } } } declare global { namespace JSX { - export interface IntrinsicElements extends ITAstroPortalGun.NewElements { } + export interface IntrinsicElements extends ITAstroPortalGun.NewElements {} } namespace preact.JSX { - interface IntrinsicElements extends ITAstroPortalGun.NewElements { } + interface IntrinsicElements extends ITAstroPortalGun.NewElements {} } namespace svelteHTML { - interface IntrinsicElements extends ITAstroPortalGun.NewElements { } + interface IntrinsicElements extends ITAstroPortalGun.NewElements {} } } declare module 'solid-js' { namespace JSX { - interface IntrinsicElements extends ITAstroPortalGun.NewElements { } + interface IntrinsicElements extends ITAstroPortalGun.NewElements {} } } diff --git a/packages/request-nanostores/CHANGELOG.md b/packages/request-nanostores/CHANGELOG.md index 38a7c1dd..de4737c1 100644 --- a/packages/request-nanostores/CHANGELOG.md +++ b/packages/request-nanostores/CHANGELOG.md @@ -1,5 +1,13 @@ # @inox-tools/request-nanostores +## 0.1.4 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + - @inox-tools/request-state@0.1.4 + ## 0.1.3 ### Patch Changes diff --git a/packages/request-nanostores/package.json b/packages/request-nanostores/package.json index e745f5e1..d72dc49b 100644 --- a/packages/request-nanostores/package.json +++ b/packages/request-nanostores/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/request-nanostores", - "version": "0.1.3", + "version": "0.1.4", "description": "Make your Nanostores concurrent safe and shared from server to client", "keywords": [ "astro-integration", diff --git a/packages/request-state/CHANGELOG.md b/packages/request-state/CHANGELOG.md index 9c93cd5d..052ae4e7 100644 --- a/packages/request-state/CHANGELOG.md +++ b/packages/request-state/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/request-state +## 0.1.4 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 0.1.3 ### Patch Changes diff --git a/packages/request-state/package.json b/packages/request-state/package.json index fa823926..0efaaa4e 100644 --- a/packages/request-state/package.json +++ b/packages/request-state/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/request-state", - "version": "0.1.3", + "version": "0.1.4", "description": "Shared request state between server and client", "keywords": [ "astro-integration", diff --git a/packages/runtime-logger/CHANGELOG.md b/packages/runtime-logger/CHANGELOG.md index 9b0a37ae..4f999590 100644 --- a/packages/runtime-logger/CHANGELOG.md +++ b/packages/runtime-logger/CHANGELOG.md @@ -1,5 +1,13 @@ # @inox-tools/runtime-logger +## 0.3.4 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + - @inox-tools/modular-station@0.3.3 + ## 0.3.3 ### Patch Changes diff --git a/packages/runtime-logger/package.json b/packages/runtime-logger/package.json index 8d05fbbf..e578399d 100644 --- a/packages/runtime-logger/package.json +++ b/packages/runtime-logger/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/runtime-logger", - "version": "0.3.3", + "version": "0.3.4", "description": "Expose Astro Integration Logger at runtime for consistent output", "keywords": [ "astro-integration", diff --git a/packages/sitemap-ext/CHANGELOG.md b/packages/sitemap-ext/CHANGELOG.md index 12c022ff..b0bf58e6 100644 --- a/packages/sitemap-ext/CHANGELOG.md +++ b/packages/sitemap-ext/CHANGELOG.md @@ -1,5 +1,11 @@ # @inox-tools/sitemap-ext +## 0.3.5 + +### Patch Changes + +- @inox-tools/aik-route-config@0.7.4 + ## 0.3.4 ### Patch Changes diff --git a/packages/sitemap-ext/package.json b/packages/sitemap-ext/package.json index 59dafd89..97f94017 100644 --- a/packages/sitemap-ext/package.json +++ b/packages/sitemap-ext/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/sitemap-ext", - "version": "0.3.4", + "version": "0.3.5", "description": "Higher level extension over Astro's official sitemap integration", "keywords": [ "sitemap", diff --git a/packages/star-warp/CHANGELOG.md b/packages/star-warp/CHANGELOG.md index 1d9c9e1b..1f65a15e 100644 --- a/packages/star-warp/CHANGELOG.md +++ b/packages/star-warp/CHANGELOG.md @@ -1,5 +1,12 @@ # @inox-tools/star-warp +## 0.1.4 + +### Patch Changes + +- Updated dependencies [e07b8a8] + - @inox-tools/utils@0.2.0 + ## 0.1.3 ### Patch Changes diff --git a/packages/star-warp/package.json b/packages/star-warp/package.json index d206e645..c8d23789 100644 --- a/packages/star-warp/package.json +++ b/packages/star-warp/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/star-warp", - "version": "0.1.3", + "version": "0.1.4", "description": "Warp-drive search for Astro sites using Pagefind", "keywords": [ "astro-integration", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index f03f3f18..2c6629b3 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @inox-tools/utils +## 0.2.0 + +### Minor Changes + +- e07b8a8: Add unist visitor with support for postorder traversal + ## 0.1.4 ### Patch Changes diff --git a/packages/utils/package.json b/packages/utils/package.json index 1a529386..08fa4e97 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@inox-tools/utils", - "version": "0.1.4", + "version": "0.2.0", "description": "A collection of utilities used throughout Inox Tools", "keywords": [ "utilities" diff --git a/packages/utils/src/unist/visit.ts b/packages/utils/src/unist/visit.ts index 46ad5f93..76c492b3 100644 --- a/packages/utils/src/unist/visit.ts +++ b/packages/utils/src/unist/visit.ts @@ -18,127 +18,127 @@ export const EXIT = false; export const SKIP = 'skip'; export type Options = { - tree: Tree; - test?: Check; - enter?: BuildVisitor; - leave?: BuildVisitor; - reverse?: boolean; + tree: Tree; + test?: Check; + enter?: BuildVisitor; + leave?: BuildVisitor; + reverse?: boolean; }; export function visitParents({ - tree, - test, - enter: enterVisitor, - leave: leaveVisitor, - reverse, + tree, + test, + enter: enterVisitor, + leave: leaveVisitor, + reverse, }: Options) { - if (!tree) { - throw new TypeError('A tree is required'); - } + if (!tree) { + throw new TypeError('A tree is required'); + } - if (!enterVisitor && !leaveVisitor) { - throw new Error('At least one visitor (`enter` or `leave`) must be provided'); - } + if (!enterVisitor && !leaveVisitor) { + throw new Error('At least one visitor (`enter` or `leave`) must be provided'); + } - const is = convert(test) as ( - node: UnistNode, - index?: number, - parent?: UnistParent - ) => node is Matches, Check>; - const step = reverse ? -1 : 1; + const is = convert(test) as ( + node: UnistNode, + index?: number, + parent?: UnistParent + ) => node is Matches, Check>; + const step = reverse ? -1 : 1; - factory(tree, undefined, [])(); + factory(tree, undefined, [])(); - function factory(node: UnistNode, index: number | undefined, parents: UnistParent[]) { - const value = node as UnistNode & Record; + function factory(node: UnistNode, index: number | undefined, parents: UnistParent[]) { + const value = node as UnistNode & Record; - if (typeof value.type === 'string') { - const name = - // `hast` - typeof value.tagName === 'string' - ? value.tagName - : // `xast` - typeof value.name === 'string' - ? value.name - : undefined; + if (typeof value.type === 'string') { + const name = + // `hast` + typeof value.tagName === 'string' + ? value.tagName + : // `xast` + typeof value.name === 'string' + ? value.name + : undefined; - Object.defineProperty(visit, 'name', { - value: 'node (' + node.type + (name ? '<' + name + '>' : '') + ')', - }); - } + Object.defineProperty(visit, 'name', { + value: 'node (' + node.type + (name ? '<' + name + '>' : '') + ')', + }); + } - return visit; + return visit; - function visit() { - let result: Readonly = empty; - let subresult: Readonly; - let offset: number; - let grandparents: UnistParent[]; - const isMatch = !test || is(node, index, parents[parents.length - 1]); + function visit() { + let result: Readonly = empty; + let subresult: Readonly; + let offset: number; + let grandparents: UnistParent[]; + const isMatch = !test || is(node, index, parents[parents.length - 1]); - if (isMatch) { - result = toResult( - enterVisitor?.( - node as Matches, Check>, - parents as Array, Check>>> - ) - ); + if (isMatch) { + result = toResult( + enterVisitor?.( + node as Matches, Check>, + parents as Array, Check>>> + ) + ); - if (result[0] === EXIT) { - return result; - } - } + if (result[0] === EXIT) { + return result; + } + } - if ('children' in node && node.children) { - const nodeAsParent = node as UnistParent; + if ('children' in node && node.children) { + const nodeAsParent = node as UnistParent; - if (nodeAsParent.children && result[0] !== SKIP) { - offset = (reverse ? nodeAsParent.children.length : -1) + step; - grandparents = parents.concat(nodeAsParent); + if (nodeAsParent.children && result[0] !== SKIP) { + offset = (reverse ? nodeAsParent.children.length : -1) + step; + grandparents = parents.concat(nodeAsParent); - while (offset > -1 && offset < nodeAsParent.children.length) { - const child = nodeAsParent.children[offset]; + while (offset > -1 && offset < nodeAsParent.children.length) { + const child = nodeAsParent.children[offset]; - subresult = factory(child, offset, grandparents)(); + subresult = factory(child, offset, grandparents)(); - if (subresult[0] === EXIT) { - return subresult; - } + if (subresult[0] === EXIT) { + return subresult; + } - offset = typeof subresult[1] === 'number' ? subresult[1] : offset + step; - } - } - } + offset = typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + } - if (isMatch && leaveVisitor) { - const leaveResult = toResult( - leaveVisitor( - node as Matches, Check>, - parents as Array, Check>>> - ) - ); + if (isMatch && leaveVisitor) { + const leaveResult = toResult( + leaveVisitor( + node as Matches, Check>, + parents as Array, Check>>> + ) + ); - return leaveResult === empty ? result : leaveResult; - } + return leaveResult === empty ? result : leaveResult; + } - return result; - } - } + return result; + } + } } /** * Turn a return value into a clean result. */ function toResult(value: VisitorResult): Readonly { - if (Array.isArray(value)) { - return value; - } + if (Array.isArray(value)) { + return value; + } - if (typeof value === 'number') { - return [CONTINUE, value]; - } + if (typeof value === 'number') { + return [CONTINUE, value]; + } - return value === null || value === undefined ? empty : [value]; + return value === null || value === undefined ? empty : [value]; } export type UnistNode = import('unist').Node; @@ -155,29 +155,29 @@ export type Test = Exclude | undefined; * Get the value of a type guard `Fn`. */ export type Predicate = Fn extends (value: any) => value is infer Thing - ? Thing - : Fallback; + ? Thing + : Fallback; /** * Check whether a node matches a primitive check in the type system. */ export type MatchesOne = Check extends null | undefined - ? Value - : Value extends { - type: Check; - } - ? Value - : Value extends Check - ? Value - : Check extends Function - ? Predicate extends Value - ? Predicate - : never - : never; + ? Value + : Value extends { + type: Check; + } + ? Value + : Value extends Check + ? Value + : Check extends Function + ? Predicate extends Value + ? Predicate + : never + : never; /** * Check whether a node matches a check in the type system. */ export type Matches = - Check extends Array ? MatchesOne : MatchesOne; + Check extends Array ? MatchesOne : MatchesOne; /** * Number; capped reasonably. */ @@ -186,65 +186,65 @@ export type Uint = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; * Increment a number in the type system. */ export type Increment = I extends 0 - ? 1 - : I extends 1 - ? 2 - : I extends 2 - ? 3 - : I extends 3 - ? 4 - : I extends 4 - ? 5 - : I extends 5 - ? 6 - : I extends 6 - ? 7 - : I extends 7 - ? 8 - : I extends 8 - ? 9 - : 10; + ? 1 + : I extends 1 + ? 2 + : I extends 2 + ? 3 + : I extends 3 + ? 4 + : I extends 4 + ? 5 + : I extends 5 + ? 6 + : I extends 6 + ? 7 + : I extends 7 + ? 8 + : I extends 8 + ? 9 + : 10; /** * Collect nodes that can be parents of `Child`. */ export type InternalParent< - Node extends import('unist').Node, - Child extends import('unist').Node, + Node extends import('unist').Node, + Child extends import('unist').Node, > = Node extends import('unist').Parent - ? Node extends { - children: (infer Children)[]; - } - ? Child extends Children - ? Node - : never - : never - : never; + ? Node extends { + children: (infer Children)[]; + } + ? Child extends Children + ? Node + : never + : never + : never; /** * Collect nodes in `Tree` that can be parents of `Child`. */ export type Parent< - Tree extends import('unist').Node, - Child extends import('unist').Node, + Tree extends import('unist').Node, + Child extends import('unist').Node, > = InternalParent, Child>; /** * Collect nodes in `Tree` that can be ancestors of `Child`. */ export type InternalAncestor< - Node extends import('unist').Node, - Child extends import('unist').Node, - Max extends Uint = 10, - Depth extends Uint = 0, + Node extends import('unist').Node, + Child extends import('unist').Node, + Max extends Uint = 10, + Depth extends Uint = 0, > = Depth extends Max - ? never - : - | InternalParent - | InternalAncestor, Max, Increment>; + ? never + : + | InternalParent + | InternalAncestor, Max, Increment>; /** * Collect nodes in `Tree` that can be ancestors of `Child`. */ export type Ancestor< - Tree extends import('unist').Node, - Child extends import('unist').Node, + Tree extends import('unist').Node, + Child extends import('unist').Node, > = InternalAncestor, Child>; /** * Collect all (inclusive) descendants of `Tree`. @@ -259,14 +259,14 @@ export type Ancestor< * > Using up to `10` doesn’t hurt or help either. */ export type InclusiveDescendant< - Tree extends import('unist').Node, - Max extends Uint = 10, - Depth extends Uint = 0, + Tree extends import('unist').Node, + Max extends Uint = 10, + Depth extends Uint = 0, > = Tree extends UnistParent - ? Depth extends Max - ? Tree - : Tree | InclusiveDescendant> - : Tree; + ? Depth extends Max + ? Tree + : Tree | InclusiveDescendant> + : Tree; /** * Union of the action types. */ @@ -289,12 +289,12 @@ export type ActionTuple = [(Action | null | undefined | void)?, (Index | null | * Any value that can be returned from a visitor. */ export type VisitorResult = - | Action - | [(void | Action | null | undefined)?, (number | null | undefined)?] - | Index - | null - | undefined - | void; + | Action + | [(void | Action | null | undefined)?, (number | null | undefined)?] + | Index + | null + | undefined + | void; /** * Handle a node (matching `test`, if given). * @@ -314,8 +314,8 @@ export type VisitorResult = * traversed. */ export type Visitor< - Visited extends import('unist').Node = import('unist').Node, - VisitedParents extends import('unist').Parent = import('unist').Parent, + Visited extends import('unist').Node = import('unist').Node, + VisitedParents extends import('unist').Parent = import('unist').Parent, > = (node: Visited, ancestors: Array) => VisitorResult; /** @@ -324,9 +324,9 @@ export type Visitor< * It will infer which values are passed as `node` and which as `parents`. */ export type BuildVisitor< - Tree extends import('unist').Node = import('unist').Node, - Check extends Test = Test, + Tree extends import('unist').Node = import('unist').Node, + Check extends Test = Test, > = Visitor< - Matches, Check>, - Ancestor, Check>> + Matches, Check>, + Ancestor, Check>> >; diff --git a/packages/utils/tests/unist/visit.test.ts b/packages/utils/tests/unist/visit.test.ts index 1e51ddb3..39ae2289 100644 --- a/packages/utils/tests/unist/visit.test.ts +++ b/packages/utils/tests/unist/visit.test.ts @@ -21,632 +21,632 @@ const skipIndex = 7; const skipReverseIndex = 6; const types = [ - 'root', // [] - 'paragraph', // [tree] - 'text', // [tree, paragraph] - 'emphasis', // [tree, paragraph] - 'text', // [tree, paragraph, emphasis] - 'text', // [tree, paragraph] - 'strong', // [tree, paragraph] - 'text', // [tree, paragraph, strong] - 'text', // [tree, paragraph] - 'inlineCode', // [tree, paragraph] - 'text', // [tree, paragraph] + 'root', // [] + 'paragraph', // [tree] + 'text', // [tree, paragraph] + 'emphasis', // [tree, paragraph] + 'text', // [tree, paragraph, emphasis] + 'text', // [tree, paragraph] + 'strong', // [tree, paragraph] + 'text', // [tree, paragraph, strong] + 'text', // [tree, paragraph] + 'inlineCode', // [tree, paragraph] + 'text', // [tree, paragraph] ]; const reverseTypes = [ - 'root', - 'paragraph', - 'text', - 'inlineCode', - 'text', - 'strong', - 'text', - 'text', - 'emphasis', - 'text', - 'text', + 'root', + 'paragraph', + 'text', + 'inlineCode', + 'text', + 'strong', + 'text', + 'text', + 'emphasis', + 'text', + 'text', ]; const ancestors: Array> = [ - [], - [tree], - [tree, paragraph], - [tree, paragraph], - [tree, paragraph, emphasis], - [tree, paragraph], - [tree, paragraph], - [tree, paragraph, strong], - [tree, paragraph], - [tree, paragraph], - [tree, paragraph], + [], + [tree], + [tree, paragraph], + [tree, paragraph], + [tree, paragraph, emphasis], + [tree, paragraph], + [tree, paragraph], + [tree, paragraph, strong], + [tree, paragraph], + [tree, paragraph], + [tree, paragraph], ]; const textAncestors: Array> = [ - [tree, paragraph], - [tree, paragraph, emphasis], - [tree, paragraph], - [tree, paragraph, strong], - [tree, paragraph], - [tree, paragraph], + [tree, paragraph], + [tree, paragraph, emphasis], + [tree, paragraph], + [tree, paragraph, strong], + [tree, paragraph], + [tree, paragraph], ]; test('should expose the public api', async function () { - assert.deepEqual(Object.keys(await import('../../src/unist/visit.js')).sort(), [ - 'CONTINUE', - 'EXIT', - 'SKIP', - 'visitParents', - ]); + assert.deepEqual(Object.keys(await import('../../src/unist/visit.js')).sort(), [ + 'CONTINUE', + 'EXIT', + 'SKIP', + 'visitParents', + ]); }); test('should fail without tree', async function () { - assert.throws(function () { - // @ts-expect-error: check that the runtime throws an error. - visitParents({}); - }, 'Error: A tree is required'); + assert.throws(function () { + // @ts-expect-error: check that the runtime throws an error. + visitParents({}); + }, 'Error: A tree is required'); }); test('should fail without visitor', async function () { - assert.throws(function () { - visitParents({ tree }); - }, 'Error: At least one visitor (`enter` or `leave`) must be provided'); + assert.throws(function () { + visitParents({ tree }); + }, 'Error: At least one visitor (`enter` or `leave`) must be provided'); }); test('should iterate over all nodes', function () { - let n = 0; - - visitParents({ - tree, - enter: function (node, parents) { - assert.strictEqual(node.type, types[n], 'should be the expected type'); - assert.deepStrictEqual(parents, ancestors[n], 'should have expected parents'); - n++; - }, - }); - - assert.equal(n, types.length, 'should visit all nodes'); + let n = 0; + + visitParents({ + tree, + enter: function (node, parents) { + assert.strictEqual(node.type, types[n], 'should be the expected type'); + assert.deepStrictEqual(parents, ancestors[n], 'should have expected parents'); + n++; + }, + }); + + assert.equal(n, types.length, 'should visit all nodes'); }); test('should iterate over all nodes, backwards', function () { - let n = 0; - - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, reverseTypes[n], 'should be the expected type'); - n++; - }, - reverse: true, - }); - - assert.equal(n, reverseTypes.length, 'should visit all nodes in reverse'); + let n = 0; + + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, reverseTypes[n], 'should be the expected type'); + n++; + }, + reverse: true, + }); + + assert.equal(n, reverseTypes.length, 'should visit all nodes in reverse'); }); test('should only visit a given `type`', function () { - let n = 0; - - visitParents({ - tree, - test: 'text', - enter: function (node, parents) { - assert.strictEqual(node.type, 'text'); - assert.deepStrictEqual(parents, textAncestors[n]); - n++; - }, - }); - - assert.equal(n, textNodes, 'should visit all nodes'); + let n = 0; + + visitParents({ + tree, + test: 'text', + enter: function (node, parents) { + assert.strictEqual(node.type, 'text'); + assert.deepStrictEqual(parents, textAncestors[n]); + n++; + }, + }); + + assert.equal(n, textNodes, 'should visit all nodes'); }); test('should only visit given `type`s', function () { - const types = ['text', 'inlineCode']; - let n = 0; - - visitParents({ - tree, - test: types, - enter: function (node) { - assert.notStrictEqual(types.indexOf(node.type), -1, 'should match'); - n++; - }, - }); - - assert.equal(n, 7, 'should visit all matching nodes'); + const types = ['text', 'inlineCode']; + let n = 0; + + visitParents({ + tree, + test: types, + enter: function (node) { + assert.notStrictEqual(types.indexOf(node.type), -1, 'should match'); + n++; + }, + }); + + assert.equal(n, 7, 'should visit all matching nodes'); }); test('should accept any `is`-compatible test function', function () { - let n = 0; - const nodes: Array = [ - paragraph.children[4], - paragraph.children[5], - paragraph.children[6], - ]; - - visitParents({ - tree, - test: function (_, index) { - return typeof index === 'number' && index > 3; - }, - enter: function (node, parents) { - const parent = parents[parents.length - 1]; - // @ts-expect-error: `node` can always be inside parent. - const index = parent ? parent.children.indexOf(node) : undefined; - const info = '(' + (parent && parent.type) + ':' + index + ')'; - assert.strictEqual(node, nodes[n], 'should be a requested node ' + info); - n++; - }, - }); - - assert.equal(n, 3, 'should visit all passing nodes'); + let n = 0; + const nodes: Array = [ + paragraph.children[4], + paragraph.children[5], + paragraph.children[6], + ]; + + visitParents({ + tree, + test: function (_, index) { + return typeof index === 'number' && index > 3; + }, + enter: function (node, parents) { + const parent = parents[parents.length - 1]; + // @ts-expect-error: `node` can always be inside parent. + const index = parent ? parent.children.indexOf(node) : undefined; + const info = '(' + (parent && parent.type) + ':' + index + ')'; + assert.strictEqual(node, nodes[n], 'should be a requested node ' + info); + n++; + }, + }); + + assert.equal(n, 3, 'should visit all passing nodes'); }); test('should accept an array of `is`-compatible tests', function () { - const expected = new Set(['root', 'paragraph', 'emphasis', 'strong']); - let n = 0; - - visitParents({ - tree, - test: [ - function (node) { - return node.type === 'root'; - }, - 'paragraph', - { value: '.' }, - 'emphasis', - 'strong', - ], - enter: function (node) { - const ok = expected.has(node.type) || ('value' in node && node.value === '.'); - assert.ok(ok, 'should be a requested type: ' + node.type); - n++; - }, - }); - - assert.equal(n, 5, 'should visit all passing nodes'); + const expected = new Set(['root', 'paragraph', 'emphasis', 'strong']); + let n = 0; + + visitParents({ + tree, + test: [ + function (node) { + return node.type === 'root'; + }, + 'paragraph', + { value: '.' }, + 'emphasis', + 'strong', + ], + enter: function (node) { + const ok = expected.has(node.type) || ('value' in node && node.value === '.'); + assert.ok(ok, 'should be a requested type: ' + node.type); + n++; + }, + }); + + assert.equal(n, 5, 'should visit all passing nodes'); }); test('should stop if enter `visitor` stops', function () { - let n = -1; + let n = -1; - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, types[++n]); - return n === stopIndex ? EXIT : CONTINUE; - }, - }); + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, types[++n]); + return n === stopIndex ? EXIT : CONTINUE; + }, + }); - assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); + assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); }); test('should stop if leave `visitor` stops', function () { - let n = -1; + let n = -1; - visitParents({ - tree, - leave: function () { - return ++n === stopIndex ? EXIT : CONTINUE; - }, - }); + visitParents({ + tree, + leave: function () { + return ++n === stopIndex ? EXIT : CONTINUE; + }, + }); - assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); + assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); }); test('should stop if enter `visitor` stops (tuple)', function () { - let n = -1; + let n = -1; - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, types[++n]); - return [n === stopIndex ? EXIT : CONTINUE]; - }, - }); + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, types[++n]); + return [n === stopIndex ? EXIT : CONTINUE]; + }, + }); - assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); + assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); }); test('should stop if enter `visitor` stops, backwards', function () { - let n = 0; - - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, reverseTypes[n++], 'should be the expected type'); - return n === stopIndex ? EXIT : CONTINUE; - }, - reverse: true, - }); - - assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); + let n = 0; + + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, reverseTypes[n++], 'should be the expected type'); + return n === stopIndex ? EXIT : CONTINUE; + }, + reverse: true, + }); + + assert.equal(n, stopIndex, 'should visit nodes until `EXIT` is given'); }); test('should skip if enter `visitor` skips', function () { - let n = 0; - let count = 0; - - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, types[n++], 'should be the expected type'); - count++; - - if (n === skipIndex) { - n++; // The one node inside it. - return SKIP; - } - }, - }); - - assert.equal(count, types.length - 1, 'should visit nodes except when `SKIP` is given'); + let n = 0; + let count = 0; + + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, types[n++], 'should be the expected type'); + count++; + + if (n === skipIndex) { + n++; // The one node inside it. + return SKIP; + } + }, + }); + + assert.equal(count, types.length - 1, 'should visit nodes except when `SKIP` is given'); }); test('should skip if enter `visitor` skips (tuple)', function () { - let n = 0; - let count = 0; - - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, types[n++], 'should be the expected type'); - count++; - - if (n === skipIndex) { - n++; // The one node inside it. - return [SKIP]; - } - }, - }); - - assert.equal(count, types.length - 1, 'should visit nodes except when `SKIP` is given'); + let n = 0; + let count = 0; + + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, types[n++], 'should be the expected type'); + count++; + + if (n === skipIndex) { + n++; // The one node inside it. + return [SKIP]; + } + }, + }); + + assert.equal(count, types.length - 1, 'should visit nodes except when `SKIP` is given'); }); test('should skip if enter `visitor` skips, backwards', function () { - let n = 0; - let count = 0; - - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, reverseTypes[n++], 'should be the expected type'); - count++; - - if (n === skipReverseIndex) { - n++; // The one node inside it. - return SKIP; - } - }, - reverse: true, - }); - - assert.equal(count, reverseTypes.length - 1, 'should visit nodes except when `SKIP` is given'); + let n = 0; + let count = 0; + + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, reverseTypes[n++], 'should be the expected type'); + count++; + + if (n === skipReverseIndex) { + n++; // The one node inside it. + return SKIP; + } + }, + reverse: true, + }); + + assert.equal(count, reverseTypes.length - 1, 'should visit nodes except when `SKIP` is given'); }); test('should support a given `index` to iterate over next (`0` to reiterate)', function () { - let n = 0; - let again = false; - const expected = [ - 'root', - 'paragraph', - 'text', - 'emphasis', - 'text', - 'text', - 'strong', - 'text', - 'text', // Again. - 'emphasis', - 'text', - 'text', - 'strong', - 'text', - 'text', - 'inlineCode', - 'text', - ]; - - visitParents({ - tree, - enter: function (node) { - assert.strictEqual(node.type, expected[n++], 'should be the expected type'); - - if (again === false && node.type === 'strong') { - again = true; - return 0; // Start over. - } - }, - }); - - assert.equal(n, expected.length, 'should visit nodes again'); + let n = 0; + let again = false; + const expected = [ + 'root', + 'paragraph', + 'text', + 'emphasis', + 'text', + 'text', + 'strong', + 'text', + 'text', // Again. + 'emphasis', + 'text', + 'text', + 'strong', + 'text', + 'text', + 'inlineCode', + 'text', + ]; + + visitParents({ + tree, + enter: function (node) { + assert.strictEqual(node.type, expected[n++], 'should be the expected type'); + + if (again === false && node.type === 'strong') { + again = true; + return 0; // Start over. + } + }, + }); + + assert.equal(n, expected.length, 'should visit nodes again'); }); test('should support a given `index` to iterate over next (`children.length` to skip further children)', function () { - let n = 0; - let again = false; - const expected = [ - 'root', - 'paragraph', - 'text', - 'emphasis', - 'text', - 'text', - 'strong', // Skip here. */ - 'text', - ]; - - visitParents({ - tree, - enter: function (node, parents) { - const parent = parents[parents.length - 1]; - - assert.strictEqual(node.type, expected[n++], 'should be the expected type'); - - if (again === false && node.type === 'strong') { - again = true; - return parent.children.length; // Skip siblings. - } - }, - }); - - assert.equal(n, expected.length, 'should skip nodes'); + let n = 0; + let again = false; + const expected = [ + 'root', + 'paragraph', + 'text', + 'emphasis', + 'text', + 'text', + 'strong', // Skip here. */ + 'text', + ]; + + visitParents({ + tree, + enter: function (node, parents) { + const parent = parents[parents.length - 1]; + + assert.strictEqual(node.type, expected[n++], 'should be the expected type'); + + if (again === false && node.type === 'strong') { + again = true; + return parent.children.length; // Skip siblings. + } + }, + }); + + assert.equal(n, expected.length, 'should skip nodes'); }); test('should support any other given `index` to iterate over next', function () { - let n = 0; - let again = false; - const expected = [ - 'root', - 'paragraph', - 'text', - 'emphasis', - 'text', - 'text', - 'strong', - 'text', - 'inlineCode', // Skip to here. - 'text', - ]; - - visitParents({ - tree, - enter: function (node, parents) { - const parent = parents[parents.length - 1]; - // @ts-expect-error: `node` can always be inside parent. - const index = parent ? parent.children.indexOf(node) : undefined; - - assert.strictEqual(node.type, expected[n++], 'should be the expected type'); - - if (index !== undefined && again === false && node.type === 'strong') { - again = true; - return index + 2; // Skip to `inlineCode`. - } - }, - }); - - assert.equal(n, expected.length, 'should skip nodes'); + let n = 0; + let again = false; + const expected = [ + 'root', + 'paragraph', + 'text', + 'emphasis', + 'text', + 'text', + 'strong', + 'text', + 'inlineCode', // Skip to here. + 'text', + ]; + + visitParents({ + tree, + enter: function (node, parents) { + const parent = parents[parents.length - 1]; + // @ts-expect-error: `node` can always be inside parent. + const index = parent ? parent.children.indexOf(node) : undefined; + + assert.strictEqual(node.type, expected[n++], 'should be the expected type'); + + if (index !== undefined && again === false && node.type === 'strong') { + again = true; + return index + 2; // Skip to `inlineCode`. + } + }, + }); + + assert.equal(n, expected.length, 'should skip nodes'); }); test('should support any other given `index` to iterate over next (tuple)', function () { - let n = 0; - let again = false; - const expected = [ - 'root', - 'paragraph', - 'text', - 'emphasis', - 'text', - 'text', - 'strong', - 'text', - 'inlineCode', // Skip to here. - 'text', - ]; - - visitParents({ - tree, - enter: function (node, parents) { - const parent = parents[parents.length - 1]; - // @ts-expect-error: `node` can always be inside parent. - const index = parent ? parent.children.indexOf(node) : undefined; - - assert.strictEqual(node.type, expected[n++], 'should be the expected type'); - - if (index !== undefined && again === false && node.type === 'strong') { - again = true; - return [undefined, index + 2]; // Skip to `inlineCode`. - } - }, - }); - - assert.equal(n, expected.length, 'should skip nodes'); + let n = 0; + let again = false; + const expected = [ + 'root', + 'paragraph', + 'text', + 'emphasis', + 'text', + 'text', + 'strong', + 'text', + 'inlineCode', // Skip to here. + 'text', + ]; + + visitParents({ + tree, + enter: function (node, parents) { + const parent = parents[parents.length - 1]; + // @ts-expect-error: `node` can always be inside parent. + const index = parent ? parent.children.indexOf(node) : undefined; + + assert.strictEqual(node.type, expected[n++], 'should be the expected type'); + + if (index !== undefined && again === false && node.type === 'strong') { + again = true; + return [undefined, index + 2]; // Skip to `inlineCode`. + } + }, + }); + + assert.equal(n, expected.length, 'should skip nodes'); }); test('should visit added nodes', function () { - const tree = fromMarkdown('Some _emphasis_, **importance**, and `code`.'); - const other = fromMarkdown('Another [sentence]($sentence).'); - const l = types.length + 5; // (p, text, link, text, text) - let n = 0; - - visitParents({ - tree, - enter: function (_, parents) { - n++; - - if (n === 2) { - const parent = parents[parents.length - 1]; - assert.ok(parent.type === 'root'); - parent.children.push(...other.children); - } - }, - }); - - assert.equal(n, l, 'should walk over all nodes'); + const tree = fromMarkdown('Some _emphasis_, **importance**, and `code`.'); + const other = fromMarkdown('Another [sentence]($sentence).'); + const l = types.length + 5; // (p, text, link, text, text) + let n = 0; + + visitParents({ + tree, + enter: function (_, parents) { + n++; + + if (n === 2) { + const parent = parents[parents.length - 1]; + assert.ok(parent.type === 'root'); + parent.children.push(...other.children); + } + }, + }); + + assert.equal(n, l, 'should walk over all nodes'); }); test('should visit nodes in the correct order', function () { - const tree = fromMarkdown('Some _emphasis_, **importance**, `code` and [link](#link "title").'); - const preorder: string[] = []; - const postorder: string[] = []; - - visitParents({ - tree, - enter: (node) => { - preorder.push(node.type === 'text' ? `text (${node.value})` : node.type); - }, - leave: (node) => { - postorder.push(node.type === 'text' ? `text (${node.value})` : node.type); - }, - }); - - const expectedPreorder: string[] = [ - 'root', - 'paragraph', - 'text (Some )', - 'emphasis', - 'text (emphasis)', - 'text (, )', - 'strong', - 'text (importance)', - 'text (, )', - 'inlineCode', - 'text ( and )', - 'link', - 'text (link)', - 'text (.)', - ]; - - const expectedPostorder: string[] = [ - 'text (Some )', - 'text (emphasis)', - 'emphasis', - 'text (, )', - 'text (importance)', - 'strong', - 'text (, )', - 'inlineCode', - 'text ( and )', - 'text (link)', - 'link', - 'text (.)', - 'paragraph', - 'root', - ]; - - assert.deepEqual( - preorder, - expectedPreorder, - 'should not visit nodes in the wrong order (preorder)' - ); - assert.deepEqual( - postorder, - expectedPostorder, - 'should visit nodes in the correct order (postorder)' - ); + const tree = fromMarkdown('Some _emphasis_, **importance**, `code` and [link](#link "title").'); + const preorder: string[] = []; + const postorder: string[] = []; + + visitParents({ + tree, + enter: (node) => { + preorder.push(node.type === 'text' ? `text (${node.value})` : node.type); + }, + leave: (node) => { + postorder.push(node.type === 'text' ? `text (${node.value})` : node.type); + }, + }); + + const expectedPreorder: string[] = [ + 'root', + 'paragraph', + 'text (Some )', + 'emphasis', + 'text (emphasis)', + 'text (, )', + 'strong', + 'text (importance)', + 'text (, )', + 'inlineCode', + 'text ( and )', + 'link', + 'text (link)', + 'text (.)', + ]; + + const expectedPostorder: string[] = [ + 'text (Some )', + 'text (emphasis)', + 'emphasis', + 'text (, )', + 'text (importance)', + 'strong', + 'text (, )', + 'inlineCode', + 'text ( and )', + 'text (link)', + 'link', + 'text (.)', + 'paragraph', + 'root', + ]; + + assert.deepEqual( + preorder, + expectedPreorder, + 'should not visit nodes in the wrong order (preorder)' + ); + assert.deepEqual( + postorder, + expectedPostorder, + 'should visit nodes in the correct order (postorder)' + ); }); test('should recurse into a bazillion nodes', function () { - const expected = 3000; - const tree = fromMarkdown(Array.from({ length: expected / 4 }).join('* 1. ') + 'asd'); - let n = 1; - - visitParents({ - tree, - enter: function () { - n++; - }, - }); - - assert.equal(n, expected, 'should walk over all nodes'); + const expected = 3000; + const tree = fromMarkdown(Array.from({ length: expected / 4 }).join('* 1. ') + 'asd'); + let n = 1; + + visitParents({ + tree, + enter: function () { + n++; + }, + }); + + assert.equal(n, expected, 'should walk over all nodes'); }); test('should add a pretty stack (hast)', function () { - const tree: import('hast').Root = { - type: 'root', - children: [ - { - type: 'element', - tagName: 'div', - properties: {}, - children: [{ type: 'text', value: 'Oh no!' }], - }, - ], - }; - let message = ''; - - try { - visitParents({ - tree, - test: 'text', - enter: function (node) { - throw new Error(node.value); - }, - }); - } catch (error) { - message = String(error && typeof error === 'object' && 'stack' in error ? error.stack : error); - } - - const stack = message - .replace(/\(\S*\/([\w.]+\.[tj]s):\d+:\d+\)/gm, '($1:1:1)') - .split('\n') - .slice(0, 6) - .join('\n'); - - assert.equal( - stack, - [ - 'Error: Oh no!', - ' at enter (visit.test.ts:1:1)', - ' at node (text) (visit.ts:1:1)', - ' at node (element
) (visit.ts:1:1)', - ' at node (root) (visit.ts:1:1)', - ' at Module.visitParents (visit.ts:1:1)', - ].join('\n'), - 'should provide a useful stack trace' - ); + const tree: import('hast').Root = { + type: 'root', + children: [ + { + type: 'element', + tagName: 'div', + properties: {}, + children: [{ type: 'text', value: 'Oh no!' }], + }, + ], + }; + let message = ''; + + try { + visitParents({ + tree, + test: 'text', + enter: function (node) { + throw new Error(node.value); + }, + }); + } catch (error) { + message = String(error && typeof error === 'object' && 'stack' in error ? error.stack : error); + } + + const stack = message + .replace(/\(\S*\/([\w.]+\.[tj]s):\d+:\d+\)/gm, '($1:1:1)') + .split('\n') + .slice(0, 6) + .join('\n'); + + assert.equal( + stack, + [ + 'Error: Oh no!', + ' at enter (visit.test.ts:1:1)', + ' at node (text) (visit.ts:1:1)', + ' at node (element
) (visit.ts:1:1)', + ' at node (root) (visit.ts:1:1)', + ' at Module.visitParents (visit.ts:1:1)', + ].join('\n'), + 'should provide a useful stack trace' + ); }); test('should add a pretty stack (xast)', function () { - const tree: import('xast').Root = { - type: 'root', - children: [ - { - type: 'element', - name: 'xml', - attributes: {}, - children: [{ type: 'text', value: 'Oh no!' }], - }, - ], - }; - let message = ''; - - try { - visitParents({ - tree, - test: 'text', - enter: function (node) { - throw new Error(node.value); - }, - }); - } catch (error) { - message = String(error && typeof error === 'object' && 'stack' in error ? error.stack : error); - } - - const stack = message - .replace(/\(\S*\/([\w.]+\.[tj]s):\d+:\d+\)/gm, '($1:1:1)') - .split('\n') - .slice(0, 6) - .join('\n'); - - assert.equal( - stack, - [ - 'Error: Oh no!', - ' at enter (visit.test.ts:1:1)', - ' at node (text) (visit.ts:1:1)', - ' at node (element) (visit.ts:1:1)', - ' at node (root) (visit.ts:1:1)', - ' at Module.visitParents (visit.ts:1:1)', - ].join('\n') - ); + const tree: import('xast').Root = { + type: 'root', + children: [ + { + type: 'element', + name: 'xml', + attributes: {}, + children: [{ type: 'text', value: 'Oh no!' }], + }, + ], + }; + let message = ''; + + try { + visitParents({ + tree, + test: 'text', + enter: function (node) { + throw new Error(node.value); + }, + }); + } catch (error) { + message = String(error && typeof error === 'object' && 'stack' in error ? error.stack : error); + } + + const stack = message + .replace(/\(\S*\/([\w.]+\.[tj]s):\d+:\d+\)/gm, '($1:1:1)') + .split('\n') + .slice(0, 6) + .join('\n'); + + assert.equal( + stack, + [ + 'Error: Oh no!', + ' at enter (visit.test.ts:1:1)', + ' at node (text) (visit.ts:1:1)', + ' at node (element) (visit.ts:1:1)', + ' at node (root) (visit.ts:1:1)', + ' at Module.visitParents (visit.ts:1:1)', + ].join('\n') + ); });