@astrojs/mdx 0.4.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +37 -0
- package/README.md +21 -3
- package/dist/astro-data-utils.d.ts +9 -0
- package/dist/astro-data-utils.js +66 -0
- package/dist/index.js +64 -47
- package/dist/rehype-collect-headings.d.ts +6 -0
- package/dist/rehype-collect-headings.js +47 -0
- package/dist/remark-prism.js +2 -34
- package/dist/utils.d.ts +5 -3
- package/dist/utils.js +22 -3
- package/package.json +9 -6
- package/src/astro-data-utils.ts +81 -0
- package/src/index.ts +83 -63
- package/src/rehype-collect-headings.ts +50 -0
- package/src/remark-prism.ts +2 -44
- package/src/utils.ts +27 -2
- package/test/fixtures/mdx-escape/src/components/Em.astro +7 -0
- package/test/fixtures/mdx-escape/src/components/P.astro +1 -0
- package/test/fixtures/mdx-escape/src/components/Title.astro +1 -0
- package/test/fixtures/mdx-escape/src/pages/html-tag.mdx +5 -0
- package/test/fixtures/mdx-escape/src/pages/index.mdx +13 -0
- package/test/fixtures/mdx-frontmatter/src/layouts/Base.astro +13 -3
- package/test/fixtures/mdx-frontmatter/src/pages/index.mdx +3 -0
- package/test/fixtures/mdx-frontmatter/src/pages/with-headings.mdx +7 -0
- package/test/fixtures/mdx-frontmatter-injection/astro.config.mjs +12 -0
- package/test/fixtures/mdx-frontmatter-injection/node_modules/.bin/astro +17 -0
- package/test/fixtures/mdx-frontmatter-injection/package.json +12 -0
- package/test/fixtures/mdx-frontmatter-injection/src/markdown-plugins.mjs +20 -0
- package/test/fixtures/mdx-frontmatter-injection/src/pages/glob.json.js +6 -0
- package/test/fixtures/mdx-frontmatter-injection/src/pages/page-1.mdx +3 -0
- package/test/fixtures/mdx-frontmatter-injection/src/pages/page-2.mdx +19 -0
- package/test/fixtures/mdx-frontmatter-injection/src/pages/with-overrides.mdx +7 -0
- package/test/fixtures/mdx-get-headings/src/pages/pages.json.js +11 -0
- package/test/fixtures/mdx-get-headings/src/pages/test-with-jsx-expressions.mdx +8 -0
- package/test/fixtures/mdx-get-headings/src/pages/test.mdx +9 -0
- package/test/fixtures/mdx-page/astro.config.ts +5 -0
- package/test/fixtures/mdx-page/node_modules/.bin/astro +17 -0
- package/test/fixtures/mdx-page/package.json +7 -0
- package/test/fixtures/mdx-plus-react/astro.config.mjs +6 -0
- package/test/fixtures/mdx-plus-react/node_modules/.bin/astro +17 -0
- package/test/fixtures/mdx-plus-react/package.json +8 -0
- package/test/fixtures/mdx-plus-react/src/components/Component.jsx +5 -0
- package/test/fixtures/mdx-plus-react/src/pages/index.astro +11 -0
- package/test/fixtures/mdx-rehype-plugins/src/pages/reading-time.json.js +7 -0
- package/test/fixtures/mdx-rehype-plugins/src/pages/space-ipsum.mdx +25 -0
- package/test/fixtures/mdx-remark-plugins/src/pages/headings-glob.json.js +6 -0
- package/test/mdx-escape.test.js +32 -0
- package/test/mdx-frontmatter-injection.test.js +44 -0
- package/test/mdx-frontmatter.test.js +26 -26
- package/test/mdx-get-headings.test.js +60 -0
- package/test/mdx-page.test.js +0 -1
- package/test/mdx-plus-react.test.js +25 -0
- package/test/mdx-rehype-plugins.test.js +70 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Space ipsum
|
|
2
|
+
|
|
3
|
+
For those who have seen the Earth from space, and for the hundreds and perhaps thousands more who will, the experience most certainly changes your perspective. The things that we share in our world are far more valuable than those which divide us.
|
|
4
|
+
|
|
5
|
+
It suddenly struck me that that tiny pea, pretty and blue, was the Earth. I put up my thumb and shut one eye, and my thumb blotted out the planet Earth. I didn’t feel like a giant. I felt very, very small.
|
|
6
|
+
|
|
7
|
+
Science has not yet mastered prophecy. We predict too much for the next year and yet far too little for the next 10.
|
|
8
|
+
|
|
9
|
+
## Section 2
|
|
10
|
+
|
|
11
|
+
We choose to go to the moon in this decade and do the other things, not because they are easy, but because they are hard, because that goal will serve to organize and measure the best of our energies and skills, because that challenge is one that we are willing to accept, one we are unwilling to postpone, and one which we intend to win.
|
|
12
|
+
|
|
13
|
+
There can be no thought of finishing for ‘aiming for the stars.’ Both figuratively and literally, it is a task to occupy the generations. And no matter how much progress one makes, there is always the thrill of just beginning.
|
|
14
|
+
|
|
15
|
+
As I stand out here in the wonders of the unknown at Hadley, I sort of realize there’s a fundamental truth to our nature, Man must explore . . . and this is exploration at its greatest.
|
|
16
|
+
|
|
17
|
+
## Section 3
|
|
18
|
+
|
|
19
|
+
Never in all their history have men been able truly to conceive of the world as one: a single sphere, a globe, having the qualities of a globe, a round earth in which all the directions eventually meet, in which there is no center because every point, or none, is center — an equal earth which all men occupy as equals. The airman’s earth, if free men make it, will be truly round: a globe in practice, not in theory.
|
|
20
|
+
|
|
21
|
+
To be the first to enter the cosmos, to engage, single-handed, in an unprecedented duel with nature—could one dream of anything more?
|
|
22
|
+
|
|
23
|
+
There can be no thought of finishing for ‘aiming for the stars.’ Both figuratively and literally, it is a task to occupy the generations. And no matter how much progress one makes, there is always the thrill of just beginning.
|
|
24
|
+
|
|
25
|
+
We are all connected; To each other, biologically. To the earth, chemically. To the rest of the universe atomically.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { parseHTML } from 'linkedom';
|
|
5
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
6
|
+
|
|
7
|
+
const FIXTURE_ROOT = new URL('./fixtures/mdx-escape/', import.meta.url);
|
|
8
|
+
|
|
9
|
+
describe('MDX frontmatter', () => {
|
|
10
|
+
let fixture;
|
|
11
|
+
before(async () => {
|
|
12
|
+
fixture = await loadFixture({
|
|
13
|
+
root: FIXTURE_ROOT,
|
|
14
|
+
integrations: [mdx()],
|
|
15
|
+
});
|
|
16
|
+
await fixture.build();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('does not have unescaped HTML at top-level', async () => {
|
|
20
|
+
const html = await fixture.readFile('/index.html');
|
|
21
|
+
const { document } = parseHTML(html);
|
|
22
|
+
|
|
23
|
+
expect(document.body.textContent).to.not.include('<em');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('does not have unescaped HTML inside html tags', async () => {
|
|
27
|
+
const html = await fixture.readFile('/html-tag/index.html');
|
|
28
|
+
const { document } = parseHTML(html);
|
|
29
|
+
|
|
30
|
+
expect(document.body.textContent).to.not.include('<em');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
3
|
+
|
|
4
|
+
const FIXTURE_ROOT = new URL('./fixtures/mdx-frontmatter-injection/', import.meta.url);
|
|
5
|
+
|
|
6
|
+
describe('MDX frontmatter injection', () => {
|
|
7
|
+
let fixture;
|
|
8
|
+
|
|
9
|
+
before(async () => {
|
|
10
|
+
fixture = await loadFixture({
|
|
11
|
+
root: FIXTURE_ROOT,
|
|
12
|
+
});
|
|
13
|
+
await fixture.build();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('remark supports custom vfile data - get title', async () => {
|
|
17
|
+
const frontmatterByPage = JSON.parse(await fixture.readFile('/glob.json'));
|
|
18
|
+
const titles = frontmatterByPage.map((frontmatter = {}) => frontmatter.title);
|
|
19
|
+
expect(titles).to.contain('Page 1');
|
|
20
|
+
expect(titles).to.contain('Page 2');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('rehype supports custom vfile data - reading time', async () => {
|
|
24
|
+
const frontmatterByPage = JSON.parse(await fixture.readFile('/glob.json'));
|
|
25
|
+
const readingTimes = frontmatterByPage.map(
|
|
26
|
+
(frontmatter = {}) => frontmatter.injectedReadingTime
|
|
27
|
+
);
|
|
28
|
+
expect(readingTimes.length).to.be.greaterThan(0);
|
|
29
|
+
for (let readingTime of readingTimes) {
|
|
30
|
+
expect(readingTime).to.not.be.null;
|
|
31
|
+
expect(readingTime.text).match(/^\d+ min read/);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('overrides injected frontmatter with user frontmatter', async () => {
|
|
36
|
+
const frontmatterByPage = JSON.parse(await fixture.readFile('/glob.json'));
|
|
37
|
+
const readingTimes = frontmatterByPage.map(
|
|
38
|
+
(frontmatter = {}) => frontmatter.injectedReadingTime?.text
|
|
39
|
+
);
|
|
40
|
+
const titles = frontmatterByPage.map((frontmatter = {}) => frontmatter.title);
|
|
41
|
+
expect(titles).to.contain('Overridden title');
|
|
42
|
+
expect(readingTimes).to.contain('1000 min read');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -7,33 +7,24 @@ import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
|
7
7
|
const FIXTURE_ROOT = new URL('./fixtures/mdx-frontmatter/', import.meta.url);
|
|
8
8
|
|
|
9
9
|
describe('MDX frontmatter', () => {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
let fixture;
|
|
11
|
+
before(async () => {
|
|
12
|
+
fixture = await loadFixture({
|
|
12
13
|
root: FIXTURE_ROOT,
|
|
13
14
|
integrations: [mdx()],
|
|
14
15
|
});
|
|
15
16
|
await fixture.build();
|
|
17
|
+
});
|
|
18
|
+
it('builds when "frontmatter.property" is in JSX expression', async () => {
|
|
16
19
|
expect(true).to.equal(true);
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
it('extracts frontmatter to "frontmatter" export', async () => {
|
|
20
|
-
const fixture = await loadFixture({
|
|
21
|
-
root: FIXTURE_ROOT,
|
|
22
|
-
integrations: [mdx()],
|
|
23
|
-
});
|
|
24
|
-
await fixture.build();
|
|
25
|
-
|
|
26
23
|
const { titles } = JSON.parse(await fixture.readFile('/glob.json'));
|
|
27
24
|
expect(titles).to.include('Using YAML frontmatter');
|
|
28
25
|
});
|
|
29
26
|
|
|
30
27
|
it('renders layout from "layout" frontmatter property', async () => {
|
|
31
|
-
const fixture = await loadFixture({
|
|
32
|
-
root: FIXTURE_ROOT,
|
|
33
|
-
integrations: [mdx()],
|
|
34
|
-
});
|
|
35
|
-
await fixture.build();
|
|
36
|
-
|
|
37
28
|
const html = await fixture.readFile('/index.html');
|
|
38
29
|
const { document } = parseHTML(html);
|
|
39
30
|
|
|
@@ -42,23 +33,32 @@ describe('MDX frontmatter', () => {
|
|
|
42
33
|
expect(layoutParagraph).to.not.be.null;
|
|
43
34
|
});
|
|
44
35
|
|
|
45
|
-
it('passes frontmatter to layout via "content"
|
|
46
|
-
const fixture = await loadFixture({
|
|
47
|
-
root: FIXTURE_ROOT,
|
|
48
|
-
integrations: [mdx()],
|
|
49
|
-
});
|
|
50
|
-
await fixture.build();
|
|
51
|
-
|
|
36
|
+
it('passes frontmatter to layout via "content" and "frontmatter" props', async () => {
|
|
52
37
|
const html = await fixture.readFile('/index.html');
|
|
53
38
|
const { document } = parseHTML(html);
|
|
54
39
|
|
|
55
|
-
const
|
|
40
|
+
const contentTitle = document.querySelector('[data-content-title]');
|
|
41
|
+
const frontmatterTitle = document.querySelector('[data-frontmatter-title]');
|
|
42
|
+
|
|
43
|
+
expect(contentTitle.textContent).to.equal('Using YAML frontmatter');
|
|
44
|
+
expect(frontmatterTitle.textContent).to.equal('Using YAML frontmatter');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('passes headings to layout via "headings" prop', async () => {
|
|
48
|
+
const html = await fixture.readFile('/with-headings/index.html');
|
|
49
|
+
const { document } = parseHTML(html);
|
|
50
|
+
|
|
51
|
+
const headingSlugs = [...document.querySelectorAll('[data-headings] > li')].map(
|
|
52
|
+
(el) => el.textContent
|
|
53
|
+
);
|
|
56
54
|
|
|
57
|
-
expect(
|
|
55
|
+
expect(headingSlugs.length).to.be.greaterThan(0);
|
|
56
|
+
expect(headingSlugs).to.contain('section-1');
|
|
57
|
+
expect(headingSlugs).to.contain('section-2');
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
it('extracts frontmatter to "customFrontmatter" export when configured', async () => {
|
|
61
|
-
const
|
|
61
|
+
const customFixture = await loadFixture({
|
|
62
62
|
root: new URL('./fixtures/mdx-custom-frontmatter-name/', import.meta.url),
|
|
63
63
|
integrations: [
|
|
64
64
|
mdx({
|
|
@@ -68,9 +68,9 @@ describe('MDX frontmatter', () => {
|
|
|
68
68
|
}),
|
|
69
69
|
],
|
|
70
70
|
});
|
|
71
|
-
await
|
|
71
|
+
await customFixture.build();
|
|
72
72
|
|
|
73
|
-
const { titles } = JSON.parse(await
|
|
73
|
+
const { titles } = JSON.parse(await customFixture.readFile('/glob.json'));
|
|
74
74
|
expect(titles).to.include('Using YAML frontmatter');
|
|
75
75
|
});
|
|
76
76
|
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { parseHTML } from 'linkedom';
|
|
5
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
6
|
+
|
|
7
|
+
describe('MDX getHeadings', () => {
|
|
8
|
+
let fixture;
|
|
9
|
+
|
|
10
|
+
before(async () => {
|
|
11
|
+
fixture = await loadFixture({
|
|
12
|
+
root: new URL('./fixtures/mdx-get-headings/', import.meta.url),
|
|
13
|
+
integrations: [mdx()],
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
await fixture.build();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('adds anchor IDs to headings', async () => {
|
|
20
|
+
const html = await fixture.readFile('/test/index.html');
|
|
21
|
+
const { document } = parseHTML(html);
|
|
22
|
+
|
|
23
|
+
const h2Ids = document.querySelectorAll('h2').map((el) => el?.id);
|
|
24
|
+
const h3Ids = document.querySelectorAll('h3').map((el) => el?.id);
|
|
25
|
+
expect(document.querySelector('h1').id).to.equal('heading-test');
|
|
26
|
+
expect(h2Ids).to.contain('section-1');
|
|
27
|
+
expect(h2Ids).to.contain('section-2');
|
|
28
|
+
expect(h3Ids).to.contain('subsection-1');
|
|
29
|
+
expect(h3Ids).to.contain('subsection-2');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('generates correct getHeadings() export', async () => {
|
|
33
|
+
const { headingsByPage } = JSON.parse(await fixture.readFile('/pages.json'));
|
|
34
|
+
// TODO: make this a snapshot test :)
|
|
35
|
+
expect(JSON.stringify(headingsByPage['./test.mdx'])).to.equal(
|
|
36
|
+
JSON.stringify([
|
|
37
|
+
{ depth: 1, slug: 'heading-test', text: 'Heading test' },
|
|
38
|
+
{ depth: 2, slug: 'section-1', text: 'Section 1' },
|
|
39
|
+
{ depth: 3, slug: 'subsection-1', text: 'Subsection 1' },
|
|
40
|
+
{ depth: 3, slug: 'subsection-2', text: 'Subsection 2' },
|
|
41
|
+
{ depth: 2, slug: 'section-2', text: 'Section 2' },
|
|
42
|
+
])
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('generates correct getHeadings() export for JSX expressions', async () => {
|
|
47
|
+
const { headingsByPage } = JSON.parse(await fixture.readFile('/pages.json'));
|
|
48
|
+
expect(JSON.stringify(headingsByPage['./test-with-jsx-expressions.mdx'])).to.equal(
|
|
49
|
+
JSON.stringify([
|
|
50
|
+
{
|
|
51
|
+
depth: 1,
|
|
52
|
+
slug: 'heading-test-with-jsx-expressions',
|
|
53
|
+
text: 'Heading test with JSX expressions',
|
|
54
|
+
},
|
|
55
|
+
{ depth: 2, slug: 'h2title', text: 'h2Title' },
|
|
56
|
+
{ depth: 3, slug: 'h3title', text: 'h3Title' },
|
|
57
|
+
])
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
});
|
package/test/mdx-page.test.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
import { parseHTML } from 'linkedom';
|
|
5
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
6
|
+
|
|
7
|
+
describe('MDX and React', () => {
|
|
8
|
+
let fixture;
|
|
9
|
+
|
|
10
|
+
before(async () => {
|
|
11
|
+
fixture = await loadFixture({
|
|
12
|
+
root: new URL('./fixtures/mdx-plus-react/', import.meta.url),
|
|
13
|
+
});
|
|
14
|
+
await fixture.build();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('can be used in the same project', async () => {
|
|
18
|
+
const html = await fixture.readFile('/index.html');
|
|
19
|
+
const { document } = parseHTML(html);
|
|
20
|
+
|
|
21
|
+
const p = document.querySelector('p');
|
|
22
|
+
|
|
23
|
+
expect(p.textContent).to.equal('Hello world');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import mdx from '@astrojs/mdx';
|
|
2
|
+
|
|
3
|
+
import getReadingTime from 'reading-time';
|
|
4
|
+
import { toString } from 'mdast-util-to-string';
|
|
5
|
+
import { expect } from 'chai';
|
|
6
|
+
import { parseHTML } from 'linkedom';
|
|
7
|
+
import { jsToTreeNode } from '../dist/utils.js';
|
|
8
|
+
|
|
9
|
+
import { loadFixture } from '../../../astro/test/test-utils.js';
|
|
10
|
+
|
|
11
|
+
function rehypeReadingTime() {
|
|
12
|
+
return function (tree, { data }) {
|
|
13
|
+
const readingTime = getReadingTime(toString(tree));
|
|
14
|
+
tree.children.unshift(
|
|
15
|
+
jsToTreeNode(`export const readingTime = ${JSON.stringify(readingTime)}`)
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const FIXTURE_ROOT = new URL('./fixtures/mdx-rehype-plugins/', import.meta.url);
|
|
21
|
+
|
|
22
|
+
describe('MDX rehype plugins', () => {
|
|
23
|
+
describe('without "extends"', () => {
|
|
24
|
+
let fixture;
|
|
25
|
+
before(async () => {
|
|
26
|
+
fixture = await loadFixture({
|
|
27
|
+
root: FIXTURE_ROOT,
|
|
28
|
+
integrations: [
|
|
29
|
+
mdx({
|
|
30
|
+
rehypePlugins: [rehypeReadingTime],
|
|
31
|
+
}),
|
|
32
|
+
],
|
|
33
|
+
});
|
|
34
|
+
await fixture.build();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('supports custom rehype plugins - reading time', async () => {
|
|
38
|
+
const { readingTime } = JSON.parse(await fixture.readFile('/reading-time.json'));
|
|
39
|
+
|
|
40
|
+
expect(readingTime).to.not.be.null;
|
|
41
|
+
expect(readingTime.text).to.match(/^\d+ min read/);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('with "extends"', () => {
|
|
46
|
+
let fixture;
|
|
47
|
+
before(async () => {
|
|
48
|
+
fixture = await loadFixture({
|
|
49
|
+
root: FIXTURE_ROOT,
|
|
50
|
+
integrations: [
|
|
51
|
+
mdx({
|
|
52
|
+
rehypePlugins: { extends: [rehypeReadingTime] },
|
|
53
|
+
}),
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
await fixture.build();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('preserves default getHeadings', async () => {
|
|
60
|
+
const html = await fixture.readFile('/space-ipsum/index.html');
|
|
61
|
+
const { document } = parseHTML(html);
|
|
62
|
+
|
|
63
|
+
const headings = [...document.querySelectorAll('h1, h2')];
|
|
64
|
+
expect(headings.length).to.be.greaterThan(0);
|
|
65
|
+
for (const heading of headings) {
|
|
66
|
+
expect(heading.id).to.not.be.empty;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|