Skip to content

Commit 582e4f2

Browse files
committed
Add baseline asciidoc support
quarto render —to asciidoc asciidoctor-pdf _book/asciidoc/index.adoc open _book/asciidoc/index.pdf
1 parent fee3a3f commit 582e4f2

File tree

8 files changed

+309
-11
lines changed

8 files changed

+309
-11
lines changed

src/format/asciidoc/format-asciidoc.ts

Lines changed: 143 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,158 @@
88
import { Format } from "../../config/types.ts";
99

1010
import { mergeConfigs } from "../../core/config.ts";
11+
import { resolveInputTarget } from "../../project/project-index.ts";
12+
import { projectFormatOutputDir } from "../../project/project-shared.ts";
13+
import { kProjectType, ProjectContext } from "../../project/types.ts";
14+
import {
15+
kBookAppendix,
16+
kBookChapters,
17+
} from "../../project/types/book/book-config.ts";
18+
import {
19+
bookConfig,
20+
isBookIndexPage,
21+
} from "../../project/types/book/book-shared.ts";
22+
import { projectType } from "../../project/types/project-types.ts";
23+
import { join } from "path/mod.ts";
1124

1225
import { plaintextFormat } from "../formats-shared.ts";
26+
import { dirAndStem } from "../../core/path.ts";
27+
import { formatResourcePath } from "../../core/resources.ts";
1328

29+
// Provide the basic asciidoc format
1430
export function asciidocFormat(): Format {
1531
return mergeConfigs(
1632
plaintextFormat("Asciidoc", "adoc"),
1733
{
1834
extensions: {
19-
book: {
20-
multiFile: true,
21-
formatOutputDirectory(_format: Format) {
22-
return "asciidoc";
23-
},
24-
},
35+
book: asciidocBookExtension,
2536
},
2637
},
2738
);
2839
}
40+
41+
// This provide book specific behavior for producing asciidoc books
42+
const asciidocBookExtension = {
43+
multiFile: true,
44+
formatOutputDirectory(_format: Format) {
45+
return "asciidoc";
46+
},
47+
async onMultiFilePrePrender(
48+
isIndex: boolean,
49+
format: Format,
50+
markdown: string,
51+
project: ProjectContext,
52+
) {
53+
if (isIndex) {
54+
// Generate additional markdown to include in the
55+
// index page
56+
const rootPageMd = await bookRootPageMarkdown(project);
57+
const completeMd = markdown + "\n" + rootPageMd;
58+
59+
// Use a book specific template for the book
60+
format.pandoc.template = formatResourcePath(
61+
"asciidoc",
62+
join(
63+
"templates",
64+
"book",
65+
"template.asciidoc",
66+
),
67+
);
68+
69+
return { markdown: completeMd, format };
70+
} else {
71+
// Turn off the TOC on child pages
72+
format.pandoc.toc = false;
73+
}
74+
return { format };
75+
},
76+
async bookPostProcess(_format: Format, _project: ProjectContext) {
77+
},
78+
};
79+
80+
async function bookRootPageMarkdown(project: ProjectContext) {
81+
// Find chapter and appendices
82+
const chapters = await resolveBookInputs(
83+
bookConfig(
84+
kBookChapters,
85+
project.config,
86+
) as string[],
87+
project,
88+
(input: string) => {
89+
// Exclude the index page from the chapter list (since we'll append
90+
// this to the index page contents)
91+
return !isBookIndexPage(input);
92+
},
93+
);
94+
95+
const bookApps = bookConfig(
96+
kBookAppendix,
97+
project.config,
98+
) as string[];
99+
const appendices = bookApps
100+
? await resolveBookInputs(
101+
bookApps,
102+
project,
103+
)
104+
: [];
105+
106+
// Write a book asciidoc file
107+
const fileContents = [
108+
"\n```{=asciidoc}\n\n",
109+
levelOffset("+1"),
110+
include(chapters),
111+
appendix(appendices),
112+
levelOffset("-1"),
113+
"```\n",
114+
];
115+
116+
return fileContents.join("\n");
117+
}
118+
119+
function levelOffset(offset: string) {
120+
return `:leveloffset: ${offset}\n`;
121+
}
122+
123+
function include(chapters: string[]) {
124+
return chapters.map((chap) => {
125+
return `include::${chap}[]\n`;
126+
}).join("\n");
127+
}
128+
129+
function appendix(apps: string[]) {
130+
if (apps.length > 0) {
131+
return apps.map((app) => {
132+
return `[appendix]\ninclude::${app}[]\n`;
133+
}).join("\n");
134+
} else {
135+
return "";
136+
}
137+
}
138+
139+
async function resolveBookInputs(
140+
inputs: string[],
141+
project: ProjectContext,
142+
filter?: (input: string) => boolean,
143+
) {
144+
const outputs: string[] = [];
145+
for (const input of inputs) {
146+
if (filter && !filter(input)) {
147+
continue;
148+
}
149+
const target = await resolveInputTarget(
150+
project,
151+
input,
152+
false,
153+
);
154+
if (target) {
155+
const [dir, stem] = dirAndStem(target?.outputHref);
156+
const outputFile = join(
157+
dir,
158+
`${stem}.adoc`,
159+
);
160+
161+
outputs.push(outputFile);
162+
}
163+
}
164+
return outputs;
165+
}

