metanorma-document 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +59 -18
- data/data/stylesheets/components/bibliography.css +2 -2
- data/data/stylesheets/components/inline.css +11 -12
- data/docs/html-renderer.adoc +261 -0
- data/lib/metanorma/document/version.rb +1 -1
- data/lib/metanorma/html/base_renderer.rb +180 -219
- data/lib/metanorma/html/drops/admonition_drop.rb +26 -0
- data/lib/metanorma/html/drops/block_element_drop.rb +20 -0
- data/lib/metanorma/html/drops/example_drop.rb +35 -0
- data/lib/metanorma/html/drops/figure_drop.rb +53 -0
- data/lib/metanorma/html/drops/formula_drop.rb +44 -0
- data/lib/metanorma/html/drops/note_drop.rb +32 -0
- data/lib/metanorma/html/drops/sourcecode_drop.rb +37 -0
- data/lib/metanorma/html/drops.rb +7 -0
- data/lib/metanorma/html/iso_renderer.rb +96 -79
- data/lib/metanorma/html/ogc_renderer.rb +5 -5
- data/lib/metanorma/html/standard_renderer.rb +34 -28
- data/lib/metanorma/html/templates/_admonition.html.liquid +4 -0
- data/lib/metanorma/html/templates/_doc_title.html.liquid +1 -1
- data/lib/metanorma/html/templates/_example.html.liquid +3 -0
- data/lib/metanorma/html/templates/_figure.html.liquid +6 -0
- data/lib/metanorma/html/templates/_formula.html.liquid +6 -0
- data/lib/metanorma/html/templates/_iso_doc_title.html.liquid +2 -2
- data/lib/metanorma/html/templates/_note.html.liquid +3 -0
- data/lib/metanorma/html/templates/_sourcecode.html.liquid +4 -0
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a15c5f341f9fbc477322f57c757f26896b1ba2bd3e80a89815ba6942a44c5c6c
|
|
4
|
+
data.tar.gz: 95f0e2d121bc523f38600fe0d5e3e058f7c6b8212b4e5e8b4ab4654d06b10a83
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01eee74753ce15ebf8bd68a3523130d7231eee75c42c2bb3551b67b30fd79e022c8e12858a1aae6d6fc03baf6bbac511b5b5e62db0b054487ee5c1bb62650c2c
|
|
7
|
+
data.tar.gz: 499dc86b2c426e22f107443b8939eead6e2861ab985b9dd427c54a2572531f11ab9c09114b7aa44e9c2fd0dd16eb5dfd36366dbc4f8b2c7c2c713994d6e53aa2
|
data/README.adoc
CHANGED
|
@@ -75,6 +75,34 @@ BaseRenderer # Core HTML rendering, document assembly, CSS/JS p
|
|
|
75
75
|
└── RiboseRenderer # Ribose-specific formatting
|
|
76
76
|
....
|
|
77
77
|
|
|
78
|
+
===== Drop Pattern
|
|
79
|
+
|
|
80
|
+
Block elements (notes, examples, sourcecode, formulas, figures, admonitions) use the Drop pattern:
|
|
81
|
+
|
|
82
|
+
[source,ruby]
|
|
83
|
+
# A Drop captures rendered content via RendererContext, then passes
|
|
84
|
+
# data to a Liquid template. The renderer never emits HTML directly.
|
|
85
|
+
def render_note(note, **_opts)
|
|
86
|
+
drop = Drops::NoteDrop.from_model(note, renderer: renderer_context)
|
|
87
|
+
@output << render_liquid("_note.html.liquid", { "block" => drop })
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
Each Drop class inherits from `BlockElementDrop` and implements `.from_model(model, renderer:)` which:
|
|
91
|
+
|
|
92
|
+
. Captures child content via `renderer.capture_output { ... }`
|
|
93
|
+
. Returns a new Drop instance with pre-rendered HTML strings
|
|
94
|
+
. The Liquid template reads Drop attributes and outputs final HTML
|
|
95
|
+
|
|
96
|
+
`RendererContext` is a facade that exposes only the rendering methods Drops need, maintaining encapsulation.
|
|
97
|
+
|
|
98
|
+
===== Class Name Ownership
|
|
99
|
+
|
|
100
|
+
The HTML renderer owns its class names entirely. **No XML-originated class names appear in the HTML output.**
|
|
101
|
+
|
|
102
|
+
* Block-level classes (`note-block`, `formula`, `figure`, etc.) are assigned by the renderer based on what it's rendering
|
|
103
|
+
* Inline span classes use `SPAN_ROLE_CLASSES` to map XML span roles to HTML-specific names (e.g., `boldtitle` → `title-text`, `citesec` → `xref-section`)
|
|
104
|
+
* The XML's `class_attr` is read as **input only** to determine semantic role, never emitted directly
|
|
105
|
+
|
|
78
106
|
==== Presentation XML
|
|
79
107
|
|
|
80
108
|
The HTML renderer expects **presentation XML** (not source XML). Presentation XML contains `fmt-*` display elements (`fmt-title`, `fmt-xref`, `fmt-link`, `fmt-concept`, `fmt-definition`, `fmt-preferred`, etc.) alongside semantic elements. The renderer prioritizes `fmt-*` elements for rendering, falling back to semantic elements when display elements are absent.
|
|
@@ -107,8 +135,15 @@ HTML structure is defined in `.liquid` templates under `lib/metanorma/html/templ
|
|
|
107
135
|
`_header.html.liquid` :: Sticky header with publisher logos
|
|
108
136
|
`_footer.html.liquid` :: Footer with copyright
|
|
109
137
|
`_cover.html.liquid` :: Cover page layout
|
|
138
|
+
`_iso_cover.html.liquid` :: ISO-specific cover page
|
|
110
139
|
`_footnotes.html.liquid` :: Footnotes section
|
|
111
140
|
`_doc_title.html.liquid` :: Document title rendering
|
|
141
|
+
`_note.html.liquid` :: Note block
|
|
142
|
+
`_example.html.liquid` :: Example block
|
|
143
|
+
`_sourcecode.html.liquid` :: Source code block
|
|
144
|
+
`_formula.html.liquid` :: Formula block
|
|
145
|
+
`_figure.html.liquid` :: Figure block
|
|
146
|
+
`_admonition.html.liquid` :: Admonition block
|
|
112
147
|
|
|
113
148
|
Templates use `Liquid::LocalFileSystem` for partials (prefixed with `_`). The `render_liquid` method handles template caching via `TEMPLATE_CACHE`.
|
|
114
149
|
|
|
@@ -151,26 +186,32 @@ Renderer instance methods:
|
|
|
151
186
|
`theme` :: Returns the `Theme` instance (override in subclasses).
|
|
152
187
|
`render_liquid(template_name, assigns)` :: Renders a Liquid template with caching.
|
|
153
188
|
|
|
154
|
-
|
|
189
|
+
== Document Flavors
|
|
190
|
+
|
|
191
|
+
The gem provides a hierarchy of document flavors:
|
|
192
|
+
|
|
193
|
+
* BasicDocument - Basic document model
|
|
194
|
+
* StandardDocument - Standard document model (extends BasicDocument)
|
|
195
|
+
* IsoDocument - ISO standard document model (extends StandardDocument)
|
|
196
|
+
* IecDocument - IEC standard document model
|
|
197
|
+
* IeeeDocument - IEEE standard document model
|
|
198
|
+
* IetfDocument - IETF standard document model
|
|
199
|
+
* IhoDocument - IHO standard document model
|
|
200
|
+
* OimlDocument - OIML standard document model
|
|
201
|
+
* BipmDocument - BIPM standard document model
|
|
202
|
+
* ItuDocument - ITU standard document model
|
|
203
|
+
* OgcDocument - OGC standard document model
|
|
204
|
+
* CcDocument - CC standard document model
|
|
205
|
+
* RiboseDocument - Ribose standard document model
|
|
206
|
+
|
|
207
|
+
== Supported XML Formats
|
|
155
208
|
|
|
156
|
-
|
|
209
|
+
This library targets the modern Metanorma XML format which uses `<metanorma>` as the root element.
|
|
157
210
|
|
|
158
|
-
|
|
159
|
-
* StandardDocument - Standard document model (extends BasicDocument)
|
|
160
|
-
* IsoDocument - ISO standard document model (extends StandardDocument)
|
|
161
|
-
* IecDocument - IEC standard document model
|
|
162
|
-
* IeeeDocument - IEEE standard document model
|
|
163
|
-
* IetfDocument - IETF standard document model
|
|
164
|
-
* IhoDocument - IHO standard document model
|
|
165
|
-
* OimlDocument - OIML standard document model
|
|
166
|
-
* BipmDocument - BIPM standard document model
|
|
167
|
-
* ItuDocument - ITU standard document model
|
|
168
|
-
* OgcDocument - OGC standard document model
|
|
169
|
-
* CcDocument - CC standard document model
|
|
170
|
-
* RiboseDocument - Ribose standard document model
|
|
211
|
+
Legacy XML formats that use flavor-specific root elements (e.g. `<iso-standard>`, `<m3d-standard>`, `<csa-standard>`, `<un-standard>`) are *not supported*.
|
|
171
212
|
|
|
172
|
-
|
|
213
|
+
== Documentation
|
|
173
214
|
|
|
174
|
-
|
|
215
|
+
Detailed architecture documentation is in the `docs/` directory:
|
|
175
216
|
|
|
176
|
-
|
|
217
|
+
* xref:docs/html-renderer.adoc[HTML Renderer Architecture] — renderer pipeline, drop pattern, class name ownership, template system
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
border-bottom: 1px solid var(--color-border);
|
|
13
13
|
}
|
|
14
14
|
.norm-ref-entry:last-child { border-bottom-color: transparent; }
|
|
15
|
-
.
|
|
16
|
-
.
|
|
15
|
+
.ref-doc-number { font-weight: 500; color: var(--mn-primary); font-family: var(--font-sans); }
|
|
16
|
+
.ref-year { font-weight: 500; }
|
|
17
17
|
.biblio-link { color: inherit; text-decoration: none; }
|
|
18
18
|
.biblio-link:hover { color: var(--mn-primary); text-decoration: underline; }
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* === Inline Elements === */
|
|
2
2
|
.fn-marker { vertical-align: super; font-size: 0.78em; color: var(--mn-primary); font-family: var(--font-sans); }
|
|
3
3
|
.small-caps { font-variant: small-caps; letter-spacing: 0.03em; }
|
|
4
|
-
.obligation { font-style: italic; color: var(--mn-accent); }
|
|
5
|
-
.
|
|
4
|
+
.obligation-text { font-style: italic; color: var(--mn-accent); }
|
|
5
|
+
.title-text { font-weight: 700; }
|
|
6
6
|
|
|
7
7
|
/* Math container — hover dropdown for source formats */
|
|
8
8
|
.math-container { position: relative; display: inline; }
|
|
@@ -30,28 +30,27 @@
|
|
|
30
30
|
border-radius: 2px; transition: background 0.15s, color 0.15s;
|
|
31
31
|
}
|
|
32
32
|
.stem-copy-btn:hover { background: var(--mn-primary-light); color: var(--mn-primary); }
|
|
33
|
-
.
|
|
33
|
+
.subtitle-text { font-weight: 400; }
|
|
34
34
|
|
|
35
|
-
.
|
|
35
|
+
.xref-section, .xref-fig, .xref-table, .xref-app {
|
|
36
36
|
color: var(--mn-primary);
|
|
37
37
|
text-decoration: underline;
|
|
38
38
|
text-decoration-color: rgba(40,56,138,0.2);
|
|
39
39
|
cursor: pointer;
|
|
40
40
|
}
|
|
41
|
-
.
|
|
41
|
+
.xref-section:hover, .xref-fig:hover, .xref-table:hover, .xref-app:hover {
|
|
42
42
|
color: var(--mn-accent);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
.
|
|
46
|
-
.
|
|
47
|
-
.
|
|
48
|
-
.
|
|
49
|
-
.
|
|
50
|
-
.std-year { font-weight: 500; }
|
|
45
|
+
.ref-part-number { font-weight: 500; }
|
|
46
|
+
.ref-title { font-style: italic; }
|
|
47
|
+
.ref-publisher, .ref-publisher-name { font-weight: 500; }
|
|
48
|
+
.ref-doc-number { font-weight: 500; }
|
|
49
|
+
.ref-year { font-weight: 500; }
|
|
51
50
|
.xref-label { font-weight: 600; }
|
|
52
51
|
a.xref { color: var(--mn-primary); text-decoration: none; border-bottom: 1px solid var(--mn-primary-light); }
|
|
53
52
|
a.xref:hover { border-bottom-color: var(--mn-primary); }
|
|
54
|
-
.doc-content a.xref .element-
|
|
53
|
+
.doc-content a.xref .element-label { font-style: italic; }
|
|
55
54
|
|
|
56
55
|
.kbd-hint {
|
|
57
56
|
display: inline-block;
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
= HTML Renderer Architecture
|
|
2
|
+
|
|
3
|
+
== Overview
|
|
4
|
+
|
|
5
|
+
The HTML renderer converts a Metanorma document model (parsed from presentation XML) into a complete, self-contained HTML document. It produces all body content, header, footer, table of contents, CSS theming, and JavaScript interactivity.
|
|
6
|
+
|
|
7
|
+
== Pipeline
|
|
8
|
+
|
|
9
|
+
....
|
|
10
|
+
Generator.generate(doc)
|
|
11
|
+
├── Auto-selects renderer by document class
|
|
12
|
+
├── Renderer.new
|
|
13
|
+
└── renderer.generate_full_document(doc)
|
|
14
|
+
├── Header (publisher logos, document title)
|
|
15
|
+
├── ToC sidebar
|
|
16
|
+
├── Body content (recursive render)
|
|
17
|
+
├── Footnotes
|
|
18
|
+
├── Footer (copyright)
|
|
19
|
+
└── Asset pipeline (inline CSS + JS)
|
|
20
|
+
....
|
|
21
|
+
|
|
22
|
+
== Renderer Hierarchy
|
|
23
|
+
|
|
24
|
+
[source,ruby]
|
|
25
|
+
BaseRenderer # Core HTML rendering, document assembly, CSS/JS pipeline
|
|
26
|
+
└── StandardRenderer # Terms, definitions, annexes, bibliography
|
|
27
|
+
├── IsoRenderer # ISO cover page, copyright, title formatting
|
|
28
|
+
│ ├── IccRenderer # ICC publisher styling
|
|
29
|
+
│ └── PdfaRenderer # PDF Association publisher styling
|
|
30
|
+
├── IecRenderer # IEC-specific formatting
|
|
31
|
+
├── IeeeRenderer # IEEE-specific formatting
|
|
32
|
+
├── IetfRenderer # IETF-specific formatting
|
|
33
|
+
├── IhoRenderer # IHO-specific formatting
|
|
34
|
+
├── ItuRenderer # ITU-specific formatting
|
|
35
|
+
├── OgcRenderer # OGC-specific formatting
|
|
36
|
+
├── OimlRenderer # OIML-specific formatting
|
|
37
|
+
├── BipmRenderer # BIPM-specific formatting
|
|
38
|
+
├── CcRenderer # CC-specific formatting
|
|
39
|
+
└── RiboseRenderer # Ribose-specific formatting
|
|
40
|
+
|
|
41
|
+
=== Renderer Selection
|
|
42
|
+
|
|
43
|
+
The `Generator` uses a two-tier lookup:
|
|
44
|
+
|
|
45
|
+
1. **Taste match**: If the document's publisher matches a registered taste, use that renderer.
|
|
46
|
+
2. **Model class**: Walk the ancestor chain from most specific to `BaseRenderer`.
|
|
47
|
+
|
|
48
|
+
[source,ruby]
|
|
49
|
+
# ICC documents are IsoDocument::Root but use IccRenderer
|
|
50
|
+
Metanorma::Html::Generator.register_taste(
|
|
51
|
+
Metanorma::IsoDocument::Root,
|
|
52
|
+
"ICC",
|
|
53
|
+
Metanorma::Html::IccRenderer
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
== Class Name Ownership
|
|
57
|
+
|
|
58
|
+
The HTML renderer owns its class names entirely. **No XML-originated class names appear in the HTML output.**
|
|
59
|
+
|
|
60
|
+
The XML document model's `class_attr` is read as **input only** to determine semantic role. The renderer maps XML roles to HTML-specific class names via `SPAN_ROLE_CLASSES`:
|
|
61
|
+
|
|
62
|
+
[source,ruby]
|
|
63
|
+
SPAN_ROLE_CLASSES = {
|
|
64
|
+
"boldtitle" => "title-text",
|
|
65
|
+
"citefig" => "xref-fig",
|
|
66
|
+
"citesec" => "xref-section",
|
|
67
|
+
"fmt-element-name" => "element-label",
|
|
68
|
+
"fmt-obligation" => "obligation-text",
|
|
69
|
+
# ...
|
|
70
|
+
}.freeze
|
|
71
|
+
|
|
72
|
+
Block-level classes (`note-block`, `formula`, `figure`, etc.) are assigned by the renderer based on what it's rendering — never carried over from XML.
|
|
73
|
+
|
|
74
|
+
Inline span classes go through `html_class_for_span`:
|
|
75
|
+
|
|
76
|
+
[source,ruby]
|
|
77
|
+
def html_class_for_span(xml_class)
|
|
78
|
+
SPAN_ROLE_CLASSES[xml_class] || "span-#{xml_class}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
Raw XML content (e.g., boilerplate) passes through Nokogiri post-processing that remaps any remaining XML class names.
|
|
82
|
+
|
|
83
|
+
== Drop Pattern
|
|
84
|
+
|
|
85
|
+
Block elements (notes, examples, sourcecode, formulas, figures, admonitions) use the Drop pattern to separate data capture from template rendering.
|
|
86
|
+
|
|
87
|
+
=== How It Works
|
|
88
|
+
|
|
89
|
+
. A `Drop` class captures rendered content via `RendererContext`
|
|
90
|
+
. The Drop passes pre-rendered HTML strings to a Liquid template
|
|
91
|
+
. The template reads Drop attributes and outputs final HTML
|
|
92
|
+
|
|
93
|
+
[source,ruby]
|
|
94
|
+
# In the renderer:
|
|
95
|
+
def render_note(note, **_opts)
|
|
96
|
+
drop = Drops::NoteDrop.from_model(note, renderer: renderer_context)
|
|
97
|
+
@output << render_liquid("_note.html.liquid", { "block" => drop })
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# In the Drop:
|
|
101
|
+
class NoteDrop < BlockElementDrop
|
|
102
|
+
def self.from_model(note, renderer:)
|
|
103
|
+
content_html = renderer.capture_output do
|
|
104
|
+
note.content.each { |para| renderer.render_paragraph(para) }
|
|
105
|
+
end
|
|
106
|
+
new(id: renderer.safe_attr(note, :id),
|
|
107
|
+
label_html: renderer.escape_html(label),
|
|
108
|
+
content_html: content_html,
|
|
109
|
+
css_class: "note-block")
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
=== BlockElementDrop
|
|
114
|
+
|
|
115
|
+
All block drops inherit from `BlockElementDrop`, which provides common attributes:
|
|
116
|
+
|
|
117
|
+
`id` :: HTML element id
|
|
118
|
+
`type` :: Block type identifier
|
|
119
|
+
`label_html` :: Pre-rendered label (e.g., "NOTE", "EXAMPLE 1")
|
|
120
|
+
`content_html` :: Pre-rendered inner content
|
|
121
|
+
`css_class` :: HTML-specific class name
|
|
122
|
+
|
|
123
|
+
=== RendererContext
|
|
124
|
+
|
|
125
|
+
`RendererContext` is a facade inside `BaseRenderer` that exposes only the rendering methods Drops need. Drops call renderer methods through this facade — the renderer's private interface stays encapsulated.
|
|
126
|
+
|
|
127
|
+
[source,ruby]
|
|
128
|
+
class RendererContext
|
|
129
|
+
def safe_attr(obj, method_name)
|
|
130
|
+
def escape_html(text)
|
|
131
|
+
def extract_block_label(block, default)
|
|
132
|
+
def extract_plain_text(node)
|
|
133
|
+
def capture_output(&block)
|
|
134
|
+
def render_paragraph(p)
|
|
135
|
+
def render_mixed_inline(node)
|
|
136
|
+
def render_inline_element(el)
|
|
137
|
+
def render_unordered_list(ul)
|
|
138
|
+
def render_ordered_list(ol)
|
|
139
|
+
def render_definition_list(dl)
|
|
140
|
+
def render_table(table)
|
|
141
|
+
def render_figure(figure)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
== Liquid Templates
|
|
145
|
+
|
|
146
|
+
HTML structure is defined in `.liquid` templates under `lib/metanorma/html/templates/`.
|
|
147
|
+
|
|
148
|
+
[horizontal]
|
|
149
|
+
`document.html.liquid` :: Full document shell (`<html>`, `<head>`, `<body>`)
|
|
150
|
+
`_header.html.liquid` :: Sticky header with publisher logos
|
|
151
|
+
`_footer.html.liquid` :: Footer with copyright
|
|
152
|
+
`_cover.html.liquid` :: Generic cover page layout
|
|
153
|
+
`_iso_cover.html.liquid` :: ISO-specific cover page
|
|
154
|
+
`_iso_doc_title.html.liquid` :: ISO document title rendering
|
|
155
|
+
`_doc_title.html.liquid` :: Generic document title rendering
|
|
156
|
+
`_footnotes.html.liquid` :: Footnotes section
|
|
157
|
+
`_note.html.liquid` :: Note block
|
|
158
|
+
`_example.html.liquid` :: Example block
|
|
159
|
+
`_sourcecode.html.liquid` :: Source code block
|
|
160
|
+
`_formula.html.liquid` :: Formula block
|
|
161
|
+
`_figure.html.liquid` :: Figure block
|
|
162
|
+
`_admonition.html.liquid` :: Admonition block
|
|
163
|
+
|
|
164
|
+
Templates use `Liquid::LocalFileSystem` for partials (prefixed with `_`). The `render_liquid` method handles template caching.
|
|
165
|
+
|
|
166
|
+
=== Template Example
|
|
167
|
+
|
|
168
|
+
`_note.html.liquid`:
|
|
169
|
+
|
|
170
|
+
[source,liquid]
|
|
171
|
+
----
|
|
172
|
+
<div{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
|
|
173
|
+
{% if block.label_html %}
|
|
174
|
+
<p class="note-label"><strong>{{ block.label_html }}</strong></p>
|
|
175
|
+
{% endif %}
|
|
176
|
+
<div class="note-content">
|
|
177
|
+
{{ block.content_html }}
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
----
|
|
181
|
+
|
|
182
|
+
== Theming
|
|
183
|
+
|
|
184
|
+
Each renderer has a `Theme` object controlling colors, typography, and layout. Theme properties are emitted as CSS custom properties (`--mn-primary`, `--font-body`, etc.).
|
|
185
|
+
|
|
186
|
+
[source,ruby]
|
|
187
|
+
class MyRenderer < Metanorma::Html::StandardRenderer
|
|
188
|
+
def theme
|
|
189
|
+
@theme ||= begin
|
|
190
|
+
t = Theme.new
|
|
191
|
+
t.primary = "#1a5276"
|
|
192
|
+
t.accent = "#2e86c1"
|
|
193
|
+
t.font_body = '"Charter", serif'
|
|
194
|
+
t
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
=== Theme Properties
|
|
200
|
+
|
|
201
|
+
[horizontal]
|
|
202
|
+
`primary` :: Primary brand color
|
|
203
|
+
`accent` :: Accent/highlight color
|
|
204
|
+
`gradient` :: Header gradient
|
|
205
|
+
`font_body` :: Body text font stack
|
|
206
|
+
`font_sans` :: Sans-serif font stack
|
|
207
|
+
`font_mono` :: Monospace font stack
|
|
208
|
+
`font_url` :: Google Fonts URL
|
|
209
|
+
`note_border` :: Note block border color
|
|
210
|
+
`note_bg` :: Note block background
|
|
211
|
+
`example_border` :: Example block border color
|
|
212
|
+
`example_bg` :: Example block background
|
|
213
|
+
`admonition_border` :: Admonition border color
|
|
214
|
+
`admonition_bg` :: Admonition background
|
|
215
|
+
`extra_css` :: Additional CSS string appended after defaults
|
|
216
|
+
|
|
217
|
+
== Presentation XML
|
|
218
|
+
|
|
219
|
+
The HTML renderer expects **presentation XML** (not source XML). Presentation XML contains `fmt-*` display elements alongside semantic elements:
|
|
220
|
+
|
|
221
|
+
- `fmt-title` — formatted section/block titles
|
|
222
|
+
- `fmt-xref` — formatted cross-reference text
|
|
223
|
+
- `fmt-link` — formatted link text
|
|
224
|
+
- `fmt-concept` — formatted concept references
|
|
225
|
+
- `fmt-definition` — formatted term definitions
|
|
226
|
+
- `fmt-preferred` — formatted preferred term names
|
|
227
|
+
|
|
228
|
+
The renderer prioritizes `fmt-*` elements for rendering, falling back to semantic elements when display elements are absent.
|
|
229
|
+
|
|
230
|
+
== Asset Pipeline
|
|
231
|
+
|
|
232
|
+
The `AssetPipeline` compiles CSS and JavaScript from modular source files into inline `<style>` and `<script>` blocks for self-contained output.
|
|
233
|
+
|
|
234
|
+
=== CSS
|
|
235
|
+
|
|
236
|
+
[horizontal]
|
|
237
|
+
`data/stylesheets/base/` :: Reset, typography, layout, dark mode, print
|
|
238
|
+
`data/stylesheets/components/` :: Component stylesheets (inline, tables, notes, etc.)
|
|
239
|
+
|
|
240
|
+
=== JavaScript
|
|
241
|
+
|
|
242
|
+
[horizontal]
|
|
243
|
+
`data/javascripts/core/` :: Reader, theme, scroll, navigation, reveal
|
|
244
|
+
`data/javascripts/components/` :: ToC, search, lightbox, code copy, glossary, etc.
|
|
245
|
+
|
|
246
|
+
== Extending
|
|
247
|
+
|
|
248
|
+
To add a new flavor renderer:
|
|
249
|
+
|
|
250
|
+
. Subclass the appropriate base (usually `IsoRenderer` or `StandardRenderer`)
|
|
251
|
+
. Override `theme` with brand colors/fonts
|
|
252
|
+
. Override `publisher_logo_map` with logo filenames
|
|
253
|
+
. Register with the Generator:
|
|
254
|
+
|
|
255
|
+
[source,ruby]
|
|
256
|
+
Metanorma::Html::Generator.register(
|
|
257
|
+
Metanorma::MyDocument::Root,
|
|
258
|
+
Metanorma::Html::MyRenderer
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
To customize how a specific block renders, override the `render_*` method and either emit HTML directly or use the Drop pattern with a new template.
|