-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🔄 Support recursive includes in myst and tex #1082
Changes from 4 commits
adfd146
6290500
8e81c4a
1f3d105
5a4f1b5
82ccd0d
0730ae4
92bc2ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'myst-to-typst': patch | ||
--- | ||
|
||
Add newlines after typst include/embed |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'myst-transforms': patch | ||
'myst-cli': patch | ||
--- | ||
|
||
Support tex includes directly in myst processing |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
'myst-transforms': patch | ||
'myst-cli': patch | ||
'mystmd': patch | ||
--- | ||
|
||
Handle circular includes with nice errors and no infinite loops |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'myst-transforms': patch | ||
'mystmd': patch | ||
--- | ||
|
||
Revive basic recursive include |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,24 +7,64 @@ import type { VFile } from 'vfile'; | |
import { parseMyst } from '../process/myst.js'; | ||
import type { ISession } from '../session/types.js'; | ||
import { watch } from '../store/reducers.js'; | ||
import { TexParser } from 'tex-to-myst'; | ||
|
||
export const makeFileLoader = | ||
(session: ISession, vfile: VFile, baseFile: string) => (filename: string) => { | ||
const dir = path.dirname(baseFile); | ||
const fullFile = path.join(dir, filename); | ||
/** | ||
* Return resolveFile function | ||
* | ||
* If `sourceFile` is format .tex, `relativeFile` will be resolved relative to the | ||
* original baseFile; otherwise, it will be resolved relative to `sourceFile`. | ||
* | ||
* The returned function will resolve the file as described above, and return it if | ||
* it exists or log an error and return undefined otherwise. | ||
*/ | ||
export const makeFileResolver = | ||
(baseFile: string) => (relativeFile: string, sourceFile: string, vfile: VFile) => { | ||
const base = sourceFile.toLowerCase().endsWith('.tex') ? baseFile : sourceFile; | ||
const fullFile = path.resolve(path.dirname(base), relativeFile); | ||
if (!fs.existsSync(fullFile)) { | ||
fileError(vfile, `Include Directive: Could not find "${fullFile}" in "${baseFile}"`, { | ||
ruleId: RuleId.includeContentLoads, | ||
}); | ||
fileError( | ||
vfile, | ||
`Include Directive: Could not find "${relativeFile}" relative to "${base}"`, | ||
{ | ||
ruleId: RuleId.includeContentLoads, | ||
}, | ||
); | ||
return; | ||
} | ||
session.store.dispatch( | ||
watch.actions.addLocalDependency({ | ||
path: baseFile, | ||
dependency: fullFile, | ||
}), | ||
); | ||
return fs.readFileSync(fullFile).toString(); | ||
return fullFile; | ||
}; | ||
|
||
/** | ||
* Return loadFile function | ||
* | ||
* Loaded file is added to original baseFile's dependencies. | ||
*/ | ||
export const makeFileLoader = (session: ISession, baseFile: string) => (fullFile: string) => { | ||
session.store.dispatch( | ||
watch.actions.addLocalDependency({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These I think that's ok - the json "dependencies" are used for loading data from other pages; in the case of 🤔 Maybe if we update There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, the included files are a local convinience, not for how the final documents work. |
||
path: baseFile, | ||
dependency: fullFile, | ||
}), | ||
); | ||
return fs.readFileSync(fullFile).toString(); | ||
}; | ||
|
||
/** | ||
* Return paresContent function | ||
* | ||
* Handles html and tex files separately; all other files are treated as MyST md. | ||
*/ | ||
export const makeContentParser = | ||
(session: ISession) => (filename: string, content: string, vfile: VFile) => { | ||
if (filename.toLowerCase().endsWith('.html')) { | ||
return [{ type: 'html', value: content }]; | ||
} | ||
if (filename.toLowerCase().endsWith('.tex')) { | ||
const subTex = new TexParser(content, vfile); | ||
return subTex.ast.children ?? []; | ||
} | ||
return parseMyst(session, content, filename).children; | ||
}; | ||
|
||
export async function includeFilesTransform( | ||
|
@@ -33,12 +73,13 @@ export async function includeFilesTransform( | |
tree: GenericParent, | ||
vfile: VFile, | ||
) { | ||
const parseContent = (filename: string, content: string) => { | ||
if (filename.toLowerCase().endsWith('.html')) { | ||
return [{ type: 'html', value: content }]; | ||
} | ||
return parseMyst(session, content, filename).children; | ||
}; | ||
const loadFile = makeFileLoader(session, vfile, baseFile); | ||
await includeDirectiveTransform(tree, vfile, { loadFile, parseContent }); | ||
const parseContent = makeContentParser(session); | ||
const loadFile = makeFileLoader(session, baseFile); | ||
const resolveFile = makeFileResolver(baseFile); | ||
await includeDirectiveTransform(tree, vfile, { | ||
resolveFile, | ||
loadFile, | ||
parseContent, | ||
sourceFile: baseFile, | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Page three | ||
|
||
This page includes content from page one: | ||
|
||
```{include} ../one.md | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Page two | ||
|
||
This page includes content from page three: | ||
|
||
```{include} ./three.md | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Page four | ||
|
||
This page includes content from itself: | ||
|
||
```{include} ./four.md | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# See docs at: https://mystmd.org/guide/frontmatter | ||
version: 1 | ||
project: | ||
id: c11009ec-caf7-445c-b498-403bfe2aa61f | ||
keywords: [] | ||
authors: [] | ||
github: https://github.com/executablebooks/mystjs | ||
site: | ||
template: book-theme | ||
nav: [] | ||
actions: | ||
- title: Learn More | ||
url: https://mystmd.org/guide | ||
domains: [] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
export: | ||
- _build/out.typ | ||
--- | ||
|
||
# Page one | ||
|
||
This page includes content from page two: | ||
|
||
```{include} ./dir/two.md | ||
``` | ||
|
||
and content from page three: | ||
|
||
```{include} ./dir/three.md | ||
``` | ||
|
||
and page four: | ||
|
||
```{include} ./four.md | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# See docs at: https://mystmd.org/guide/frontmatter | ||
version: 1 | ||
project: | ||
id: c11009ec-caf7-445c-b498-403bfe2aa61f | ||
keywords: [] | ||
authors: [] | ||
github: https://github.com/executablebooks/mystjs | ||
site: | ||
template: book-theme | ||
nav: [] | ||
actions: | ||
- title: Learn More | ||
url: https://mystmd.org/guide | ||
domains: [] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
export: | ||
- _build/out.typ | ||
--- | ||
|
||
# Page one | ||
|
||
This page includes content from page two: | ||
|
||
```{include} ./two.md | ||
``` | ||
|
||
and content from page three: | ||
|
||
```{include} ./three.md | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Page three | ||
|
||
This page does not include any other pages. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Page two | ||
|
||
This page includes content from page three: | ||
|
||
```{include} ./three.md | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Live reload was not working well for
tex
include content. ThefastProcessFile
function was getting triggered correctly for dependent files, but this transform was never run on the file with\input{...}
(useCache
was stilltrue
).Now, when this function is called in
processMdast
it handlestex
as well, so live reload behaviour matches md processing, regardless ofuseCache
for file loading. (And calling the function here is unnecessary.)