summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@matthewphillips.info> 2021-03-23 15:20:03 -0400
committerGravatar GitHub <noreply@github.com> 2021-03-23 15:20:03 -0400
commited85702581cad3f00729f920036560da439e1189 (patch)
tree96da9ef8e21d2dfaebc3c1c10120c0ffc6da802a /src
parente0353d50e77039bdf73d178a1d09dcd1aa0f59d0 (diff)
downloadastro-ed85702581cad3f00729f920036560da439e1189.tar.gz
astro-ed85702581cad3f00729f920036560da439e1189.tar.zst
astro-ed85702581cad3f00729f920036560da439e1189.zip
Allow HMX components in markdown (#19)
* Allow HMX components in markdown This adds support for HMX components in markdown. The mechanism for importing is via frontmatter. We could do this differently (setup script maybe?) but since this was the easiest to implement I thought it was a good first-pass option. * Remove node-fetch from snowpack config * Assert that the runtime is created successfully * Add back in the micromark extension for encoding entities * Encode both codeTextData and codeFlowValue * Install snowpack app's deps
Diffstat (limited to 'src')
-rw-r--r--src/dev.ts7
-rw-r--r--src/micromark-encode.ts35
-rw-r--r--src/transform2.ts29
3 files changed, 61 insertions, 10 deletions
diff --git a/src/dev.ts b/src/dev.ts
index 93a890057..c6ad9ff7c 100644
--- a/src/dev.ts
+++ b/src/dev.ts
@@ -57,6 +57,8 @@ export default async function (astroConfig: AstroConfig) {
break;
}
}
+ res.statusCode = 500;
+ res.end(formatErrorForBrowser(result.error));
break;
}
}
@@ -66,3 +68,8 @@ export default async function (astroConfig: AstroConfig) {
console.log(`Server running at http://${hostname}:${port}/`);
});
}
+
+function formatErrorForBrowser(error: Error) {
+ // TODO make this pretty.
+ return error.toString();
+} \ No newline at end of file
diff --git a/src/micromark-encode.ts b/src/micromark-encode.ts
new file mode 100644
index 000000000..d205d13e3
--- /dev/null
+++ b/src/micromark-encode.ts
@@ -0,0 +1,35 @@
+import type { HtmlExtension, Token, Tokenize } from 'micromark/dist/shared-types';
+
+const characterReferences = {
+ '"': 'quot',
+ '&': 'amp',
+ '<': 'lt',
+ '>': 'gt',
+ '{': 'lbrace',
+ '}': 'rbrace',
+};
+
+type EncodedChars = '"' | '&' | '<' | '>' | '{' | '}';
+
+function encode(value: string): string {
+ return value.replace(/["&<>{}]/g, (raw: string) => {
+ return '&' + characterReferences[raw as EncodedChars] + ';';
+ });
+}
+
+function encodeToken(this: Record<string, () => void>) {
+ const token: Token = arguments[0];
+ const serialize = (this.sliceSerialize as unknown) as (t: Token) => string;
+ const raw = (this.raw as unknown) as (s: string) => void;
+ const value = serialize(token);
+ raw(encode(value));
+}
+
+const plugin: HtmlExtension = {
+ exit: {
+ codeTextData: encodeToken,
+ codeFlowValue: encodeToken,
+ },
+};
+
+export { plugin as encodeMarkdown }; \ No newline at end of file
diff --git a/src/transform2.ts b/src/transform2.ts
index 2f1e651cf..42a151b3c 100644
--- a/src/transform2.ts
+++ b/src/transform2.ts
@@ -8,6 +8,7 @@ import gfmHtml from 'micromark-extension-gfm/html.js';
import { CompileResult, TransformResult } from './@types/astro';
import { parse } from './compiler/index.js';
import { createMarkdownHeadersCollector } from './micromark-collect-headers.js';
+import { encodeMarkdown } from './micromark-encode.js';
import { defaultLogOptions } from './logger.js';
import { optimize } from './optimize/index.js';
import { codegen } from './codegen/index.js';
@@ -54,8 +55,9 @@ async function convertMdToJsx(
const { data: _frontmatterData, content } = matter(contents);
const { headers, headersExtension } = createMarkdownHeadersCollector();
const mdHtml = micromark(content, {
+ allowDangerousHtml: true,
extensions: [gfmSyntax()],
- htmlExtensions: [gfmHtml, headersExtension],
+ htmlExtensions: [gfmHtml, encodeMarkdown, headersExtension],
});
const setupContext = {
@@ -68,19 +70,26 @@ async function convertMdToJsx(
},
};
+ let imports = '';
+ for(let [ComponentName, specifier] of Object.entries(_frontmatterData.import || {})) {
+ imports += `import ${ComponentName} from '${specifier}';\n`;
+ }
+
// </script> can't be anywhere inside of a JS string, otherwise the HTML parser fails.
// Break it up here so that the HTML parser won't detect it.
const stringifiedSetupContext = JSON.stringify(setupContext).replace(/\<\/script\>/g, `</scrip" + "t>`);
- return convertHmxToJsx(
- `<script astro>
- ${_frontmatterData.layout ? `export const layout = ${JSON.stringify(_frontmatterData.layout)};` : ''}
- export function setup({context}) {
- return {context: ${stringifiedSetupContext} };
- }
- </script><section>{${JSON.stringify(mdHtml)}}</section>`,
- { compileOptions, filename, fileID }
- );
+ const raw = `<script astro>
+ ${imports}
+ ${_frontmatterData.layout ? `export const layout = ${JSON.stringify(_frontmatterData.layout)};` : ''}
+ export function setup({context}) {
+ return {context: ${stringifiedSetupContext} };
+ }
+</script><section>${mdHtml}</section>`;
+
+ const convertOptions = { compileOptions, filename, fileID };
+
+ return convertHmxToJsx(raw, convertOptions);
}
async function transformFromSource(