src/format/html/format-html.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ import {
9797
kNotebookViewStyleNotebook,
9898
notebookViewPostProcessor,
9999
} from "./format-html-notebook.ts";
100-
import { ProjectContext } from "../../project/types.ts";
100+
import { ProjectConfig, ProjectContext } from "../../project/types.ts";
101101

102102
export function htmlFormat(
103103
figwidth: number,

src/project/types/book/book-render.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ import {
7878
import {
7979
bookConfig,
8080
BookConfigKey,
81+
BookExtension,
8182
isBookIndexPage,
8283
isMultiFileBookFormat,
8384
isNumberedChapter,
@@ -93,6 +94,7 @@ import { removePandocTo } from "../../../command/render/flags.ts";
9394
import { resourcePath } from "../../../core/resources.ts";
9495
import { PandocAttr, PartitionedMarkdown } from "../../../core/pandoc/types.ts";
9596
import { stringify } from "encoding/yaml.ts";
97+
import { markdownEngine } from "../../../execute/markdown.ts";
9698

9799
export function bookPandocRenderer(
98100
options: RenderOptions,
@@ -138,7 +140,8 @@ export function bookPandocRenderer(
138140
);
139141

140142
// index file
141-
if (isBookIndexPage(fileRelative)) {
143+
const isIndex = isBookIndexPage(fileRelative);
144+
if (isIndex) {
142145
file.recipe.format = withBookTitleMetadata(
143146
file.recipe.format,
144147
project.config,
@@ -216,6 +219,27 @@ export function bookPandocRenderer(
216219
}
217220
}
218221

222+
// Use the pre-render hook to allow formats to customize
223+
// the format before it is rendered.
224+
if (file.recipe.format.extensions?.book) {
225+
const bookExtension =
226+
(file.recipe.format.extensions?.book as BookExtension);
227+
if (bookExtension.onMultiFilePrePrender) {
228+
const result = await bookExtension.onMultiFilePrePrender(
229+
isIndex,
230+
file.recipe.format,
231+
file.executeResult.markdown,
232+
project,
233+
);
234+
if (result.format) {
235+
file.recipe.format = result.format;
236+
}
237+
if (result.markdown) {
238+
file.executeResult.markdown = result.markdown;
239+
}
240+
}
241+
}
242+
219243
// Since this is a book page, don't include other format links
220244
file.recipe.format.render[kFormatLinks] = false;
221245

@@ -565,6 +589,21 @@ export async function bookPostRender(
565589
incremental: boolean,
566590
outputFiles: ProjectOutputFile[],
567591
) {
592+
const formats: Format[] = [];
593+
outputFiles.forEach((file) => {
594+
if (!formats.includes(file.format)) {
595+
formats.push(file.format);
596+
}
597+
});
598+
for (const format of formats) {
599+
if (format.extensions?.book) {
600+
const bookExt = format.extensions?.book as BookExtension;
601+
if (bookExt.bookPostProcess) {
602+
await bookExt.bookPostProcess(format, context);
603+
}
604+
}
605+
}
606+
568607
// get web output contained in the outputFiles passed to us
569608
const websiteFiles = websiteOutputFiles(outputFiles);
570609
if (websiteFiles.length > 0) {

src/project/types/book/book-shared.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ export interface BookExtension {
5151
project: ProjectContext,
5252
file: RenderedFile,
5353
) => void;
54+
55+
onMultiFilePrePrender?: (
56+
isIndex: boolean,
57+
format: Format,
58+
markdown: string,
59+
project: ProjectContext,
60+
) => Promise<{ format?: Format; markdown?: string }>;
61+
62+
bookPostProcess?: (format: Format, project: ProjectContext) => Promise<void>;
5463
}
5564

5665
export function bookConfig(
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
$if(titleblock)$
2+
= $title$
3+
$if(author)$
4+
$for(author)$$author$$sep$; $endfor$
5+
$endif$
6+
$if(date)$
7+
$date$
8+
$endif$
9+
$if(keywords)$
10+
:keywords: $for(keywords)$$keywords$$sep$, $endfor$
11+
$endif$
12+
$if(lang)$
13+
:lang: $lang$
14+
$endif$
15+
$if(toc)$
16+
:toc:
17+
$endif$
18+
19+
$endif$
20+
$if(abstract)$
21+
[abstract]
22+
== Abstract
23+
$abstract$
24+
25+
$endif$
26+
$for(header-includes)$
27+
$header-includes$
28+
29+
$endfor$
30+
$for(include-before)$
31+
$include-before$
32+
33+
$endfor$
34+
$body$
35+
$for(include-after)$
36+
37+
$include-after$
38+
$endfor$
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
$if(titleblock)$
2+
= $title$
3+
$if(author)$
4+
$for(author)$$author$$sep$; $endfor$
5+
$endif$
6+
$if(date)$
7+
$date$
8+
$endif$
9+
$if(keywords)$
10+
:keywords: $for(keywords)$$keywords$$sep$, $endfor$
11+
$endif$
12+
$if(lang)$
13+
:lang: $lang$
14+
$endif$
15+
$if(toc)$
16+
:toc:
17+
$endif$
18+
19+
$endif$
20+
$if(abstract)$
21+
[abstract]
22+
== Abstract
23+
$abstract$
24+
25+
$endif$
26+
$for(header-includes)$
27+
$header-includes$
28+
29+
$endfor$
30+
$for(include-before)$
31+
$include-before$
32+
33+
$endfor$
34+
$body$
35+
$for(include-after)$
36+
37+
$include-after$
38+
$endfor$
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
$if(titleblock)$
2+
= $title$
3+
$if(author)$
4+
$for(author)$$author$$sep$; $endfor$
5+
$endif$
6+
$if(date)$
7+
$date$
8+
$endif$
9+
$if(keywords)$
10+
:keywords: $for(keywords)$$keywords$$sep$, $endfor$
11+
$endif$
12+
$if(lang)$
13+
:lang: $lang$
14+
$endif$
15+
$if(toc)$
16+
:toc:
17+
$endif$
18+
:doctype: book
19+
20+
$endif$
21+
$if(abstract)$
22+
[abstract]
23+
== Abstract
24+
$abstract$
25+
26+
$endif$
27+
$for(header-includes)$
28+
$header-includes$
29+
30+
$endfor$
31+
$for(include-before)$
32+
$include-before$
33+
34+
$endfor$
35+
$body$
36+
$for(include-after)$
37+
38+
$include-after$
39+
$endfor$

tests/docs/books/simple/_quarto.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,4 @@ format:
1818
theme: cosmo
1919
pdf:
2020
documentclass: scrreprt
21-
22-
23-
21+
asciidoc: default

0 commit comments

Comments
 (0)