Skip to content

Commit

Permalink
🍣 Add raw directives/roles for inserting tex/typst-specific content (#…
Browse files Browse the repository at this point in the history
…1442)

Co-authored-by: Rowan Cockett <rowanc1@gmail.com>
  • Loading branch information
fwkoch and rowanc1 authored Aug 9, 2024
1 parent 5524441 commit 857c5ac
Show file tree
Hide file tree
Showing 17 changed files with 320 additions and 7 deletions.
10 changes: 10 additions & 0 deletions .changeset/empty-rules-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'myst-directives': patch
'myst-spec-ext': patch
'myst-to-typst': patch
'myst-to-tex': patch
'myst-roles': patch
'myst-cli': patch
---

Add raw directives/roles for inserting tex/typst-specific content
14 changes: 13 additions & 1 deletion docs/creating-pdf-documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,22 @@ exports:

Please consider [contributing your template](/jtex/contribute-a-template) to the growing list of templates so that other people can benefit and improve your work!

## Excluding Source
## Excluding Content from Specific Exports

If you have a block or notebook cell that you do not want to render to your $\LaTeX$ output, add the `no-tex` tag to the cell. Similarly, to exclude a cell from Typst, use `no-typst`. To exclude a cell from both formats, use `no-pdf`.

## Including Content with Specific Exports

If you need to inject some $\LaTeX$- or Typst-specific content into their respective exports, you may use the `{raw:latex}` or `{raw:typst}` role and directive. For example, to insert a new page in Typst with two columns:

````markdown
```{raw:typst}
#set page(columns: 2, margin: (x: 1.5cm, y: 2cm),);
```
````

The content in these directives and roles will be included exactly as written in their respective exports, and will be ignored in all other contexts.

(multi-article-exports)=

