-
Notifications
You must be signed in to change notification settings - Fork 44
/
Helium.scala
160 lines (146 loc) · 6.11 KB
/
Helium.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package laika.helium
import laika.helium.config.{ AllFormatsOps, EPUBOps, PDFOps, SiteOps }
import laika.helium.internal.builder.HeliumThemeBuilder
import laika.helium.internal.config.{ EPUBSettings, HeliumDefaults, PDFSettings, SiteSettings }
import laika.helium.internal.generate.MermaidInitializer
import laika.theme.ThemeProvider
/** Configuration API for the Helium theme settings.
*
* Helium can be fully configured with its Scala API and does not require any configuration files.
*
* The entry point for all configuration steps is always `Helium.defaults` to ensure there are sensible defaults
* in place for all the options you omit in your configuration.
*
* For each configuration step you need to choose one of the four selectors,
* either `all` to specify options for all three output formats or `site`, `epub` or `pdf` to select a single format.
* Not all options are available for all formats, but the IDE's context help and the documentation below can guide you.
*
* In the minimal example below we only specify some metadata for all formats as well as the navigation depth
* for EPUB and PDF:
*
* {{{
* val theme = Helium.defaults
* .all.metadata(
* title = Some("Project Name"),
* language = Some("de"),
* )
* .epub.navigationDepth(4)
* .pdf.navigationDepth(4)
* .build
* }}}
*
* Laika also provides convenient constructors for some of the data types used frequently in its theme API.
* You can import `laika.theme.Color._` for specifying colors with `hex("ffaaff")` or `rgb(255, 0, 0)` and
* `laika.ast.LengthUnit._` for specifying sizes with `px(12)` or `pt(9)` or other available units.
*
* The final call to `build` produces a `ThemeProvider` that can be passed to Laika's transformers
* or the `laikaTheme` sbt setting:
*
* Example for sbt plugin:
* {{{
* laikaTheme := theme
* }}}
*
* Example for the library API:
* {{{
* val transformer = Transformer
* .from(Markdown)
* .to(EPUB)
* .parallel[IO]
* .withTheme(theme)
* .build
* }}}
*
* @author Jens Halm
*/
class Helium private[laika] (
private[laika] val siteSettings: SiteSettings,
private[laika] val epubSettings: EPUBSettings,
private[laika] val pdfSettings: PDFSettings,
private[laika] val extensions: Seq[ThemeProvider]
) { self =>
/** Selects the configuration options available for site generation.
*/
object site extends SiteOps {
protected def helium: Helium = self
}
/** Selects the configuration options available for EPUB generation.
*/
object epub extends EPUBOps {
protected def helium: Helium = self
}
/** Selects the configuration options available for PDF generation.
*/
object pdf extends PDFOps {
protected def helium: Helium = self
}
/** Selects the configuration options available for all three output formats.
*
* This means that it only contains the options that exist in all three formats,
* for anything specific to one or two formats you need to use their respective selectors.
*/
object all extends AllFormatsOps {
protected def helium: Helium = self
}
/** Creates a new Helium configuration using this instance as a base and the provided theme as the extension.
*
* The exact mechanics of extending a theme vary depending on the type of functionality supported by themes.
* They are roughly as follows:
*
* - For functionality that is an accumulation of features, for example input files, parser extensions,
* renderer overrides or AST rewrite rules, the effect is accumulative,
* this theme and the extensions will be merged to a single set of features.
*
* - For functionality that is provided by unique instances, for example the template engine or the default template,
* the effect is replacement, where the instance in the extension replaces the corresponding instance in the base,
* if present.
*/
def extendWith(theme: ThemeProvider): Helium =
new Helium(siteSettings, epubSettings, pdfSettings, extensions :+ theme)
/** Creates a new Helium configuration by applying provided extension, using this instance as a base.
*
* In contrast to the `extendWith` overload, this method can be used when an extension does
* not only provide additional resources and/or extension bundles,
* but also simply needs to talk to the Helium configuration API,
* e.g. to configure how/when CSS/JS resources are to be included.
*
* The functionality of this method is essentially a superset of the `extendWith` overload,
* as the provided handler can internally call the other method, too.
*/
def extendWith(ext: Helium => Helium): Helium = ext(this)
/** Builds a theme provider that can be passed to the sbt plugin's `laikaTheme` setting
* or the `withTheme` method of parsers and transformers when using the library API.
*/
def build: ThemeProvider = {
val helium = MermaidInitializer.applyTo(this)
val base: ThemeProvider = new HeliumThemeBuilder(helium)
extensions.foldLeft(base)(_.extendWith(_))
}
}
/** Entry point for the configuration API of the Helium theme.
*
* See the documentation for the `Helium` class for a full introduction.
*/
object Helium {
/** The defaults of the Helium theme which are always used as an entry point for any customizations.
*
* If you do not override any defaults, the generated site and e-books will look like those for the
* Laika manual, including all color and font choices.
*/
val defaults: Helium = HeliumDefaults.instance
}