diff options
author | 2023-07-24 19:34:06 -0400 | |
---|---|---|
committer | 2023-07-24 19:34:06 -0400 | |
commit | 7461e82c81438df956861197536f9ceeaf63d6b3 (patch) | |
tree | 5d5318b0f8fd61eba466cbccb00c8e5035914b57 /packages/integrations/markdoc/src/runtime.ts | |
parent | 81c460e30b3318b9727a609390243f42e112ad24 (diff) | |
download | astro-7461e82c81438df956861197536f9ceeaf63d6b3.tar.gz astro-7461e82c81438df956861197536f9ceeaf63d6b3.tar.zst astro-7461e82c81438df956861197536f9ceeaf63d6b3.zip |
Add "allowHTML" option for Markdoc with HTML parsing/processing (#7597)
* 7576 - initial support for HTML inside Markdoc.
This uses htmlparser2 to perform a pure token transform/mutation
on the markdown-it tokens, replacing the original raw HTML string
tokens with a richer set of tokens per HTML node, and in the process
Markdoc tags are interleaved in the resulting token graph at the
appropriate locations
This removes the legacy config of the @astrojs/markdoc integration
entirely (suggested by @bholmesdev) and introduces a new type for
options to be specified in the astro config, initially, with just the new
"enableHTML" option
When "enableHTML" is *not* enabled (the default), the behavior
of the entire @astrojs/markdoc integration should remain functionally
equivalent to before this change
* 7576 - fixed issues with whitespace preservation
also:
* cleaned up " to ' for astro project preferred linting
* made the html rendering test fixture use a dynamic path
* 7576 - detailed nested HTML test coverage
* 7576 - component + HTML interleaved tests
* 7576 - fix lint problems from previous changes
* 7576 - some commentary
* 7576 - file naming, refactor html under imports, package.json exports definition for html
* 7576
* move out of extensions dir, remove export
* cdata handling changes
* 7576
* inline license from third party code
* cleanup test class copy of HTML output
* remove // third party indicators for imports (clarification: not third party code, just a indicator this group of imports is third party)
* 7576 - fixed test before/after for DRY'ness
* 7576 - no need to React-ify HTML attribute case
* 7576 - rename "enableHTML" option to "allowHTML"
* Added Markdoc allowHTML feature changeset
* 7576 - updated README with allowHTML info
* 7576 - fixed changeset typo
* 7576 - minor edits based on PR feedback for docs
* 7576 - minor edits based on PR feedback for docs
Diffstat (limited to 'packages/integrations/markdoc/src/runtime.ts')
-rw-r--r-- | packages/integrations/markdoc/src/runtime.ts | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/packages/integrations/markdoc/src/runtime.ts b/packages/integrations/markdoc/src/runtime.ts index 6a20a8740..4b93349b8 100644 --- a/packages/integrations/markdoc/src/runtime.ts +++ b/packages/integrations/markdoc/src/runtime.ts @@ -10,13 +10,15 @@ import type { AstroInstance } from 'astro'; import { createComponent, renderComponent } from 'astro/runtime/server/index.js'; import type { AstroMarkdocConfig } from './config.js'; import { setupHeadingConfig } from './heading-ids.js'; +import type { MarkdocIntegrationOptions } from './options.js'; +import { htmlTag } from './html/tagdefs/html.tag.js'; /** * Merge user config with default config and set up context (ex. heading ID slugger) * Called on each file's individual transform. * TODO: virtual module to merge configs per-build instead of per-file? */ -export async function setupConfig(userConfig: AstroMarkdocConfig = {}): Promise<MergedConfig> { +export async function setupConfig(userConfig: AstroMarkdocConfig = {}, options: MarkdocIntegrationOptions | undefined): Promise<MergedConfig> { let defaultConfig: AstroMarkdocConfig = setupHeadingConfig(); if (userConfig.extends) { @@ -29,14 +31,26 @@ export async function setupConfig(userConfig: AstroMarkdocConfig = {}): Promise< } } - return mergeConfig(defaultConfig, userConfig); + let merged = mergeConfig(defaultConfig, userConfig); + + if (options?.allowHTML) { + merged = mergeConfig(merged, HTML_CONFIG); + } + + return merged; } /** Used for synchronous `getHeadings()` function */ -export function setupConfigSync(userConfig: AstroMarkdocConfig = {}): MergedConfig { +export function setupConfigSync(userConfig: AstroMarkdocConfig = {}, options: MarkdocIntegrationOptions | undefined): MergedConfig { const defaultConfig: AstroMarkdocConfig = setupHeadingConfig(); - return mergeConfig(defaultConfig, userConfig); + let merged = mergeConfig(defaultConfig, userConfig); + + if (options?.allowHTML) { + merged = mergeConfig(merged, HTML_CONFIG); + } + + return merged; } type MergedConfig = Required<Omit<AstroMarkdocConfig, 'extends'>>; @@ -146,12 +160,12 @@ export function collectHeadings( } } -export function createGetHeadings(stringifiedAst: string, userConfig: AstroMarkdocConfig) { +export function createGetHeadings(stringifiedAst: string, userConfig: AstroMarkdocConfig, options: MarkdocIntegrationOptions | undefined) { return function getHeadings() { /* Yes, we are transforming twice (once from `getHeadings()` and again from <Content /> in case of variables). TODO: propose new `render()` API to allow Markdoc variable passing to `render()` itself, instead of the Content component. Would remove double-transform and unlock variable resolution in heading slugs. */ - const config = setupConfigSync(userConfig); + const config = setupConfigSync(userConfig, options); const ast = Markdoc.Ast.fromJSON(stringifiedAst); const content = Markdoc.transform(ast as Node, config as ConfigType); let collectedHeadings: MarkdownHeading[] = []; @@ -164,6 +178,7 @@ export function createContentComponent( Renderer: AstroInstance['default'], stringifiedAst: string, userConfig: AstroMarkdocConfig, + options: MarkdocIntegrationOptions | undefined, tagComponentMap: Record<string, AstroInstance['default']>, nodeComponentMap: Record<NodeType, AstroInstance['default']> ) { @@ -171,7 +186,7 @@ export function createContentComponent( async factory(result: any, props: Record<string, any>) { const withVariables = mergeConfig(userConfig, { variables: props }); const config = resolveComponentImports( - await setupConfig(withVariables), + await setupConfig(withVariables, options), tagComponentMap, nodeComponentMap ); @@ -181,3 +196,10 @@ export function createContentComponent( propagation: 'self', }); } + +// statically define a partial MarkdocConfig which registers the required "html-tag" Markdoc tag when the "allowHTML" feature is enabled +const HTML_CONFIG: AstroMarkdocConfig = { + tags: { + "html-tag": htmlTag, + }, +}; |