summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/hip-rockets-glow.md5
-rw-r--r--packages/integrations/markdoc/README.md34
-rw-r--r--packages/integrations/markdoc/src/options.ts1
-rw-r--r--packages/integrations/markdoc/src/tokenizer.ts6
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/astro.config.mjs7
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/markdoc.config.ts26
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/package.json9
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/Code.astro12
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/CustomMarquee.astro1
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/blog/with-indented-components.mdoc24
-rw-r--r--packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/pages/index.astro19
-rw-r--r--packages/integrations/markdoc/test/render.test.js42
-rw-r--r--pnpm-lock.yaml9
13 files changed, 194 insertions, 1 deletions
diff --git a/.changeset/hip-rockets-glow.md b/.changeset/hip-rockets-glow.md
new file mode 100644
index 000000000..fd121c0d4
--- /dev/null
+++ b/.changeset/hip-rockets-glow.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/markdoc': minor
+---
+
+Added ignoreIndentation as a markdoc integration option to enable better readability of source code.
diff --git a/packages/integrations/markdoc/README.md b/packages/integrations/markdoc/README.md
index da575acc2..fa506b24a 100644
--- a/packages/integrations/markdoc/README.md
+++ b/packages/integrations/markdoc/README.md
@@ -458,6 +458,40 @@ To achieve a more Markdown-like experience, where HTML elements can be included
> **Warning**
> When `allowHTML` is enabled, HTML markup inside Markdoc documents will be rendered as actual HTML elements (including `<script>`), making attack vectors like XSS possible. Ensure that any HTML markup comes from trusted sources.
+### `ignoreIndentation`
+
+By default, any content that is indented by four spaces is treated as a code block. Unfortunately, this behavior makes it difficult to use arbitrary levels of indentation to improve the readability of documents with complex structure.
+
+When using nested tags in Markdoc, it can be helpful to indent the content inside of tags so that the level of depth is clear. To support arbitrary indentation, we have to disable the indent-based code blocks and modify several other markdown-it parsing rules that account for indent-based code blocks. These changes can be applied by enabling the ignoreIndentation option.
+
+```diff lang="js" "ignoreIndentation: true"
+ // astro.config.mjs
+ import { defineConfig } from 'astro/config';
+ import markdoc from '@astrojs/markdoc';
+
+ export default defineConfig({
+ // ...
++ integrations: [markdoc({ ignoreIndentation: true })],
+ // ^^^^^^^^^^^^^^^^^^^^^^^
+ });
+```
+
+```md
+# Welcome to Markdoc with indented tags 👋
+# Note: Can use either spaces or tabs for indentation
+
+{% custom-tag %}
+ {% custom-tag %}
+ ### Tags can be indented for better readability
+
+ {% another-custom-tag %}
+ This is easier to follow when there is a lot of nesting
+ {% /another-custom-tag %}
+
+ {% /custom-tag %}
+{% /custom-tag %}
+```
+
## Examples
- The [Astro Markdoc starter template](https://github.com/withastro/astro/tree/latest/examples/with-markdoc) shows how to use Markdoc files in your Astro project.
diff --git a/packages/integrations/markdoc/src/options.ts b/packages/integrations/markdoc/src/options.ts
index de0926cbb..450285bcf 100644
--- a/packages/integrations/markdoc/src/options.ts
+++ b/packages/integrations/markdoc/src/options.ts
@@ -1,3 +1,4 @@
export interface MarkdocIntegrationOptions {
allowHTML?: boolean;
+ ignoreIndentation?: boolean;
}
diff --git a/packages/integrations/markdoc/src/tokenizer.ts b/packages/integrations/markdoc/src/tokenizer.ts
index 02719b363..79d0d7358 100644
--- a/packages/integrations/markdoc/src/tokenizer.ts
+++ b/packages/integrations/markdoc/src/tokenizer.ts
@@ -15,11 +15,15 @@ export function getMarkdocTokenizer(options: MarkdocIntegrationOptions | undefin
};
if (options?.allowHTML) {
- // we want to allow indentation for Markdoc tags that are interleaved inside HTML block elements
+ // allow indentation for Markdoc tags that are interleaved inside HTML block elements
tokenizerOptions.allowIndentation = true;
// enable HTML token detection in markdown-it
tokenizerOptions.html = true;
}
+ if (options?.ignoreIndentation) {
+ // allow indentation so nested Markdoc tags can be formatted for better readability
+ tokenizerOptions.allowIndentation = true;
+ }
_cachedMarkdocTokenizers[key] = new Markdoc.Tokenizer(tokenizerOptions);
}
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/astro.config.mjs b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/astro.config.mjs
new file mode 100644
index 000000000..c711e7cb6
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/astro.config.mjs
@@ -0,0 +1,7 @@
+import { defineConfig } from 'astro/config';
+import markdoc from '@astrojs/markdoc';
+
+// https://astro.build/config
+export default defineConfig({
+ integrations: [markdoc({ ignoreIndentation: true })],
+});
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/markdoc.config.ts b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/markdoc.config.ts
new file mode 100644
index 000000000..ffb264ed8
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/markdoc.config.ts
@@ -0,0 +1,26 @@
+import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
+
+export default defineMarkdocConfig({
+ nodes: {
+ fence: {
+ render: component('./src/components/Code.astro'),
+ attributes: {
+ language: { type: String },
+ content: { type: String },
+ },
+ },
+ },
+ tags: {
+ 'marquee-element': {
+ render: component('./src/components/CustomMarquee.astro'),
+ attributes: {
+ direction: {
+ type: String,
+ default: 'left',
+ matches: ['left', 'right', 'up', 'down'],
+ errorLevel: 'critical',
+ },
+ },
+ },
+ },
+})
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/package.json b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/package.json
new file mode 100644
index 000000000..3c1d0a7b5
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/markdoc-render-with-indented-components",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/markdoc": "workspace:*",
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/Code.astro b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/Code.astro
new file mode 100644
index 000000000..18bf1399f
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/Code.astro
@@ -0,0 +1,12 @@
+---
+import { Code } from 'astro/components';
+
+type Props = {
+ content: string;
+ language: string;
+}
+
+const { content, language } = Astro.props as Props;
+---
+
+<Code lang={language} code={content} />
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/CustomMarquee.astro b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/CustomMarquee.astro
new file mode 100644
index 000000000..3108b9973
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/components/CustomMarquee.astro
@@ -0,0 +1 @@
+<marquee data-custom-marquee {...Astro.props}><slot /></marquee>
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/blog/with-indented-components.mdoc b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/blog/with-indented-components.mdoc
new file mode 100644
index 000000000..a52b35fc4
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/content/blog/with-indented-components.mdoc
@@ -0,0 +1,24 @@
+---
+title: Post with indented components
+---
+
+## Post with indented components
+
+This uses a custom marquee component with a shortcode:
+
+{% marquee-element direction="right" %}
+ I'm a marquee too!
+
+ {% marquee-element direction="right" %}
+ I'm an indented marquee!
+
+ ### I am an h3!
+ {% /marquee-element %}
+
+ And a nested code block:
+
+ ```js
+ const isRenderedWithShiki = true;
+ ```
+{% /marquee-element %}
+
diff --git a/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/pages/index.astro b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/pages/index.astro
new file mode 100644
index 000000000..0ae7ed4c9
--- /dev/null
+++ b/packages/integrations/markdoc/test/fixtures/render-with-indented-components/src/pages/index.astro
@@ -0,0 +1,19 @@
+---
+import { getEntryBySlug } from "astro:content";
+
+const post = await getEntryBySlug('blog', 'with-indented-components');
+const { Content } = await post.render();
+---
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Content</title>
+</head>
+<body>
+ <Content />
+</body>
+</html>
diff --git a/packages/integrations/markdoc/test/render.test.js b/packages/integrations/markdoc/test/render.test.js
index 86ffcb707..97c441b85 100644
--- a/packages/integrations/markdoc/test/render.test.js
+++ b/packages/integrations/markdoc/test/render.test.js
@@ -46,6 +46,19 @@ describe('Markdoc - render', () => {
await server.stop();
});
+ it('renders content - with indented components', async () => {
+ const fixture = await getFixture('render-with-indented-components');
+ const server = await fixture.startDevServer();
+
+ const res = await fixture.fetch('/');
+ const html = await res.text();
+
+ renderIndentedComponentsChecks(html);
+
+ await server.stop();
+
+ });
+
it('renders content - with `render: null` in document', async () => {
const fixture = await getFixture('render-null');
const server = await fixture.startDevServer();
@@ -87,6 +100,15 @@ describe('Markdoc - render', () => {
renderComponentsChecks(html);
});
+ it('renders content - with indented components', async () => {
+ const fixture = await getFixture('render-with-indented-components');
+ await fixture.build();
+
+ const html = await fixture.readFile('/index.html');
+
+ renderIndentedComponentsChecks(html);
+ });
+
it('renders content - with `render: null` in document', async () => {
const fixture = await getFixture('render-null');
await fixture.build();
@@ -126,6 +148,26 @@ function renderComponentsChecks(html) {
}
/** @param {string} html */
+function renderIndentedComponentsChecks(html) {
+ const { document } = parseHTML(html);
+ const h2 = document.querySelector('h2');
+ expect(h2.textContent).to.equal('Post with indented components');
+
+ // Renders custom shortcode components
+ const marquees = document.querySelectorAll('marquee');
+ expect(marquees.length).to.equal(2);
+
+ // Renders h3
+ const h3 = document.querySelector('h3');
+ expect(h3.textContent).to.equal('I am an h3!');
+
+ // Renders Astro Code component
+ const pre = document.querySelector('pre');
+ expect(pre).to.not.be.null;
+ expect(pre.className).to.equal('astro-code github-dark');
+}
+
+/** @param {string} html */
function renderConfigChecks(html) {
const { document } = parseHTML(html);
const h2 = document.querySelector('h2');
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 40672d815..bb4bbc547 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3869,6 +3869,15 @@ importers:
specifier: workspace:*
version: link:../../../../../astro
+ packages/integrations/markdoc/test/fixtures/render-with-indented-components:
+ dependencies:
+ '@astrojs/markdoc':
+ specifier: workspace:*
+ version: link:../../..
+ astro:
+ specifier: workspace:*
+ version: link:../../../../../astro
+
packages/integrations/markdoc/test/fixtures/variables:
dependencies:
'@astrojs/markdoc':