## Multi-Article Exports
Expand Down
1 change: 1 addition & 0 deletions packages/myst-cli/src/transforms/raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { PhrasingContent } from 'myst-spec';
export async function rawDirectiveTransform(tree: GenericParent, vfile: VFile) {
const rawNodes = selectAll('raw', tree) as Raw[];
rawNodes.forEach((node) => {
if (!node.value) return;
if (['latex', 'tex'].includes(node.lang as string)) {
const state = new TexParser(node.value, vfile);
(node as GenericNode).children = state.ast.children;
Expand Down
6 changes: 4 additions & 2 deletions packages/myst-directives/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { mdastDirective } from './mdast.js';
import { mermaidDirective } from './mermaid.js';
import { mystdemoDirective } from './mystdemo.js';
import { blockquoteDirective } from './blockquote.js';
import { rawDirective } from './raw.js';
import { rawDirective, rawLatexDirective, rawTypstDirective } from './raw.js';
import { divDirective } from './div.js';

export const defaultDirectives = [
Expand All @@ -43,6 +43,8 @@ export const defaultDirectives = [
mermaidDirective,
mystdemoDirective,
rawDirective,
rawLatexDirective,
rawTypstDirective,
divDirective,
];

Expand All @@ -63,5 +65,5 @@ export { mdastDirective } from './mdast.js';
export { mermaidDirective } from './mermaid.js';
export { mystdemoDirective } from './mystdemo.js';
export { blockquoteDirective } from './blockquote.js';
export { rawDirective } from './raw.js';
export { rawDirective, rawLatexDirective, rawTypstDirective } from './raw.js';
export { divDirective } from './div.js';
56 changes: 53 additions & 3 deletions packages/myst-directives/src/raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Raw } from 'myst-spec-ext';

export const rawDirective: DirectiveSpec = {
name: 'raw',
doc: 'Allows you to include the source or parsed version of a separate file into your document tree.',
doc: 'Allows you to include non-markdown text in your document. If the argument "latex" is provided, the text will be parsed as latex; otherwise, it will be included as raw text.',
arg: {
type: String,
doc: 'Format of directive content - for now, only "latex" is valid',
Expand All @@ -13,11 +13,61 @@ export const rawDirective: DirectiveSpec = {
doc: 'Raw content to be parsed',
},
run(data): Raw[] {
const lang = (data.arg as string) ?? '';
const value = (data.body as string) ?? '';
const tex = ['tex', 'latex'].includes(lang) ? `\n${value}\n` : undefined;
const typst = ['typst', 'typ'].includes(lang) ? `\n${value}\n` : undefined;
return [
{
type: 'raw',
lang: (data.arg as string) ?? '',
value: (data.body as string) ?? '',
lang,
tex,
typst,
value,
},
];
},
};

export const rawLatexDirective: DirectiveSpec = {
name: 'raw:latex',
alias: ['raw:tex'],
doc: 'Allows you to include tex in your document that will only be included in tex exports',
body: {
type: String,
doc: 'Raw tex content',
},
run(data): Raw[] {
const lang = 'tex';
const body = data.body as string;
const tex = body ? `\n${body}\n` : '';
return [
{
type: 'raw',
lang,
tex,
},
];
},
};

export const rawTypstDirective: DirectiveSpec = {
name: 'raw:typst',
alias: ['raw:typ'],
doc: 'Allows you to include typst in your document that will only be included in typst exports',
body: {
type: String,
doc: 'Raw typst content',
},
run(data): Raw[] {
const lang = 'typst';
const body = data.body as string;
const typst = body ? `\n${body}\n` : '';
return [
{
type: 'raw',
lang,
typst,
},
];
},
Expand Down
4 changes: 4 additions & 0 deletions packages/myst-roles/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { subscriptRole } from './subscript.js';
import { superscriptRole } from './superscript.js';
import { underlineRole } from './underline.js';
import { keyboardRole } from './keyboard.js';
import { rawLatexRole, rawTypstRole } from './raw.js';

export const defaultRoles = [
abbreviationRole,
Expand All @@ -34,6 +35,8 @@ export const defaultRoles = [
superscriptRole,
underlineRole,
keyboardRole,
rawLatexRole,
rawTypstRole,
];
export { abbreviationRole } from './abbreviation.js';
export { chemRole } from './chem.js';
Expand All @@ -51,3 +54,4 @@ export { subscriptRole } from './subscript.js';
export { superscriptRole } from './superscript.js';
export { underlineRole } from './underline.js';
export { keyboardRole } from './keyboard.js';
export { rawLatexRole, rawTypstRole } from './raw.js';
44 changes: 44 additions & 0 deletions packages/myst-roles/src/raw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { RoleSpec } from 'myst-common';
import type { Raw } from 'myst-spec-ext';

export const rawLatexRole: RoleSpec = {
name: 'raw:latex',
alias: ['raw:tex'],
doc: 'Allows you to include tex in your document that will only be included in tex exports',
body: {
type: String,
doc: 'Raw tex content',
},
run(data): Raw[] {
const lang = 'tex';
const tex = (data.body as string) ?? '';
return [
{
type: 'raw',
lang,
tex,
},
];
},
};

export const rawTypstRole: RoleSpec = {
name: 'raw:typst',
alias: ['raw:typ'],
doc: 'Allows you to include typst in your document that will only be included in typst exports',
body: {
type: String,
doc: 'Raw typst content',
},
run(data): Raw[] {
const lang = 'typst';
const typst = (data.body as string) ?? '';
return [
{
type: 'raw',
lang,
typst,
},
];
},
};
4 changes: 3 additions & 1 deletion packages/myst-spec-ext/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ export type Include = {
export type Raw = {
type: 'raw';
lang?: string;
value: string;
tex?: string;
typst?: string;
value?: string;
children?: (FlowContent | ListContent | PhrasingContent)[];
};

Expand Down
7 changes: 7 additions & 0 deletions packages/myst-to-tex/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,13 @@ const handlers: Record<string, Handler> = {
state.write('}');
}
},
raw(node, state) {
if (node.tex) {
state.write(node.tex);
} else if (node.children?.length) {
state.renderChildren(node);
}
},
};

class TexSerializer implements ITexSerializer {
Expand Down
7 changes: 7 additions & 0 deletions packages/myst-to-typst/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,13 @@ const handlers: Record<string, Handler> = {
span(node, state) {
state.renderChildren(node, 0, { trimEnd: false });
},
raw(node, state) {
if (node.typst) {
state.write(node.typst);
} else if (node.children?.length) {
state.renderChildren(node, undefined, { trimEnd: false });
}
},
};

class TypstSerializer implements ITypstSerializer {
Expand Down
10 changes: 10 additions & 0 deletions packages/mystmd/tests/exports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,13 @@ cases:
outputs:
- path: citation-cff/CITATION.cff
content: citation-cff/outputs/CITATION.cff
- title: Raw directives and roles
cwd: raw
command: myst build --all
outputs:
- path: raw/_build/out.tex
content: raw/outputs/out.tex
- path: raw/_build/out.typ
content: raw/outputs/out.typ
- path: raw/_build/site/content/index.json
content: raw/outputs/index.json
2 changes: 2 additions & 0 deletions packages/mystmd/tests/raw/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# MyST build outputs
/_build/
18 changes: 18 additions & 0 deletions packages/mystmd/tests/raw/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Project with raw content

This has raw {raw:tex}`LaTeX`{raw:typst}`Typst` content

```{raw:latex}
\section{LaTeX Heading}
```
```{raw:typ}
= Typst Heading
```

```{raw}
This is *just text*
```

```{raw} latex
This is \textit{latex}
```
16 changes: 16 additions & 0 deletions packages/mystmd/tests/raw/myst.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# See docs at: https://mystmd.org/guide/frontmatter
version: 1
project:
author: Franklin Koch
date: 9 Aug 2024
exclude: outputs
exports:
- output: _build/out.tex
template: null
- output: _build/out.typ
template: null
site:
template: ../templates/site/myst/book-theme
# options:
# favicon: favicon.ico
# logo: site_logo.png
Loading

0 comments on commit 857c5ac

Please sign in to comment.