@rettangoli/sites 0.2.7 → 1.0.0-rc10

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.
package/README.md CHANGED
@@ -1,133 +1,241 @@
1
1
  # Rettangoli Sites
2
2
 
3
- A static site generator using Markdown and YAML.
3
+ `@rettangoli/sites` is the static-site engine used by Rettangoli. It renders pages from YAML and Markdown into `_site/`, with support for templates, partials, global data, collections, and watch mode.
4
+
5
+ It can run directly with `bunx rtgl`, so a site-level `package.json` is optional.
4
6
 
5
7
  ## Quick Start
6
8
 
7
9
  ```bash
8
- # Create a new site from template
9
- bunx rtgl sites init my-site # Uses 'default' template
10
- bunx rtgl sites init my-site -t default # Explicit template name
10
+ # scaffold
11
+ bunx rtgl sites init my-site
11
12
 
12
- # Install and build
13
+ # run
13
14
  cd my-site
14
- bun install
15
- bun run build
15
+ bunx rtgl sites build
16
16
  ```
17
17
 
18
- ## Project Structure
18
+ ## Package Contract
19
19
 
20
- ```
20
+ ```text
21
21
  my-site/
22
- ├── pages/ # Content (YAML and Markdown)
23
- ├── templates/ # Page layouts
24
- ├── partials/ # Reusable components
25
- ├── data/ # Global data files
26
- ├── static/ # Static assets
27
- ├── sites.config.js # Optional config
28
- ├── package.json
29
- └── _site/ # Generated output
22
+ pages/ # YAML or Markdown pages (with optional frontmatter)
23
+ templates/ # YAML templates
24
+ partials/ # YAML partials
25
+ data/ # Global YAML data
26
+ static/ # Static assets copied to _site/
27
+ sites.config.yaml # Optional site settings
28
+ _site/ # Generated output
30
29
  ```
31
30
 
32
- ## Pages
31
+ ## What It Supports
33
32
 
34
- **YAML page:**
35
- ```yaml
36
- ---
37
- template: base
38
- title: Home
39
- ---
40
- - h1: Welcome
41
- - p: Hello world
42
- ```
33
+ - YAML pages rendered through `jempl` + `yahtml`
34
+ - Markdown pages rendered through `markdown-it` + Shiki (default `rtglMarkdown`)
35
+ - Frontmatter (`template`, `tags`, arbitrary page metadata)
36
+ - Global data (`data/*.yaml`) merged with page frontmatter
37
+ - Collections built from page tags
38
+ - `$if`, `$for`, `$partial`, template functions
39
+ - Static file copying from `static/` to `_site/`
40
+ - Watch mode with local dev server + websocket reload
43
41
 
44
- **Markdown page:**
45
- ```markdown
46
- ---
47
- template: base
48
- title: About
49
- ---
50
- # About Us
42
+ ## Site Config
51
43
 
52
- Content in **markdown**.
44
+ Use `sites.config.yaml` (or `sites.config.yml`) with top-level `markdownit` for supported settings.
45
+ Legacy key `markdown` is still accepted as an alias.
46
+
47
+ ```yaml
48
+ markdownit:
49
+ preset: default
50
+ html: true
51
+ xhtmlOut: false
52
+ linkify: true
53
+ typographer: false
54
+ breaks: false
55
+ langPrefix: language-
56
+ quotes: "\u201c\u201d\u2018\u2019"
57
+ maxNesting: 100
58
+ shiki:
59
+ enabled: true
60
+ theme: slack-dark
61
+ codePreview:
62
+ enabled: false
63
+ showSource: true
64
+ theme: slack-dark
65
+ headingAnchors:
66
+ enabled: true
67
+ slugMode: unicode
68
+ wrap: true
69
+ fallback: section
70
+ build:
71
+ keepMarkdownFiles: false
72
+ imports:
73
+ templates:
74
+ base: https://example.com/templates/base.yaml
75
+ docs: https://example.com/templates/docs.yaml
76
+ partials:
77
+ docs/nav: https://example.com/partials/docs-nav.yaml
53
78
  ```
54
79
 
55
- ## Syntax
80
+ In the default starter template, CDN runtime scripts are controlled via `data/site.yaml`:
56
81
 
57
82
  ```yaml
58
- # Element with class and id
59
- - div.container#main:
60
- - h1: Title
61
-
62
- # Attributes
63
- - 'a href="/about"': About Us
64
- - 'img src="/logo.png" alt="Logo"':
65
-
66
- # Variables
67
- - h1: ${title}
68
- - p: ${site.description}
69
-
70
- # Conditionals
71
- - $if showBanner:
72
- - div.banner: Hello!
73
-
74
- # Loops
75
- - $for item in items:
76
- - li: ${item.name}
77
-
78
- # Partials
79
- - $partial: header
80
- - $partial: card
81
- title: My Card
82
- description: Card content
83
+ assets:
84
+ loadUiFromCdn: true
85
+ loadConstructStyleSheetsPolyfill: true
83
86
  ```
84
87
 
85
- ## Data Files
88
+ Enable `codePreview` if you want fenced blocks like ```` ```html codePreview ```` to render a live preview panel.
89
+ Use `showSource` to show/hide the source pane and `theme` to override the highlight theme for preview blocks.
90
+
91
+ Set `build.keepMarkdownFiles: true` to keep source Markdown files in output in addition to generated HTML.
92
+ Example mappings:
93
+ - `pages/index.md` -> `_site/index.html` and `_site/index.md`
94
+ - `pages/docs/intro.md` -> `_site/docs/intro/index.html` and `_site/docs/intro.md`
86
95
 
87
- `data/site.yaml` available as `${site.name}`, `${site.nav}`, etc.
96
+ `imports` lets you map aliases to remote YAML files (HTTP/HTTPS only). Use aliases in pages/templates:
97
+ - page frontmatter: `template: base` or `template: docs`
98
+ - template/page content: `$partial: docs/nav`
88
99
 
89
- ## Collections
100
+ Imported files are cached on disk under `.rettangoli/sites/imports/{templates|partials}/` (hashed filenames).
101
+ Alias/url/hash mapping is tracked in `.rettangoli/sites/imports/index.yaml`.
102
+ Build is cache-first: if a cached file exists, it is used without a network request.
90
103
 
91
- Tag pages to create collections:
104
+ When an alias exists both remotely and locally, local files under `templates/` and `partials/` override the imported one.
105
+
106
+ If you want to publish a manual `llms.txt`, place it in `static/llms.txt`; it will be copied to `_site/llms.txt`.
107
+
108
+ ## System Frontmatter
109
+
110
+ Use `_bind` to map global data keys into page-local variables.
111
+
112
+ Example:
92
113
 
93
114
  ```yaml
94
- # pages/blog/post.md
95
115
  ---
96
- tags: [blog]
116
+ template: base
117
+ _bind:
118
+ docs: feDocs
97
119
  ---
98
120
  ```
99
121
 
100
- ```yaml
101
- # pages/blog.yaml
102
- - $for post in collections.blog:
103
- - a href="${post.url}": ${post.data.title}
104
- ```
122
+ This resolves `docs` from `data/feDocs.yaml` for that page.
123
+ `_bind` is a system property and is not exposed to templates directly.
105
124
 
106
- ## Configuration
107
-
108
- `sites.config.js`:
109
- ```javascript
110
- export default {
111
- mdRender: customMarkdownRenderer,
112
- functions: {
113
- sortDate: (list) => list.sort((a, b) =>
114
- new Date(b.data.date) - new Date(a.data.date)
115
- )
116
- }
117
- }
118
- ```
125
+ Rules:
126
+
127
+ - `_bind` must be an object
128
+ - each `_bind` value must be a non-empty string
129
+ - each `_bind` value must point to an existing `data/*.yaml` key
130
+ - `_bind` is removed from public frontmatter before rendering/collections
131
+
132
+ Binding order:
133
+
134
+ 1. build page context from `deepMerge(globalData, frontmatterWithoutSystemKeys)`
135
+ 2. apply `_bind` aliases on top (alias wins for that key)
136
+
137
+ ## Pre-published Import Assets
138
+
139
+ `@rettangoli/sites` publishes reusable template/partial YAML assets under `sites/` for URL imports.
119
140
 
120
- ## Scripts
141
+ - Base template: `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/templates/base.yaml`
142
+ - Docs template: `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/templates/docs.yaml`
143
+ - Generic partials: `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/{seo,navbar,mobile-nav,docs-sidebar}.yaml`
144
+ - Legacy docs partial (compat, flat path): `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/docs-mobile-nav.yaml`
145
+
146
+ See `sites/README.md` for full alias examples and required data contract.
147
+
148
+ ## Template Authoring Pattern
149
+
150
+ Keep base templates as shells with minimal logic:
151
+
152
+ - document root (`html`, `head`, `body`)
153
+ - main content slot (`"${content}"`)
154
+ - stable layout containers
155
+
156
+ Put variant-specific behavior and data wiring in partials instead.
157
+ Partials accept explicit parameters via `$partial`, so they are the preferred place for:
158
+
159
+ - section-specific navigation data
160
+ - conditional UI branches
161
+ - reusable interactive blocks
162
+
163
+ This keeps one template reusable across many page variants and avoids duplicated template files.
164
+
165
+ ## Commands
121
166
 
122
167
  ```bash
123
- bun run build # Build site to _site/
124
- bun run watch # Build + watch for changes
125
- bun run serve # Serve _site/
126
- bun run screenshot # Generate page screenshots
168
+ bunx rtgl sites build
169
+ bunx rtgl sites watch
170
+ bunx rtgl sites build --quiet
171
+ bunx rtgl sites watch --quiet
172
+ bunx rtgl sites watch --reload-mode full
173
+ bunx rtgl sites build --root-dir . --output-path dist
174
+ bunx rtgl sites watch --root-dir . --output-path dist --reload-mode full
175
+ ```
176
+
177
+ `--reload-mode body` (default) does fast body replacement; `--reload-mode full` forces full page refresh.
178
+ `--root-dir`/`--output-path` are the preferred option names (`--rootDir`/`--outputPath` remain as legacy aliases).
179
+
180
+ ## Built-in Template Functions
181
+
182
+ Available in YAML templates/pages without extra setup:
183
+
184
+ - `encodeURI(value)`
185
+ - `encodeURIComponent(value)`
186
+ - `decodeURI(value)`
187
+ - `decodeURIComponent(value)`
188
+ - `jsonStringify(value, space = 0)`
189
+ - `formatDate(value, format = "YYYYMMDDHHmmss", useUtc = true)`
190
+ - `now(format = "YYYYMMDDHHmmss", useUtc = true)`
191
+ - `sort(list, key, order = "asc")`
192
+ - `md(content)`
193
+ - `toQueryString(object)`
194
+
195
+ `formatDate` tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`.
196
+ `decodeURI`/`decodeURIComponent` return the original input when decoding fails.
197
+ `sort` supports `order` as `asc` or `desc` (default: `asc`), accepts dot-path keys (for example `data.date`), and returns a new array.
198
+ `md` returns raw rendered HTML from Markdown for template insertion.
199
+
200
+ ## Screenshots
201
+
202
+ `@rettangoli/sites` builds pages; screenshot capture is handled by `@rettangoli/vt`.
203
+
204
+ Use VT against your generated site:
205
+
206
+ 1. Add `vt/specs/*.html` specs (use frontmatter `url` for the page to capture).
207
+ 2. Add `vt` config in `rettangoli.config.yaml`.
208
+ 3. Run `rtgl vt generate`, `rtgl vt report`, and `rtgl vt accept`.
209
+
210
+ Example:
211
+
212
+ ```yaml
213
+ vt:
214
+ path: ./vt
215
+ url: http://127.0.0.1:4173
216
+ service:
217
+ start: bun run preview
218
+ sections:
219
+ - title: pages
220
+ files: .
221
+ ```
222
+
223
+ ```html
224
+ ---
225
+ title: home
226
+ url: /
227
+ ---
228
+ <div></div>
127
229
  ```
128
230
 
129
- ## Templates
231
+ `bun run preview` (or any equivalent local server command) must serve your built site on `vt.url` (for example serving `_site/` on port `4173`).
232
+
233
+ ## Full Architecture And Analysis
130
234
 
131
- Starter templates in `templates/`:
235
+ See `docs/architecture-and-analysis.md` for:
132
236
 
133
- - **default** - Basic site with homepage, blog, and about page
237
+ - End-to-end rendering flow
238
+ - Data/context model used during render
239
+ - URL/output mapping rules
240
+ - Config contract details
241
+ - Full robustness analysis and prioritized improvements
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rettangoli/sites",
3
- "version": "0.2.7",
4
- "description": "Generate static sites using Markdown and YAML. Straightforward, zero-complexity. Complete toolkit for landing pages, blogs, documentation, admin dashboards, and more.git remote add origin git@github.com:yuusoft-org/sitic.git",
3
+ "version": "1.0.0-rc10",
4
+ "description": "Generate static sites using Markdown and YAML for docs, blogs, and marketing sites.",
5
5
  "author": {
6
6
  "name": "Luciano Hanyon Wu",
7
7
  "email": "han4wluc@yuusoft.com"
@@ -14,15 +14,15 @@
14
14
  "files": [
15
15
  "src",
16
16
  "components",
17
- "templates"
17
+ "templates",
18
+ "sites"
18
19
  ],
19
20
  "dependencies": {
21
+ "gray-matter": "^4.0.3",
20
22
  "jempl": "^0.3.1-rc1",
21
23
  "js-yaml": "^4.1.0",
22
24
  "markdown-it": "^14.1.0",
23
- "minimatch": "^10.0.3",
24
- "playwright": "^1.55.0",
25
- "sharp": "^0.34.3",
25
+ "shiki": "^3.13.0",
26
26
  "ws": "^8.18.0",
27
27
  "yahtml": "0.0.4"
28
28
  },
@@ -50,7 +50,7 @@
50
50
  "dashboard"
51
51
  ],
52
52
  "bugs": {
53
- "url": "https://github.com/yuusoft-org/sitic/issues"
53
+ "url": "https://github.com/yuusoft-org/rettangoli/issues"
54
54
  },
55
- "homepage": "https://github.com/yuusoft-org/sitic#readme"
55
+ "homepage": "https://github.com/yuusoft-org/rettangoli/tree/main/packages/rettangoli-sites#readme"
56
56
  }
@@ -0,0 +1,67 @@
1
+ # Rettangoli Sites Import Assets
2
+
3
+ This folder contains publish-only YAML templates/partials for `@rettangoli/sites` URL imports.
4
+ These files are distribution assets, not `@rettangoli/sites` runtime source code.
5
+
6
+ ## Published Templates
7
+
8
+ - Base shell template:
9
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/templates/base.yaml`
10
+ - Docs layout template:
11
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/templates/docs.yaml`
12
+
13
+ ## Published Partials
14
+
15
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/seo.yaml`
16
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/navbar.yaml`
17
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/mobile-nav.yaml`
18
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/docs-sidebar.yaml`
19
+ - `https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/docs-mobile-nav.yaml` (legacy compat partial, flat path)
20
+
21
+ ## Recommended Alias Map
22
+
23
+ ```yaml
24
+ imports:
25
+ templates:
26
+ base: https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/templates/base.yaml
27
+ docs: https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/templates/docs.yaml
28
+ partials:
29
+ seo: https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/seo.yaml
30
+ navbar: https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/navbar.yaml
31
+ mobile-nav: https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/mobile-nav.yaml
32
+ docs-sidebar: https://cdn.jsdelivr.net/npm/@rettangoli/sites@<version>/sites/partials/docs-sidebar.yaml
33
+ ```
34
+
35
+ ## Frontmatter Examples
36
+
37
+ Docs page:
38
+
39
+ ```yaml
40
+ ---
41
+ template: docs
42
+ _bind:
43
+ docs: docs
44
+ title: Getting Started
45
+ sidebarId: getting-started
46
+ ---
47
+ ```
48
+
49
+ Regular page:
50
+
51
+ ```yaml
52
+ ---
53
+ template: base
54
+ title: Home
55
+ ---
56
+ ```
57
+
58
+ ## Docs Template Data Contract
59
+
60
+ The `docs` template expects:
61
+
62
+ - `docs.header` with `label` and `href`
63
+ - `docs.items` (sidebar items)
64
+ - `sidebarId`
65
+ - `title`
66
+
67
+ Use `_bind.docs` to map `docs` from a global data file (for example `data/docs.yaml`).
@@ -0,0 +1,7 @@
1
+ - $if docsLayout && docsLayout.sidebar && docsLayout.sidebar.header && docsLayout.sidebar.items:
2
+ - 'rtgl-view hide md-show w=f d=v bgc=bg':
3
+ - 'rtgl-view pos=fix w=f h=56 bgc=bg av=c ph=lg bwb=xs z=10 style="top:0;left:0"':
4
+ - 'a href="${docsLayout.sidebar.header.href}" style="text-decoration:none;display:contents;color:inherit;"':
5
+ - rtgl-text s=md: ${docsLayout.sidebar.header.label}
6
+ - rtgl-view h=56:
7
+ - rtgl-sidebar selected-item-id=${sidebarId} header="${encodeURIComponent(jsonStringify(docsLayout.sidebar.header))}" items="${encodeURIComponent(jsonStringify(docsLayout.sidebar.items))}" w=f:
@@ -0,0 +1 @@
1
+ - rtgl-sidebar selected-item-id=${sidebarId} header="${encodeURIComponent(jsonStringify(header))}" items="${encodeURIComponent(jsonStringify(items))}":
@@ -0,0 +1,10 @@
1
+ - 'rtgl-view data-mobile-autohide="true" hide md-show pos=fix w=f h=56 bgc=bg av=c ph=lg d=h bwb=xs z=10 style="top:0;left:0"':
2
+ - 'a href="${headerHref}" style="text-decoration:none;display:contents;color:inherit;"':
3
+ - rtgl-text s=md: ${headerLabel}
4
+ - rtgl-view w=1fg:
5
+ - 'rtgl-view id="mobile-menu-btn" data-testid="mobile-menu-btn" cur=pointer aria-label="Open docs navigation" aria-controls="mobile-nav-overlay" aria-expanded="false"':
6
+ - rtgl-svg id="mobile-menu-icon" data-testid="mobile-menu-icon" wh=24 svg=menu cur=pointer:
7
+
8
+ - 'rtgl-view id="mobile-nav-overlay" pos=fix w=f bgc=bg z=20 d=v hidden style="top:56px;left:0;height:calc(100vh - 56px)"':
9
+ - rtgl-view sv w=f h=f:
10
+ - rtgl-sidebar selected-item-id=${sidebarId} header="${encodeURIComponent(jsonStringify(header))}" items="${encodeURIComponent(jsonStringify(items))}" w=f bwr=none hide-header="true":
@@ -0,0 +1,7 @@
1
+ - 'rtgl-view data-mobile-autohide="true" bwb=xs w=f ah=c pos=fix bgc=bg':
2
+ - rtgl-view md-w="100vw" lg-w="768" w="1024" d=h av=c h=64 ph=lg:
3
+ - rtgl-text: ${title}
4
+ - rtgl-view w=1fg:
5
+ - rtgl-view d=h av=c:
6
+ - 'a href="https://github.com/yuusoft-org/rettangoli" target="_blank" style="text-decoration:none;display:contents;color:inherit;"':
7
+ - rtgl-svg.svg-icon wh="32" svg="github":
@@ -0,0 +1,11 @@
1
+ - meta charset="utf-8":
2
+ - meta name="viewport" content="width=device-width,initial-scale=1":
3
+ - title: "${title}"
4
+ - meta name="description" content="${seo.description}":
5
+ - link rel="canonical" href="${site.baseUrl}${page.url}":
6
+ - link rel="icon" type="image/x-icon" href="/public/favicon.png":
7
+
8
+ - meta property="og:title" content="${seo.title}":
9
+ - meta property="og:description" content="${seo.description}":
10
+ - meta property="og:site_name" content="${seo.ogSiteName}":
11
+ - meta property="og:type" content="${seo.ogType}":
@@ -0,0 +1,25 @@
1
+ - html lang="en":
2
+ - head:
3
+ - $partial: seo
4
+ page: ${page}
5
+ seo: ${seo}
6
+ title: ${title}
7
+ - link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@rettangoli/ui@1.0.0-rc13/dist/themes/base.css":
8
+ - link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@rettangoli/ui@1.0.0-rc13/dist/themes/theme-rtgl-slate.css":
9
+ - script src="https://cdn.jsdelivr.net/npm/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.min.js":
10
+ - script src="https://cdn.jsdelivr.net/npm/@rettangoli/ui@1.0.0-rc13/dist/rettangoli-iife-ui.min.js":
11
+ - script src="/public/rtgl-icons.js":
12
+
13
+ - body.dark:
14
+ - rtgl-view:
15
+ - rtgl-view pos="abs" edge="t" ah="c" bgc="bg":
16
+ - $partial: navbar
17
+ title: ${site.navbar.title}
18
+ cta: ${site.navbar.cta}
19
+ - rtgl-view w=f:
20
+ - rtgl-view h="48":
21
+ - rtgl-view w="f" ah="c":
22
+ - rtgl-view w=f ph="lg" pb="lg" ah=c:
23
+ - "${content}"
24
+
25
+ - script src="/public/mobile-nav.js":
@@ -0,0 +1,37 @@
1
+ - html lang="en":
2
+ - head:
3
+ - $partial: seo
4
+ page: ${page}
5
+ seo: ${seo}
6
+ title: ${title}
7
+ - link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@rettangoli/ui@1.0.0-rc13/dist/themes/base.css":
8
+ - link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@rettangoli/ui@1.0.0-rc13/dist/themes/theme-rtgl-slate.css":
9
+ - script src="https://cdn.jsdelivr.net/npm/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.min.js":
10
+ - script src="https://cdn.jsdelivr.net/npm/@rettangoli/ui@1.0.0-rc13/dist/rettangoli-iife-ui.min.js":
11
+ - script src="/public/rtgl-icons.js":
12
+
13
+ - body.dark:
14
+ - $partial: mobile-nav
15
+ headerLabel: ${docs.header.label}
16
+ headerHref: ${docs.header.href}
17
+ header: ${docs.header}
18
+ items: ${docs.items}
19
+ sidebarId: ${sidebarId}
20
+
21
+ - rtgl-view bgc="bg" w="f" d=h:
22
+ - 'rtgl-view md-hide pos=fix h=100vh bgc=bg style="left: 0"':
23
+ - $partial: docs-sidebar
24
+ sidebarId: ${sidebarId}
25
+ header: ${docs.header}
26
+ items: ${docs.items}
27
+ - rtgl-view md-hide xl-show hide w=272:
28
+ - rtgl-view w="1fg" ah=c:
29
+ - rtgl-view pv="lg" lg-w="100vw" w="720" ph="lg" sv id="content-container":
30
+ - rtgl-view hide md-show h=56:
31
+ - rtgl-text s="h1" mb="lg": ${title}
32
+ - "${content}"
33
+ - rtgl-view h=200:
34
+ - 'rtgl-view xl-hide style="position: fixed; right: 0"':
35
+ - rtgl-page-outline id="page-outline" target-id="content-container" scroll-container-id="window" offset-top="80":
36
+
37
+ - script src="/public/mobile-nav.js":