[ci] format
This commit is contained in:
parent
cfae9760b2
commit
cb039219ef
11 changed files with 134 additions and 115 deletions
|
@ -125,9 +125,15 @@ export default function markdown({ config }: AstroPluginOptions): Plugin {
|
|||
let { data: frontmatter, content: markdownContent } = matter(source);
|
||||
|
||||
// Turn HTML comments into JS comments
|
||||
markdownContent = markdownContent.replace(/<\s*!--([^-->]*)(.*?)-->/gs, (whole) => `{/*${whole}*/}`)
|
||||
markdownContent = markdownContent.replace(
|
||||
/<\s*!--([^-->]*)(.*?)-->/gs,
|
||||
(whole) => `{/*${whole}*/}`
|
||||
);
|
||||
|
||||
let renderResult = await renderMarkdown(markdownContent, { ...renderOpts, fileURL: fileUrl } as any);
|
||||
let renderResult = await renderMarkdown(markdownContent, {
|
||||
...renderOpts,
|
||||
fileURL: fileUrl,
|
||||
} as any);
|
||||
let { code: astroResult, metadata } = renderResult;
|
||||
const { layout = '', components = '', setup = '', ...content } = frontmatter;
|
||||
content.astro = metadata;
|
||||
|
|
|
@ -39,7 +39,7 @@ describe('Astro Markdown', () => {
|
|||
const html = await fixture.readFile('/slug/index.html');
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
expect($('h1').attr("id")).to.equal('my-blog-post');
|
||||
expect($('h1').attr('id')).to.equal('my-blog-post');
|
||||
});
|
||||
|
||||
it('Can handle code elements without extra spacing', async () => {
|
||||
|
@ -47,7 +47,7 @@ describe('Astro Markdown', () => {
|
|||
const $ = cheerio.load(html);
|
||||
|
||||
$('code').each((_, el) => {
|
||||
expect($(el).html()).to.equal($(el).html().trim())
|
||||
expect($(el).html()).to.equal($(el).html().trim());
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ describe('Astro Markdown', () => {
|
|||
it('Can handle scripts in markdown pages', async () => {
|
||||
const html = await fixture.readFile('/script/index.html');
|
||||
console.log(html);
|
||||
expect(html).not.to.match(new RegExp("\/src\/scripts\/test\.js"));
|
||||
expect(html).not.to.match(new RegExp('/src/scripts/test.js'));
|
||||
});
|
||||
|
||||
it('Can load more complex jsxy stuff', async () => {
|
||||
|
|
|
@ -36,8 +36,15 @@ export async function renderMarkdown(
|
|||
content: string,
|
||||
opts: MarkdownRenderingOptions = {}
|
||||
): Promise<MarkdownRenderingResult> {
|
||||
let { fileURL, mode = 'mdx', syntaxHighlight = 'shiki', shikiConfig = {}, remarkPlugins = [], rehypePlugins = [] } = opts;
|
||||
const input = new VFile({ value: content, path: fileURL })
|
||||
let {
|
||||
fileURL,
|
||||
mode = 'mdx',
|
||||
syntaxHighlight = 'shiki',
|
||||
shikiConfig = {},
|
||||
remarkPlugins = [],
|
||||
rehypePlugins = [],
|
||||
} = opts;
|
||||
const input = new VFile({ value: content, path: fileURL });
|
||||
const scopedClassName = opts.$?.scopedClassName;
|
||||
const isMDX = mode === 'mdx';
|
||||
const { headers, rehypeCollectHeaders } = createCollectHeaders();
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
import {
|
||||
mdxExpressionFromMarkdown,
|
||||
mdxExpressionToMarkdown
|
||||
} from 'mdast-util-mdx-expression'
|
||||
import {mdxJsxFromMarkdown, mdxJsxToMarkdown} from 'mdast-util-mdx-jsx'
|
||||
import { mdxExpressionFromMarkdown, mdxExpressionToMarkdown } from 'mdast-util-mdx-expression';
|
||||
import { mdxJsxFromMarkdown, mdxJsxToMarkdown } from 'mdast-util-mdx-jsx';
|
||||
|
||||
export function mdxFromMarkdown(): any {
|
||||
return [mdxExpressionFromMarkdown, mdxJsxFromMarkdown]
|
||||
return [mdxExpressionFromMarkdown, mdxJsxFromMarkdown];
|
||||
}
|
||||
|
||||
export function mdxToMarkdown(): any {
|
||||
return {
|
||||
extensions: [
|
||||
mdxExpressionToMarkdown,
|
||||
mdxJsxToMarkdown,
|
||||
]
|
||||
}
|
||||
return {
|
||||
extensions: [mdxExpressionToMarkdown, mdxJsxToMarkdown],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -31,21 +31,22 @@ export default function createCollectHeaders() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (child.type === 'text' || child.type === 'raw') {
|
||||
if (child.type === 'text' || child.type === 'raw') {
|
||||
raw += child.value;
|
||||
text += child.value;
|
||||
isJSX = isJSX || child.value.includes('{');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
node.properties = node.properties || {};
|
||||
if (typeof node.properties.id !== 'string') {
|
||||
if (isJSX) {
|
||||
// HACK: for ids that have JSX content, use $$slug helper to generate slug at runtime
|
||||
node.properties.id = `$$slug(\`${text.replace(/\{/g, '${')}\`)`;
|
||||
(node as any).type = 'raw';
|
||||
(node as any).value = `<${node.tagName} id={${node.properties.id}}>${raw}</${node.tagName}>`;
|
||||
(
|
||||
node as any
|
||||
).value = `<${node.tagName} id={${node.properties.id}}>${raw}</${node.tagName}>`;
|
||||
} else {
|
||||
node.properties.id = slugger.slug(text);
|
||||
}
|
||||
|
|
|
@ -9,36 +9,36 @@ export default function rehypeJsx(): any {
|
|||
}
|
||||
if (MDX_ELEMENTS.has(child.type)) {
|
||||
const attrs = child.attributes.reduce((acc: any[], entry: any) => {
|
||||
let attr = entry.value;
|
||||
if (attr && typeof attr === 'object') {
|
||||
attr = `{${attr.value}}`;
|
||||
} else if (attr && entry.type === 'mdxJsxExpressionAttribute') {
|
||||
attr = `{${attr}}`
|
||||
} else if (attr === null) {
|
||||
attr = "";
|
||||
} else if (typeof attr === 'string') {
|
||||
attr = `"${attr}"`;
|
||||
}
|
||||
if (!entry.name) {
|
||||
return acc + ` ${attr}`;
|
||||
}
|
||||
return acc + ` ${entry.name}${attr ? '=' : ''}${attr}`;
|
||||
}, '');
|
||||
let attr = entry.value;
|
||||
if (attr && typeof attr === 'object') {
|
||||
attr = `{${attr.value}}`;
|
||||
} else if (attr && entry.type === 'mdxJsxExpressionAttribute') {
|
||||
attr = `{${attr}}`;
|
||||
} else if (attr === null) {
|
||||
attr = '';
|
||||
} else if (typeof attr === 'string') {
|
||||
attr = `"${attr}"`;
|
||||
}
|
||||
if (!entry.name) {
|
||||
return acc + ` ${attr}`;
|
||||
}
|
||||
return acc + ` ${entry.name}${attr ? '=' : ''}${attr}`;
|
||||
}, '');
|
||||
|
||||
if (child.children.length === 0) {
|
||||
return {
|
||||
type: 'raw',
|
||||
value: `<${child.name}${attrs} />`
|
||||
value: `<${child.name}${attrs} />`,
|
||||
};
|
||||
}
|
||||
child.children.splice(0, 0, {
|
||||
type: 'raw',
|
||||
value: `\n<${child.name}${attrs}>`
|
||||
})
|
||||
value: `\n<${child.name}${attrs}>`,
|
||||
});
|
||||
child.children.push({
|
||||
type: 'raw',
|
||||
value: `</${child.name}>\n`
|
||||
})
|
||||
value: `</${child.name}>\n`,
|
||||
});
|
||||
return {
|
||||
...child,
|
||||
type: 'element',
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* @typedef {import('remark-mdx')} DoNotTouchAsThisImportItIncludesMdxInTree
|
||||
*/
|
||||
|
||||
import {visit} from 'unist-util-visit'
|
||||
import { visit } from 'unist-util-visit';
|
||||
|
||||
/**
|
||||
* A tiny plugin that unravels `<p><h1>x</h1></p>` but also
|
||||
|
@ -19,63 +19,54 @@ import {visit} from 'unist-util-visit'
|
|||
* @type {import('unified').Plugin<Array<void>, Root>}
|
||||
*/
|
||||
export default function remarkMarkAndUnravel() {
|
||||
return (tree: any) => {
|
||||
visit(tree, (node, index, parent_) => {
|
||||
const parent = /** @type {Parent} */ (parent_)
|
||||
let offset = -1
|
||||
let all = true
|
||||
/** @type {boolean|undefined} */
|
||||
let oneOrMore
|
||||
return (tree: any) => {
|
||||
visit(tree, (node, index, parent_) => {
|
||||
const parent = /** @type {Parent} */ parent_;
|
||||
let offset = -1;
|
||||
let all = true;
|
||||
/** @type {boolean|undefined} */
|
||||
let oneOrMore;
|
||||
|
||||
if (parent && typeof index === 'number' && node.type === 'paragraph') {
|
||||
const children = node.children
|
||||
if (parent && typeof index === 'number' && node.type === 'paragraph') {
|
||||
const children = node.children;
|
||||
|
||||
while (++offset < children.length) {
|
||||
const child = children[offset]
|
||||
while (++offset < children.length) {
|
||||
const child = children[offset];
|
||||
|
||||
if (
|
||||
child.type === 'mdxJsxTextElement' ||
|
||||
child.type === 'mdxTextExpression'
|
||||
) {
|
||||
oneOrMore = true
|
||||
} else if (
|
||||
child.type === 'text' &&
|
||||
/^[\t\r\n ]+$/.test(String(child.value))
|
||||
) {
|
||||
// Empty.
|
||||
} else {
|
||||
all = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (child.type === 'mdxJsxTextElement' || child.type === 'mdxTextExpression') {
|
||||
oneOrMore = true;
|
||||
} else if (child.type === 'text' && /^[\t\r\n ]+$/.test(String(child.value))) {
|
||||
// Empty.
|
||||
} else {
|
||||
all = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all && oneOrMore) {
|
||||
offset = -1
|
||||
if (all && oneOrMore) {
|
||||
offset = -1;
|
||||
|
||||
while (++offset < children.length) {
|
||||
const child = children[offset]
|
||||
while (++offset < children.length) {
|
||||
const child = children[offset];
|
||||
|
||||
if (child.type === 'mdxJsxTextElement') {
|
||||
child.type = 'mdxJsxFlowElement'
|
||||
}
|
||||
if (child.type === 'mdxJsxTextElement') {
|
||||
child.type = 'mdxJsxFlowElement';
|
||||
}
|
||||
|
||||
if (child.type === 'mdxTextExpression') {
|
||||
child.type = 'mdxFlowExpression'
|
||||
}
|
||||
}
|
||||
if (child.type === 'mdxTextExpression') {
|
||||
child.type = 'mdxFlowExpression';
|
||||
}
|
||||
}
|
||||
|
||||
parent.children.splice(index, 1, ...children)
|
||||
return index
|
||||
}
|
||||
}
|
||||
parent.children.splice(index, 1, ...children);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
node.type === 'mdxJsxFlowElement' ||
|
||||
node.type === 'mdxJsxTextElement'
|
||||
) {
|
||||
const data = node.data || (node.data = {})
|
||||
data._mdxExplicitJsx = true
|
||||
}
|
||||
})
|
||||
}
|
||||
if (node.type === 'mdxJsxFlowElement' || node.type === 'mdxJsxTextElement') {
|
||||
const data = node.data || (node.data = {});
|
||||
data._mdxExplicitJsx = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import {mdxjs} from 'micromark-extension-mdxjs'
|
||||
import { mdxFromMarkdown, mdxToMarkdown } from './mdast-util-mdxish.js'
|
||||
import { mdxjs } from 'micromark-extension-mdxjs';
|
||||
import { mdxFromMarkdown, mdxToMarkdown } from './mdast-util-mdxish.js';
|
||||
|
||||
export default function remarkMdxish(this: any, options = {}) {
|
||||
const data = this.data()
|
||||
const data = this.data();
|
||||
|
||||
add('micromarkExtensions', mdxjs(options))
|
||||
add('fromMarkdownExtensions', mdxFromMarkdown())
|
||||
add('toMarkdownExtensions', mdxToMarkdown())
|
||||
add('micromarkExtensions', mdxjs(options));
|
||||
add('fromMarkdownExtensions', mdxFromMarkdown());
|
||||
add('toMarkdownExtensions', mdxToMarkdown());
|
||||
|
||||
function add(field: string, value: unknown) {
|
||||
const list = data[field] ? data[field] : (data[field] = [])
|
||||
list.push(value)
|
||||
}
|
||||
function add(field: string, value: unknown) {
|
||||
const list = data[field] ? data[field] : (data[field] = []);
|
||||
list.push(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,14 +49,23 @@ describe('components', () => {
|
|||
it('should normalize children', async () => {
|
||||
const { code } = await renderMarkdown(`<Component bool={true}>Hello world!</Component>`, {});
|
||||
|
||||
chai.expect(code).to.equal(`<Fragment>\n<Component bool={true}>Hello world!</Component>\n</Fragment>`);
|
||||
chai
|
||||
.expect(code)
|
||||
.to.equal(`<Fragment>\n<Component bool={true}>Hello world!</Component>\n</Fragment>`);
|
||||
});
|
||||
|
||||
it('should allow markdown without many spaces', async () => {
|
||||
const { code } = await renderMarkdown(`<Component>
|
||||
const { code } = await renderMarkdown(
|
||||
`<Component>
|
||||
# Hello world!
|
||||
</Component>`, {});
|
||||
</Component>`,
|
||||
{}
|
||||
);
|
||||
|
||||
chai.expect(code).to.equal(`<Fragment>\n<Component><h1 id="hello-world">Hello world!</h1></Component>\n</Fragment>`);
|
||||
chai
|
||||
.expect(code)
|
||||
.to.equal(
|
||||
`<Fragment>\n<Component><h1 id="hello-world">Hello world!</h1></Component>\n</Fragment>`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,24 +17,35 @@ describe('expressions', () => {
|
|||
it('should be able to serialize expression inside markdown', async () => {
|
||||
const { code } = await renderMarkdown(`# {frontmatter.title}`, {});
|
||||
|
||||
chai.expect(code).to.equal(`<h1 id={$$slug(\`\${frontmatter.title}\`)}>{frontmatter.title}</h1>`);
|
||||
chai
|
||||
.expect(code)
|
||||
.to.equal(`<h1 id={$$slug(\`\${frontmatter.title}\`)}>{frontmatter.title}</h1>`);
|
||||
});
|
||||
|
||||
it('should be able to serialize complex expression inside markdown', async () => {
|
||||
const { code } = await renderMarkdown(`# Hello {frontmatter.name}`, {});
|
||||
|
||||
chai.expect(code).to.equal(`<h1 id={$$slug(\`Hello \${frontmatter.name}\`)}>Hello {frontmatter.name}</h1>`);
|
||||
chai
|
||||
.expect(code)
|
||||
.to.equal(`<h1 id={$$slug(\`Hello \${frontmatter.name}\`)}>Hello {frontmatter.name}</h1>`);
|
||||
});
|
||||
|
||||
it('should be able to serialize complex expression with markup inside markdown', async () => {
|
||||
const { code } = await renderMarkdown(`# Hello <span>{frontmatter.name}</span>`, {});
|
||||
|
||||
chai.expect(code).to.equal(`<h1 id={$$slug(\`Hello \${frontmatter.name}\`)}>Hello <span>{frontmatter.name}</span></h1>`);
|
||||
chai
|
||||
.expect(code)
|
||||
.to.equal(
|
||||
`<h1 id={$$slug(\`Hello \${frontmatter.name}\`)}>Hello <span>{frontmatter.name}</span></h1>`
|
||||
);
|
||||
});
|
||||
|
||||
it('should be able to serialize function expression', async () => {
|
||||
const { code } = await renderMarkdown(`{frontmatter.list.map(item => <p id={item}>{item}</p>)}` , {});
|
||||
const { code } = await renderMarkdown(
|
||||
`{frontmatter.list.map(item => <p id={item}>{item}</p>)}`,
|
||||
{}
|
||||
);
|
||||
|
||||
chai.expect(code).to.equal(`{frontmatter.list.map(item => <p id={item}>{item}</p>)}`);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,11 +16,11 @@ describe('plugins', () => {
|
|||
};
|
||||
|
||||
return transformer;
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
chai.expect(typeof context).to.equal('object');
|
||||
chai.expect(context.path).to.equal(fileURLToPath(new URL('virtual.md', import.meta.url)));
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue