summaryrefslogtreecommitdiff
path: root/packages/markdown-support/src/index.ts
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@matthewphillips.info> 2021-06-04 14:19:01 -0400
committerGravatar GitHub <noreply@github.com> 2021-06-04 14:19:01 -0400
commit50e6f491ad2258689ba8735a3f98a0d99e4ba336 (patch)
treecc2c1284b3632d6447d3c9bab3b5c1aa461c35cf /packages/markdown-support/src/index.ts
parenta2594ef572c41ce05dd01ef095e8595ffcd35842 (diff)
downloadastro-50e6f491ad2258689ba8735a3f98a0d99e4ba336.tar.gz
astro-50e6f491ad2258689ba8735a3f98a0d99e4ba336.tar.zst
astro-50e6f491ad2258689ba8735a3f98a0d99e4ba336.zip
Use npm package names to load internal deps (#294)
* Use npm package names to load internal deps This is necessary so that published Astro components work. These components will be built by esinstall and therefore they cannot rely on `_astro_internal`. The fix is to use npm specifiers everywhere. * Move most of frontend to internal * Mark astro/internal/markdown.js as external * Move markdown stuff to its own package This moves the markdown stuff to its own package so that we can externalize it in the markdown component. * Add the changeset
Diffstat (limited to 'packages/markdown-support/src/index.ts')
-rw-r--r--packages/markdown-support/src/index.ts69
1 files changed, 69 insertions, 0 deletions
diff --git a/packages/markdown-support/src/index.ts b/packages/markdown-support/src/index.ts
new file mode 100644
index 000000000..4db3089ba
--- /dev/null
+++ b/packages/markdown-support/src/index.ts
@@ -0,0 +1,69 @@
+import type { AstroMarkdownOptions } from './types';
+
+import createCollectHeaders from './rehype-collect-headers.js';
+import scopedStyles from './remark-scoped-styles.js';
+import { remarkCodeBlock, rehypeCodeBlock } from './codeblock.js';
+import raw from 'rehype-raw';
+
+import unified from 'unified';
+import markdown from 'remark-parse';
+import markdownToHtml from 'remark-rehype';
+// import smartypants from '@silvenon/remark-smartypants';
+import rehypeStringify from 'rehype-stringify';
+
+export interface MarkdownRenderingOptions extends Partial<AstroMarkdownOptions> {
+ $?: {
+ scopedClassName: string | null;
+ };
+ mode: 'md' | 'astro-md';
+}
+
+/** Internal utility for rendering a full markdown file and extracting Frontmatter data */
+export async function renderMarkdownWithFrontmatter(contents: string, opts?: MarkdownRenderingOptions | null) {
+ // Dynamic import to ensure that "gray-matter" isn't built by Snowpack
+ const { default: matter } = await import('gray-matter');
+ const { data: frontmatter, content } = matter(contents);
+ const value = await renderMarkdown(content, { ...opts, mode: 'md' });
+ return { ...value, frontmatter };
+}
+
+/** Shared utility for rendering markdown */
+export async function renderMarkdown(content: string, opts?: MarkdownRenderingOptions | null) {
+ const { $: { scopedClassName = null } = {}, mode = 'astro-md', footnotes: useFootnotes = true, gfm: useGfm = true } = opts ?? {};
+ const { headers, rehypeCollectHeaders } = createCollectHeaders();
+
+ let parser = unified().use(markdown).use(remarkCodeBlock());
+
+ if (scopedClassName) {
+ parser = parser.use(scopedStyles(scopedClassName));
+ }
+
+ if (useGfm) {
+ const { default: gfm } = await import('remark-gfm');
+ parser = parser.use(gfm);
+ }
+
+ if (useFootnotes) {
+ const { default: footnotes } = await import('remark-footnotes');
+ parser = parser.use(footnotes);
+ }
+
+ let result: string;
+ try {
+ const vfile = await parser
+ .use(markdownToHtml, { allowDangerousHtml: true, passThrough: ['raw'] })
+ .use(raw)
+ .use(rehypeCollectHeaders)
+ .use(rehypeCodeBlock())
+ .use(rehypeStringify)
+ .process(content);
+ result = vfile.contents.toString();
+ } catch (err) {
+ throw err;
+ }
+
+ return {
+ astro: { headers, source: content },
+ content: result.toString(),
+ };
+} \ No newline at end of file