diff --git a/.eslintrc.json b/.eslintrc.json index 4fe0891..bb16bed 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,6 +2,15 @@ "extends": "@antfu", "rules": { "jsonc/sort-keys": "off", - "eol-last": "off" + "eol-last": "off", + // "cases" allows for graceful use of that variable + // in type testing + "@typescript-eslint/no-unused-vars": [ + "error", + { + "varsIgnorePattern": "cases|^_", + "argsIgnorePattern": "^_" + } + ] } } \ No newline at end of file diff --git a/example/vite.config.ts b/example/vite.config.ts index b200df9..75edfa3 100644 --- a/example/vite.config.ts +++ b/example/vite.config.ts @@ -5,9 +5,9 @@ import Components from 'unplugin-vue-components/vite' import Inspect from 'vite-plugin-inspect' import Layouts from 'vite-plugin-vue-layouts' import Markdown from 'vite-plugin-md' -import code from '@yankeeinlondon/code-builder' -import link from '@yankeeinlondon/link-builder' -import meta from '@yankeeinlondon/meta-builder' +// import code from '@yankeeinlondon/code-builder' +// import link from '@yankeeinlondon/link-builder' +// import meta from '@yankeeinlondon/meta-builder' import Pages from 'vite-plugin-pages' import Unocss from 'unocss/vite' import Vue from '@vitejs/plugin-vue' @@ -60,11 +60,11 @@ const config = defineConfig({ baseStyle: 'github', }, builders: [ - meta(), - link(), - code({ - theme: 'base', - }), + // meta(), + // link(), + // code({ + // theme: 'base', + // }), ], }), diff --git a/package.json b/package.json index 2f14ac2..808b1b9 100644 --- a/package.json +++ b/package.json @@ -55,15 +55,15 @@ "test:component": "npx cypress open-ct -p 4000" }, "dependencies": { - "@yankeeinlondon/builder-api": "^1.2.2", + "@yankeeinlondon/builder-api": "^1.3.4", "@yankeeinlondon/gray-matter": "^6.1.1", "@yankeeinlondon/happy-wrapper": "^2.10.1", "markdown-it": "^13.0.1", "source-map-js": "^1.0.2" }, "peerDependencies": { - "vite": "^4.0.0 || ^3.0.0", - "@vitejs/plugin-vue": ">=2.3.4" + "@vitejs/plugin-vue": ">=2.3.4", + "vite": "^4.0.0 || ^3.0.0" }, "devDependencies": { "@antfu/eslint-config": "^0.34.0", @@ -78,7 +78,7 @@ "@vitest/coverage-c8": "^0.25.8", "@vitest/ui": "^0.25.8", "@vue/test-utils": "^2.2.6", - "@vueuse/core": "^9.6.0", + "@vueuse/core": "^9.7.0", "@yankeeinlondon/code-builder": "^1.2.1", "@yankeeinlondon/link-builder": "^1.2.1", "@yankeeinlondon/meta-builder": "^1.2.1", @@ -89,6 +89,7 @@ "eslint-config-prettier": "^8.5.0", "fp-ts": "^2.13.1", "happy-dom": "^8.1.0", + "native-dash": "^1.25.0", "npm-run-all": "^4.1.5", "pathe": "^1.0.0", "rollup": "^3.7.4", @@ -99,4 +100,4 @@ "vue": "^3.2.45", "vue-router": "^4.1.6" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00ea669..81dc35f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,8 +16,8 @@ importers: '@vitest/coverage-c8': ^0.25.8 '@vitest/ui': ^0.25.8 '@vue/test-utils': ^2.2.6 - '@vueuse/core': ^9.6.0 - '@yankeeinlondon/builder-api': ^1.2.2 + '@vueuse/core': ^9.7.0 + '@yankeeinlondon/builder-api': ^1.3.4 '@yankeeinlondon/code-builder': ^1.2.1 '@yankeeinlondon/gray-matter': ^6.1.1 '@yankeeinlondon/happy-wrapper': ^2.10.1 @@ -31,6 +31,7 @@ importers: fp-ts: ^2.13.1 happy-dom: ^8.1.0 markdown-it: ^13.0.1 + native-dash: ^1.25.0 npm-run-all: ^4.1.5 pathe: ^1.0.0 rollup: ^3.7.4 @@ -42,7 +43,7 @@ importers: vue: ^3.2.45 vue-router: ^4.1.6 dependencies: - '@yankeeinlondon/builder-api': 1.2.2_jpq67ecuqssjycqwb362ku3jlm + '@yankeeinlondon/builder-api': 1.3.4_jpq67ecuqssjycqwb362ku3jlm '@yankeeinlondon/gray-matter': 6.1.1_jpq67ecuqssjycqwb362ku3jlm '@yankeeinlondon/happy-wrapper': 2.10.1_@vitest+ui@0.25.8 markdown-it: 13.0.1 @@ -60,7 +61,7 @@ importers: '@vitest/coverage-c8': 0.25.8_jpq67ecuqssjycqwb362ku3jlm '@vitest/ui': 0.25.8 '@vue/test-utils': 2.2.6_vue@3.2.45 - '@vueuse/core': 9.6.0_vue@3.2.45 + '@vueuse/core': 9.7.0_vue@3.2.45 '@yankeeinlondon/code-builder': 1.2.1_tiat3p6jseq43duslkothyjwyu '@yankeeinlondon/link-builder': 1.2.1_jpq67ecuqssjycqwb362ku3jlm '@yankeeinlondon/meta-builder': 1.2.1_jpq67ecuqssjycqwb362ku3jlm @@ -71,6 +72,7 @@ importers: eslint-config-prettier: 8.5.0_eslint@8.29.0 fp-ts: 2.13.1 happy-dom: 8.1.0 + native-dash: 1.25.0_jpq67ecuqssjycqwb362ku3jlm npm-run-all: 4.1.5 pathe: 1.0.0 rollup: 3.7.4 @@ -546,8 +548,8 @@ packages: resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} dev: true - /@iconify/utils/2.0.3: - resolution: {integrity: sha512-kLpJ95/ZeT1+vIstjdeFnyfiEmmTJuekGb5SVykfKjLSJjmftTCzm7sxxzNHsd8i5mpKPl7Rws9sLGR3juKJ+g==} + /@iconify/utils/2.0.4: + resolution: {integrity: sha512-/ZYdSK+vao8XPoRPkdQeetGBtuCcPcVTtuXUz2Y+281EpcmM/5G1SCbtgty28r/Y9HkR9ePbKst7eWUOK7/jNQ==} dependencies: '@antfu/install-pkg': 0.1.1 '@antfu/utils': 0.5.2 @@ -983,7 +985,7 @@ packages: /@unocss/preset-icons/0.47.6: resolution: {integrity: sha512-YvANR5ueN+r1E4YOfqF1llyUzS6yxROrJ+7MGNdIfyNHFcTwdHRy0f6y8uyiMYWyLc6nGGrUjjdo+DEc30obSA==} dependencies: - '@iconify/utils': 2.0.3 + '@iconify/utils': 2.0.4 '@unocss/core': 0.47.6 ohmyfetch: 0.4.21 transitivePeerDependencies: @@ -1269,6 +1271,18 @@ packages: - '@vue/composition-api' - vue + /@vueuse/core/9.7.0_vue@3.2.45: + resolution: {integrity: sha512-/AGY/t7jJPxCyRoVTygNKoroTiCvRaaZIW+yeSlBCnI7QRpQ9cvXNTdNaSl3GvSyFbn83+XwZwEZvI1OpQfeGw==} + dependencies: + '@types/web-bluetooth': 0.0.16 + '@vueuse/metadata': 9.7.0 + '@vueuse/shared': 9.7.0_vue@3.2.45 + vue-demi: 0.13.11_vue@3.2.45 + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + /@vueuse/head/1.0.22_vue@3.2.45: resolution: {integrity: sha512-YmUdbzNdCnhmrAFxGnJS+Rixj+swE+TQC9OEaYDHIro6gE7W11jugcdwVP00HrA4WRQhg+TOQ4YcY2oL/PP1hw==} peerDependencies: @@ -1283,6 +1297,10 @@ packages: /@vueuse/metadata/9.6.0: resolution: {integrity: sha512-sIC8R+kWkIdpi5X2z2Gk8TRYzmczDwHRhEFfCu2P+XW2JdPoXrziqsGpDDsN7ykBx4ilwieS7JUIweVGhvZ93w==} + /@vueuse/metadata/9.7.0: + resolution: {integrity: sha512-M7WsAgw28FNtTH0bzsGuHEtJOPJqPpyeHS6PHq+8UesLgNjZ9waMAntiUrgUQlxt09M4i2lH7y9sRi0jkfeXGA==} + dev: true + /@vueuse/shared/9.6.0_vue@3.2.45: resolution: {integrity: sha512-/eDchxYYhkHnFyrb00t90UfjCx94kRHxc7J1GtBCqCG4HyPMX+krV9XJgVtWIsAMaxKVU4fC8NSUviG1JkwhUQ==} dependencies: @@ -1291,6 +1309,15 @@ packages: - '@vue/composition-api' - vue + /@vueuse/shared/9.7.0_vue@3.2.45: + resolution: {integrity: sha512-pwmt1y3TJ2s5KqWmkv9ZKEV59GwuZQZk8XLiU+hGswz0jej318ozbea9E4A/A50ksyM26swSFr7sZ9llNPsZHg==} + dependencies: + vue-demi: 0.13.11_vue@3.2.45 + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + /@yankeeinlondon/builder-api/1.2.2: resolution: {integrity: sha512-EDeZbbHdRjm0rqXJhdqeRrSdeo9qza/iPVA31k2jJrRc3sil4gzd1tiMN3qANLetg04x8M+tlfvH0S51a4z5rA==} dependencies: @@ -1314,8 +1341,8 @@ packages: - terser dev: true - /@yankeeinlondon/builder-api/1.2.2_jpq67ecuqssjycqwb362ku3jlm: - resolution: {integrity: sha512-EDeZbbHdRjm0rqXJhdqeRrSdeo9qza/iPVA31k2jJrRc3sil4gzd1tiMN3qANLetg04x8M+tlfvH0S51a4z5rA==} + /@yankeeinlondon/builder-api/1.3.4_jpq67ecuqssjycqwb362ku3jlm: + resolution: {integrity: sha512-zzYetYzAIQSgt4j8TDpGZD3OSvzx6Uz7LbOwZG6wgqvquzHrfUG7tLvexAC5MhtzUmxLLyprxHuIuUpZxio2/A==} dependencies: '@types/markdown-it': 12.2.3 '@yankeeinlondon/happy-wrapper': 2.10.1_@vitest+ui@0.25.8 @@ -1340,7 +1367,7 @@ packages: resolution: {integrity: sha512-UazmH2O74OwEhtSTsAJaOLR7tg1/yO41MLLbo31qF1FZdoHYXVTitYt4jjiE41jTnZ4348b8tY8ZL/qQtgm4cg==} dependencies: '@types/markdown-it': 12.2.3 - '@yankeeinlondon/builder-api': 1.2.2_jpq67ecuqssjycqwb362ku3jlm + '@yankeeinlondon/builder-api': 1.3.4_jpq67ecuqssjycqwb362ku3jlm '@yankeeinlondon/happy-wrapper': 2.10.1_@vitest+ui@0.25.8 inferred-types: 0.37.6_jpq67ecuqssjycqwb362ku3jlm markdown-it: 13.0.1 @@ -1480,7 +1507,7 @@ packages: /@yankeeinlondon/link-builder/1.2.1_jpq67ecuqssjycqwb362ku3jlm: resolution: {integrity: sha512-ohQQ42CE/LaUpPLoWy6KQ+55wVpPIQYh2fWvcnFSLHPsRsCHBP0Taf7fXbBTEnQvlOrX0ot+GOAKu5J2p7YC6g==} dependencies: - '@yankeeinlondon/builder-api': 1.2.2_jpq67ecuqssjycqwb362ku3jlm + '@yankeeinlondon/builder-api': 1.3.4_jpq67ecuqssjycqwb362ku3jlm '@yankeeinlondon/happy-wrapper': 2.10.1_@vitest+ui@0.25.8 transitivePeerDependencies: - '@edge-runtime/vm' @@ -1520,7 +1547,7 @@ packages: /@yankeeinlondon/meta-builder/1.2.1_jpq67ecuqssjycqwb362ku3jlm: resolution: {integrity: sha512-RVXCrO6hVPwETq2K345EmHuqyUG4OWo+PCw+he6CXjEJThJJwwaqvccfJbPEmjUAdTGdxtYTzRchI9oiyNnTAw==} dependencies: - '@yankeeinlondon/builder-api': 1.2.2_jpq67ecuqssjycqwb362ku3jlm + '@yankeeinlondon/builder-api': 1.3.4_jpq67ecuqssjycqwb362ku3jlm inferred-types: 0.37.6_jpq67ecuqssjycqwb362ku3jlm transitivePeerDependencies: - '@edge-runtime/vm' diff --git a/src/composeSfcBlocks.ts b/src/composeSfcBlocks.ts index a458dd6..e6c8554 100644 --- a/src/composeSfcBlocks.ts +++ b/src/composeSfcBlocks.ts @@ -1,8 +1,9 @@ import { flow, pipe } from 'fp-ts/lib/function.js' import { isRight } from 'fp-ts/lib/Either.js' + import { resolveOptions } from './options' -import { PipelineStage } from './types' import type { + GenericBuilder, Options, Pipeline, ViteConfigPassthrough, @@ -18,13 +19,11 @@ import { finalize, frontmatterPreprocess, gatherBuilderEvents, - injectUtilityFunctions, loadMarkdownItPlugins, parseHtml, repairFrontmatterLinks, sourcemap, transformsBefore, - usesBuilder, wrapHtml, } from './pipeline' import { lift } from './utils' @@ -35,14 +34,21 @@ import { kebabCaseComponents } from './pipeline/kebabCaseComponents' * Composes the `template` and `script` blocks, along with any other `customBlocks` from * the raw markdown content along with user options. */ -export async function composeSfcBlocks( +export async function composeSfcBlocks< + B extends readonly GenericBuilder[] = [], +>( id: string, raw: string, - opts: Omit = {}, + opts: Options = {} as Options, config: Partial = {}, ) { const options = resolveOptions(opts) - const p0 = { + + /** + * The initial pipeline state + */ + const payload: Pipeline<'initialize', B> = { + stage: 'initialize', fileName: id, content: raw.trimStart(), head: {}, @@ -58,50 +64,40 @@ export async function composeSfcBlocks( options, } - /** - * The initial pipeline state - */ - const payload: Pipeline = { - ...p0, - usesBuilder: usesBuilder(p0 as unknown as Pipeline, []), - } - const handlers = gatherBuilderEvents(options) /** initialize the configuration */ const initialize = flow( - lift('initialize'), - transformsBefore, - handlers(PipelineStage.initialize), - // addBuilderDependencies([]), + // lifted, + transformsBefore(), + handlers('initialize'), ) /** extract the meta-data from the MD content */ const metaExtracted = flow( - injectUtilityFunctions, - extractFrontmatter, - baseStyling, - frontmatterPreprocess, - handlers(PipelineStage.metaExtracted), + extractFrontmatter(), + baseStyling(), + frontmatterPreprocess(), + handlers('metaExtracted'), ) /** establish the MarkdownIt parser */ const parser = flow( - createParser, - loadMarkdownItPlugins, - applyMarkdownItOptions, - handlers(PipelineStage.parser), + createParser(), + loadMarkdownItPlugins(), + applyMarkdownItOptions(), + handlers('parser'), ) /** * use MarkdownIt to produce HTML */ const parsed = flow( - parseHtml, - kebabCaseComponents, - repairFrontmatterLinks, - wrapHtml, - handlers(PipelineStage.parsed), + parseHtml(), + kebabCaseComponents(), + repairFrontmatterLinks(), + wrapHtml(), + handlers('parsed'), ) /** @@ -109,14 +105,14 @@ export async function composeSfcBlocks( * easier to perform. */ const dom = flow( - convertToDom, - escapeCodeTagInterpolation, - handlers(PipelineStage.dom), + convertToDom(), + escapeCodeTagInterpolation(), + handlers('dom'), ) // construct the async pipeline const result = await pipe( - payload, + lift(payload), initialize, metaExtracted, @@ -124,12 +120,12 @@ export async function composeSfcBlocks( parsed, dom, - extractBlocks, - handlers(PipelineStage.sfcBlocksExtracted), + extractBlocks(), + handlers('sfcBlocksExtracted'), - finalize, - sourcemap, - handlers(PipelineStage.closeout), + finalize(), + sourcemap(), + handlers('closeout'), )() if (isRight(result)) diff --git a/src/createSfcComponent.ts b/src/createSfcComponent.ts index 7db679c..b346a7c 100644 --- a/src/createSfcComponent.ts +++ b/src/createSfcComponent.ts @@ -5,7 +5,7 @@ import type { ViteConfig } from '.' /** * Produces a _string_ which represents the parsed Markdown as a SFC component. */ -export const createSfcComponent = (options: Options = {}) => (config: ViteConfig) => { +export const createSfcComponent = >(options: Partial = {} as Partial) => (config: ViteConfig) => { // callback called for each Markdown file return async (id: string, raw: string) => { const pipeline = await composeSfcBlocks(id, raw, options, config) diff --git a/src/index.ts b/src/index.ts index d5b95b2..ffd2d89 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,7 @@ export type ViteConfig = Readonly -function VitePluginMarkdown(userOptions: Options = {}) { +function VitePluginMarkdown>(userOptions: O = {} as O) { const options = resolveOptions(userOptions) const markdownToVue = createSfcComponent(options) let config: ViteConfig diff --git a/src/options.ts b/src/options.ts index e954d83..bc1d3d6 100644 --- a/src/options.ts +++ b/src/options.ts @@ -1,9 +1,12 @@ import { toArray } from '@antfu/utils' +import type { BuilderOptions, ConfiguredBuilder } from '@yankeeinlondon/builder-api' import { preprocessHead } from './head' -import type { Frontmatter, Options, ResolvedOptions } from './types' +import type { Frontmatter, PipelineStage, Options, ResolvedOptions } from './types' import { getVueVersion } from './utils' -export function resolveOptions(userOptions: Omit = {}): ResolvedOptions { +export function resolveOptions< + B extends readonly ConfiguredBuilder[], +>(userOptions: Partial> = {} as Partial>): ResolvedOptions { const defaultOptions: Omit = { style: { baseStyle: 'none', @@ -48,7 +51,7 @@ export function resolveOptions(userOptions: Omit = {}): ...userOptions.style, }, usingBuilder: (name: string) => { - return !options.builders.every(b => b.name !== name) + return !options.builders.every(b => b.about.name !== name) }, frontmatterPreprocess: (frontmatter: Frontmatter, options: ResolvedOptions) => { if (!options.usingBuilder('link')) { @@ -64,5 +67,5 @@ export function resolveOptions(userOptions: Omit = {}): .filter((i?: string) => i) .join(' ') - return options as ResolvedOptions + return options as ResolvedOptions } diff --git a/src/pipeline/applyMarkdownItOptions.ts b/src/pipeline/applyMarkdownItOptions.ts index bf24b82..ffd79c5 100644 --- a/src/pipeline/applyMarkdownItOptions.ts +++ b/src/pipeline/applyMarkdownItOptions.ts @@ -1,3 +1,4 @@ +import type { GenericBuilder } from '../types/core' import { transformer } from '../utils' /** @@ -5,7 +6,7 @@ import { transformer } from '../utils' * the parser will be passed into this callback function so that the * parser may be configured. */ -export const applyMarkdownItOptions = transformer('applyMarkdownItOptions', 'parser', 'parser', (payload) => { +export const applyMarkdownItOptions = () => transformer()('parser', (payload) => { payload.options.markdownItSetup(payload.parser) return payload }) diff --git a/src/pipeline/baseStyling.ts b/src/pipeline/baseStyling.ts index 6bd6379..67002d2 100644 --- a/src/pipeline/baseStyling.ts +++ b/src/pipeline/baseStyling.ts @@ -1,10 +1,11 @@ import { createInlineStyle } from '@yankeeinlondon/happy-wrapper' +import type { GenericBuilder } from '../types/core' import { transformer } from '../utils' /** * Call's the transformer function provided in `options.before` */ -export const baseStyling = (transformer('baseStyling', 'metaExtracted', 'metaExtracted', (p) => { +export const baseStyling = () => transformer()('metaExtracted', (p) => { if (p.options.style.baseStyle === 'github') { const style = createInlineStyle() .addCssVariable('md-text-color', '#111827') @@ -50,4 +51,4 @@ export const baseStyling = (transformer('baseStyling', 'metaExtracted', 'metaExt } return p -})) +}) diff --git a/src/pipeline/convertHandlerToTask.ts b/src/pipeline/convertHandlerToTask.ts index 41da2a3..a02c134 100644 --- a/src/pipeline/convertHandlerToTask.ts +++ b/src/pipeline/convertHandlerToTask.ts @@ -1,23 +1,24 @@ -import type { BuilderOptions, BuilderRegistration } from '@yankeeinlondon/builder-api' +import type { BuilderOptions, BuilderRegistration, ConfiguredBuilder } from '@yankeeinlondon/builder-api' import { pipe } from 'fp-ts/lib/function.js' import * as TE from 'fp-ts/lib/TaskEither.js' -import type { IPipelineStage, PipeTask, Pipeline, ResolvedOptions } from '../types' +import type { PipelineStage, PipeTask, Pipeline, ResolvedOptions } from '../types' /** * Gets all builders associated with a particular pipeline stage */ const getBuilders = < - S extends IPipelineStage, + S extends PipelineStage, + B extends readonly ConfiguredBuilder[], >( stage: S, - options: ResolvedOptions, + options: ResolvedOptions, ) => { const builders = options.builders.reduce( (acc, b) => { - return b.lifecycle === stage ? [...acc, b as BuilderRegistration] : acc + return b.about.stage === stage ? [...acc, b() as BuilderRegistration] : acc }, - [] as readonly BuilderRegistration[], + [] as BuilderRegistration[], ) return builders } @@ -33,26 +34,28 @@ const getBuilders = < * = transformForBuilders(stage) * ``` */ -export const getBuilderTask = ( - stage: S, - options: ResolvedOptions, -) => (payload: Pipeline): PipeTask => { +export const getBuilderTask = < + S extends PipelineStage, + B extends readonly ConfiguredBuilder[], +>( + stage: S, + options: ResolvedOptions, + ) => (payload: Pipeline) => { const builders = getBuilders(stage, options) if (builders.length === 0) { // if no builders then just return payload as-is return TE.right(payload) } - const asyncApi = async (payload: Pipeline) => { + const asyncApi = async (payload: Pipeline): Promise> => { for (const b of builders) { try { - payload = await b.handler(payload as any, b.options) as Pipeline + payload = await b.handler(payload as any, b.options) } catch (e) { throw new Error(`During the "${stage}" stage, the builder API "${b.name}" was unable to transform the payload. It received the following error message: ${e instanceof Error ? e.message : String(e)}`) } } - return payload } @@ -70,20 +73,22 @@ export const getBuilderTask = ( * - an asynchronous `TaskEither` * - in _both_ cases the return type will be a `TaskEither` */ -export const gatherBuilderEvents = (options: ResolvedOptions) => +export const gatherBuilderEvents = < + B extends readonly ConfiguredBuilder[], +>(options: ResolvedOptions) => /** * Providing the _stage_ allows isolating only those events * which should be executed at this point in time and */ - (stage: S) => { - const task = (payload: PipeTask): PipeTask => { + (stage: S) => { + const task = (payload: PipeTask): PipeTask => { const bt = getBuilderTask(stage, options) return pipe( payload, TE.map(bt), TE.flatten, - ) as PipeTask + ) as PipeTask } return task } diff --git a/src/pipeline/convertToDom.ts b/src/pipeline/convertToDom.ts index d5c8858..48c245a 100644 --- a/src/pipeline/convertToDom.ts +++ b/src/pipeline/convertToDom.ts @@ -1,9 +1,11 @@ import { createFragment } from '@yankeeinlondon/happy-wrapper' +import type { GenericBuilder } from '../types/core' import { transformer } from '../utils' -export const convertToDom = transformer('convertToDom', 'parsed', 'dom', (payload) => { +export const convertToDom = () => transformer()('parsed', (payload) => { return { ...payload, + stage: 'dom', html: createFragment(payload.html), fencedLanguages: new Set(), } diff --git a/src/pipeline/createParser.ts b/src/pipeline/createParser.ts index b848a17..f126f3d 100644 --- a/src/pipeline/createParser.ts +++ b/src/pipeline/createParser.ts @@ -1,10 +1,11 @@ import MarkdownIt from 'markdown-it' +import type { GenericBuilder } from '../types/core' import { transformer } from '../utils' /** * Creates a **MarkdownIt** parser instance which this plugin will use for all processing. */ -export const createParser = transformer('createParser', 'metaExtracted', 'parser', (payload) => { +export const createParser = () => transformer()('metaExtracted', (payload) => { const parser = new MarkdownIt({ html: true, linkify: true, @@ -14,5 +15,5 @@ export const createParser = transformer('createParser', 'metaExtracted', 'parser parser.linkify.set({ fuzzyLink: false }) - return { ...payload, parser } + return { ...payload, parser, stage: 'parser' } }) diff --git a/src/pipeline/escapeCodeTagInterpolation.ts b/src/pipeline/escapeCodeTagInterpolation.ts index 91a8de4..58eeaa0 100644 --- a/src/pipeline/escapeCodeTagInterpolation.ts +++ b/src/pipeline/escapeCodeTagInterpolation.ts @@ -1,4 +1,5 @@ import { getClassList, select, setAttribute } from '@yankeeinlondon/happy-wrapper' +import type { GenericBuilder } from '../types/core' import { transformer } from '../utils' /** @@ -10,9 +11,8 @@ import { transformer } from '../utils' * the payload being passed through as this could be valuable for _search_ * or other meta features. */ -export const escapeCodeTagInterpolation = transformer( - 'escapeCodeTagInterpolation', - 'dom', 'dom', +export const escapeCodeTagInterpolation = () => transformer()( + 'dom', (payload) => { const { options: { escapeCodeTagInterpolation, usingBuilder }, html: dom } = payload const addVPre = setAttribute('v-pre')('true') diff --git a/src/pipeline/extractBlocks.ts b/src/pipeline/extractBlocks.ts index 210b52a..a5f5ae5 100644 --- a/src/pipeline/extractBlocks.ts +++ b/src/pipeline/extractBlocks.ts @@ -3,8 +3,8 @@ import type { IElement } from '@yankeeinlondon/happy-wrapper' import { pipe } from 'fp-ts/lib/function.js' import { isVue2, transformer, wrap } from '../utils' import type { + GenericBuilder, Pipeline, - PipelineStage, ResolvedOptions, } from '../types' @@ -46,7 +46,9 @@ const createVue2ScriptBlock = (codeBlocks: Record) { +function extractScriptBlocks< + P extends Pipeline<'dom', any>, +>(p: P) { const scripts: IElement[] = [] const extractor = extract(scripts) const html = select(p.html) @@ -73,7 +75,10 @@ function extractScriptBlocks(p: Pipeline) { * for this plugin. This call also mutates the `html` property to extract these custom * blocks. */ -function extractCustomBlocks(p: Pipeline, options: ResolvedOptions) { +function extractCustomBlocks< + B extends readonly GenericBuilder[], + P extends Pipeline<'dom', B>, +>(p: P, options: ResolvedOptions) { const styleBlocks = [ ...select(p.html).findAll('style'), ...elementHashToArray(p.vueStyleBlocks), @@ -94,7 +99,9 @@ function extractCustomBlocks(p: Pipeline, options: ResolvedOp } /** produces the defineExpose() call based on config */ -function expose(p: Pipeline<'dom'>) { +function expose< + P extends Pipeline<'dom', any>, +>(p: P) { const fm = p.frontmatter delete fm.excerpt @@ -112,104 +119,107 @@ function expose(p: Pipeline<'dom'>) { /** * Separates the various "blocks" in an SFC component */ -export const extractBlocks = transformer('extractBlocks', 'dom', 'sfcBlocksExtracted', (payload) => { +export const extractBlocks = () => transformer()( + 'dom', + (payload) => { // eslint-disable-next-line prefer-const - let { options, frontmatter, head } = payload + let { options, frontmatter, head } = payload - const { scriptSetups, traditionalScripts } = extractScriptBlocks(payload) - const { styleBlocks, customBlocks } = extractCustomBlocks(payload, options) + const { scriptSetups, traditionalScripts } = extractScriptBlocks(payload) + const { styleBlocks, customBlocks } = extractCustomBlocks(payload, options) - /** template blocks that will be applied below */ - const template = { + /** template blocks that will be applied below */ + const template = { /** adds the lines needed to include useHead() */ - useHead: head && options.headEnabled - ? `import { useHead } from "@vueuse/head"\n const head = ${JSON.stringify(head)}\n useHead(head)` - : '', - importDefineExpose: options.frontmatter ? 'import { defineExpose } from \'vue\'' : '', - /** exports the excerpt in a `