Skip to content

Commit

Permalink
Markdoc Integration allowIndentation option
Browse files Browse the repository at this point in the history
Added allowIndentation to the markdoc integration options. This allows indentation of markdoc tags for better readability without allowing raw HTML in Markdoc files.
  • Loading branch information
AndyClifford committed Oct 11, 2023
1 parent a8b979e commit 34c58ef
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/hip-rockets-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/markdoc': minor
---

Added allowIndentation as a markdoc integration option to enable better readability
18 changes: 18 additions & 0 deletions packages/integrations/markdoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,24 @@ 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.
### `allowIndentation`
Enables indentation of Markdoc tags for better readability.
The allowIndentation option is experimental and is not enabled by default. When the option is enabled, it is not possible to use indent-based code blocks.
```diff lang="js" "allowIndentation: true"
// astro.config.mjs
import { defineConfig } from 'astro/config';
import markdoc from '@astrojs/markdoc';

export default defineConfig({
// ...
+ integrations: [markdoc({ allowIndentation: true })],
// ^^^^^^^^^^^^^^^^^^^^^^
});
```
## 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.
Expand Down
1 change: 1 addition & 0 deletions packages/integrations/markdoc/src/options.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export interface MarkdocIntegrationOptions {
allowHTML?: boolean;
allowIndentation?: boolean;
}
6 changes: 5 additions & 1 deletion packages/integrations/markdoc/src/tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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?.allowIndentation) {
// allow indentation so nested Markdoc tags can be formatted for better readability
tokenizerOptions.allowIndentation = true;
}

_cachedMarkdocTokenizers[key] = new Markdoc.Tokenizer(tokenizerOptions);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'astro/config';
import markdoc from '@astrojs/markdoc';

// https://astro.build/config
export default defineConfig({
integrations: [markdoc({ allowIndentation: true })],
});
Original file line number Diff line number Diff line change
@@ -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',
},
},
},
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "@test/markdoc-render-with-indented-components",
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/markdoc": "workspace:*",
"astro": "workspace:*"
},
"devDependencies": {
"shiki": "^0.14.3"
}
}
Original file line number Diff line number Diff line change
@@ -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} />
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<marquee data-custom-marquee {...Astro.props}><slot /></marquee>
Original file line number Diff line number Diff line change
@@ -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 %}

Original file line number Diff line number Diff line change
@@ -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>
42 changes: 42 additions & 0 deletions packages/integrations/markdoc/test/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -125,6 +147,26 @@ function renderComponentsChecks(html) {
expect(pre.className).to.equal('astro-code github-dark');
}

/** @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 indented 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);
Expand Down
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 34c58ef

Please sign in to comment.