@rettangoli/sites 0.2.6 → 0.2.7
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 +77 -269
- package/package.json +1 -1
- package/src/cli/index.js +2 -0
- package/src/cli/init.js +38 -0
- package/src/utils/loadSiteConfig.js +1 -1
- package/templates/default/README.md +212 -0
- package/templates/default/data/site.yaml +25 -0
- package/templates/default/package.json +14 -0
- package/templates/default/pages/about.md +16 -0
- package/templates/default/pages/blog/hello-world.md +14 -0
- package/templates/default/pages/blog.yaml +14 -0
- package/templates/default/pages/index.yaml +21 -0
- package/templates/default/partials/footer.yaml +9 -0
- package/templates/default/partials/header.yaml +9 -0
- package/templates/default/sites.config.js +9 -0
- package/templates/default/static/css/theme.css +224 -0
- package/templates/default/templates/base.yaml +18 -0
- package/templates/default/templates/post.yaml +24 -0
package/README.md
CHANGED
|
@@ -1,325 +1,133 @@
|
|
|
1
1
|
# Rettangoli Sites
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A static site generator using Markdown and YAML.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
- 🚀 **Zero Configuration** - Works out of the box with sensible defaults
|
|
8
|
-
- 📝 **Markdown & YAML** - Write content in familiar formats
|
|
9
|
-
- 🎨 **Full-featured** - Templates, partials, collections, global data, nested pages, static assets, and extensible architecture
|
|
10
|
-
|
|
11
|
-
## Installation
|
|
5
|
+
## Quick Start
|
|
12
6
|
|
|
13
7
|
```bash
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
# Install and build
|
|
13
|
+
cd my-site
|
|
14
|
+
bun install
|
|
15
|
+
bun run build
|
|
16
|
+
```
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
## Project Structure
|
|
20
19
|
|
|
21
20
|
```
|
|
22
21
|
my-site/
|
|
23
|
-
├── pages/ #
|
|
24
|
-
├── templates/ #
|
|
25
|
-
├── partials/ # Reusable components
|
|
26
|
-
├── data/ # Global data files
|
|
27
|
-
├── static/ # Static assets
|
|
28
|
-
|
|
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
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
## Pages
|
|
32
33
|
|
|
33
|
-
**
|
|
34
|
+
**YAML page:**
|
|
34
35
|
```yaml
|
|
35
36
|
---
|
|
36
|
-
title: Welcome
|
|
37
37
|
template: base
|
|
38
|
+
title: Home
|
|
38
39
|
---
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### 3. Create a Template
|
|
44
|
-
|
|
45
|
-
**templates/base.yaml**
|
|
46
|
-
```yaml
|
|
47
|
-
- tag: html
|
|
48
|
-
children:
|
|
49
|
-
- tag: head
|
|
50
|
-
children:
|
|
51
|
-
- tag: title
|
|
52
|
-
children: $title
|
|
53
|
-
- tag: body
|
|
54
|
-
children: $content
|
|
40
|
+
- h1: Welcome
|
|
41
|
+
- p: Hello world
|
|
55
42
|
```
|
|
56
43
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npx rtgl sites build
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Your site will be generated in the `_site` directory.
|
|
64
|
-
|
|
65
|
-
## Core Concepts
|
|
66
|
-
|
|
67
|
-
### Pages
|
|
68
|
-
|
|
69
|
-
Pages are the content of your site. They can be either:
|
|
70
|
-
- **YAML files** (`.yaml`) - Structured content with components
|
|
71
|
-
- **Markdown files** (`.md`) - Rich text content with frontmatter
|
|
72
|
-
|
|
73
|
-
Every page can have frontmatter (metadata) at the top:
|
|
74
|
-
|
|
75
|
-
```yaml
|
|
44
|
+
**Markdown page:**
|
|
45
|
+
```markdown
|
|
76
46
|
---
|
|
77
|
-
title: My Page Title
|
|
78
47
|
template: base
|
|
79
|
-
|
|
48
|
+
title: About
|
|
80
49
|
---
|
|
81
|
-
|
|
50
|
+
# About Us
|
|
82
51
|
|
|
83
|
-
|
|
52
|
+
Content in **markdown**.
|
|
53
|
+
```
|
|
84
54
|
|
|
85
|
-
|
|
55
|
+
## Syntax
|
|
86
56
|
|
|
87
|
-
**Example template:**
|
|
88
57
|
```yaml
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
children: $title
|
|
93
|
-
- tag: div
|
|
94
|
-
class: content
|
|
95
|
-
children: $content
|
|
96
|
-
```
|
|
58
|
+
# Element with class and id
|
|
59
|
+
- div.container#main:
|
|
60
|
+
- h1: Title
|
|
97
61
|
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
62
|
+
# Attributes
|
|
63
|
+
- 'a href="/about"': About Us
|
|
64
|
+
- 'img src="/logo.png" alt="Logo"':
|
|
101
65
|
|
|
102
|
-
|
|
66
|
+
# Variables
|
|
67
|
+
- h1: ${title}
|
|
68
|
+
- p: ${site.description}
|
|
103
69
|
|
|
104
|
-
|
|
70
|
+
# Conditionals
|
|
71
|
+
- $if showBanner:
|
|
72
|
+
- div.banner: Hello!
|
|
105
73
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
-
|
|
109
|
-
children:
|
|
110
|
-
- tag: nav
|
|
111
|
-
children:
|
|
112
|
-
- tag: a
|
|
113
|
-
href: /
|
|
114
|
-
children: Home
|
|
115
|
-
- tag: a
|
|
116
|
-
href: /about
|
|
117
|
-
children: About
|
|
118
|
-
```
|
|
74
|
+
# Loops
|
|
75
|
+
- $for item in items:
|
|
76
|
+
- li: ${item.name}
|
|
119
77
|
|
|
120
|
-
|
|
121
|
-
```yaml
|
|
78
|
+
# Partials
|
|
122
79
|
- $partial: header
|
|
123
|
-
-
|
|
80
|
+
- $partial: card
|
|
81
|
+
title: My Card
|
|
82
|
+
description: Card content
|
|
124
83
|
```
|
|
125
84
|
|
|
126
|
-
|
|
85
|
+
## Data Files
|
|
127
86
|
|
|
128
|
-
|
|
87
|
+
`data/site.yaml` → available as `${site.name}`, `${site.nav}`, etc.
|
|
129
88
|
|
|
130
|
-
|
|
131
|
-
```yaml
|
|
132
|
-
name: My Awesome Site
|
|
133
|
-
author: John Doe
|
|
134
|
-
social:
|
|
135
|
-
twitter: johndoe
|
|
136
|
-
github: johndoe
|
|
137
|
-
```
|
|
89
|
+
## Collections
|
|
138
90
|
|
|
139
|
-
|
|
140
|
-
```yaml
|
|
141
|
-
- tag: footer
|
|
142
|
-
children:
|
|
143
|
-
- text: "© 2024 "
|
|
144
|
-
- text: $site.author
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Collections
|
|
148
|
-
|
|
149
|
-
Collections group related content using tags. Any page with a `tags` field in its frontmatter becomes part of a collection.
|
|
150
|
-
|
|
151
|
-
**pages/blog/post-1.md**
|
|
152
|
-
```markdown
|
|
153
|
-
---
|
|
154
|
-
title: My First Post
|
|
155
|
-
tags: blog
|
|
156
|
-
date: 2024-01-15
|
|
157
|
-
---
|
|
158
|
-
# Hello World
|
|
159
|
-
This is my first blog post.
|
|
160
|
-
```
|
|
91
|
+
Tag pages to create collections:
|
|
161
92
|
|
|
162
|
-
**pages/blog-index.yaml**
|
|
163
93
|
```yaml
|
|
94
|
+
# pages/blog/post.md
|
|
164
95
|
---
|
|
165
|
-
|
|
96
|
+
tags: [blog]
|
|
166
97
|
---
|
|
167
|
-
- heading: Recent Posts
|
|
168
|
-
- ul:
|
|
169
|
-
- $for post in collections.blog:
|
|
170
|
-
li:
|
|
171
|
-
- 'a href="${post.url}"':
|
|
172
|
-
- ${post.data.title}
|
|
173
98
|
```
|
|
174
99
|
|
|
175
|
-
### Page Variables
|
|
176
|
-
|
|
177
|
-
Every page has access to a `page.url` variable that contains the page's URL path. All frontmatter variables (like `title`) are available directly:
|
|
178
|
-
|
|
179
|
-
**pages/about.yaml**
|
|
180
|
-
```yaml
|
|
181
|
-
---
|
|
182
|
-
title: About Us
|
|
183
|
-
---
|
|
184
|
-
- paragraph: Current page URL is ${page.url}
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
**templates/base.yaml**
|
|
188
100
|
```yaml
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
-
|
|
192
|
-
children: ${title}
|
|
193
|
-
- tag: link
|
|
194
|
-
rel: canonical
|
|
195
|
-
href: ${page.url}
|
|
101
|
+
# pages/blog.yaml
|
|
102
|
+
- $for post in collections.blog:
|
|
103
|
+
- a href="${post.url}": ${post.data.title}
|
|
196
104
|
```
|
|
197
105
|
|
|
198
|
-
|
|
199
|
-
- `/index.html` → `page.url` = `/`
|
|
200
|
-
- `/about.html` → `page.url` = `/about/`
|
|
201
|
-
- `/docs/guide.html` → `page.url` = `/docs/guide/`
|
|
202
|
-
|
|
203
|
-
This variable is available in both pages and templates, making it useful for navigation, breadcrumbs, and canonical URLs.
|
|
204
|
-
|
|
205
|
-
### Static Files
|
|
206
|
-
|
|
207
|
-
Everything in the `static/` directory is copied directly to the output:
|
|
208
|
-
- `static/css/style.css` → `_site/css/style.css`
|
|
209
|
-
- `static/images/logo.png` → `_site/images/logo.png`
|
|
210
|
-
- `static/app.js` → `_site/app.js`
|
|
211
|
-
|
|
212
|
-
## Advanced Features
|
|
213
|
-
|
|
214
|
-
### Nested Pages
|
|
215
|
-
|
|
216
|
-
Create subdirectories in `pages/` to organize your content:
|
|
217
|
-
- `pages/index.yaml` → `_site/index.html`
|
|
218
|
-
- `pages/about.yaml` → `_site/about.html`
|
|
219
|
-
- `pages/blog/post-1.md` → `_site/blog/post-1.html`
|
|
220
|
-
- `pages/docs/api/reference.yaml` → `_site/docs/api/reference.html`
|
|
221
|
-
|
|
222
|
-
### Markdown Support
|
|
223
|
-
|
|
224
|
-
Markdown files can use frontmatter and templates:
|
|
225
|
-
|
|
226
|
-
```markdown
|
|
227
|
-
---
|
|
228
|
-
title: My Blog Post
|
|
229
|
-
template: blog/post
|
|
230
|
-
tags: [blog, tutorial]
|
|
231
|
-
author: Jane Doe
|
|
232
|
-
---
|
|
233
|
-
# Introduction
|
|
234
|
-
|
|
235
|
-
This is a **markdown** post with *formatting*.
|
|
236
|
-
|
|
237
|
-
## Code Example
|
|
238
|
-
|
|
239
|
-
\`\`\`javascript
|
|
240
|
-
console.log('Hello, World!');
|
|
241
|
-
\`\`\`
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Custom Markdown Renderer
|
|
245
|
-
|
|
246
|
-
Configure a custom markdown renderer in `sites.config.js`:
|
|
106
|
+
## Configuration
|
|
247
107
|
|
|
108
|
+
`sites.config.js`:
|
|
248
109
|
```javascript
|
|
249
|
-
import MarkdownIt from 'markdown-it';
|
|
250
|
-
import hljs from 'highlight.js';
|
|
251
|
-
|
|
252
|
-
const md = MarkdownIt({
|
|
253
|
-
highlight: function (str, lang) {
|
|
254
|
-
if (lang && hljs.getLanguage(lang)) {
|
|
255
|
-
return hljs.highlight(str, { language: lang }).value;
|
|
256
|
-
}
|
|
257
|
-
return '';
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
|
|
261
110
|
export default {
|
|
262
|
-
mdRender:
|
|
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
|
+
}
|
|
263
117
|
}
|
|
264
118
|
```
|
|
265
119
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Rettangoli Sites uses [Jempl](https://github.com/yuusoft-org/jempl) for templating, which provides powerful features for dynamic content including variable replacement, conditionals, loops, and partials.
|
|
120
|
+
## Scripts
|
|
269
121
|
|
|
270
|
-
|
|
122
|
+
```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
|
|
127
|
+
```
|
|
271
128
|
|
|
129
|
+
## Templates
|
|
272
130
|
|
|
273
|
-
|
|
131
|
+
Starter templates in `templates/`:
|
|
274
132
|
|
|
275
|
-
|
|
276
|
-
```
|
|
277
|
-
blog-site/
|
|
278
|
-
├── pages/
|
|
279
|
-
│ ├── index.yaml # Homepage
|
|
280
|
-
│ ├── about.md # About page
|
|
281
|
-
│ └── blog/
|
|
282
|
-
│ ├── index.yaml # Blog listing
|
|
283
|
-
│ ├── 2024-01-15-first-post.md
|
|
284
|
-
│ └── 2024-01-20-second-post.md
|
|
285
|
-
├── templates/
|
|
286
|
-
│ ├── base.yaml # Main layout
|
|
287
|
-
│ └── blog/
|
|
288
|
-
│ ├── post.yaml # Blog post template
|
|
289
|
-
│ └── listing.yaml # Blog list template
|
|
290
|
-
├── partials/
|
|
291
|
-
│ ├── header.yaml
|
|
292
|
-
│ ├── footer.yaml
|
|
293
|
-
│ └── post-card.yaml
|
|
294
|
-
├── data/
|
|
295
|
-
│ └── site.yaml # Site metadata
|
|
296
|
-
└── static/
|
|
297
|
-
├── css/
|
|
298
|
-
│ └── style.css
|
|
299
|
-
└── images/
|
|
300
|
-
└── logo.png
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Documentation Site Structure
|
|
304
|
-
```
|
|
305
|
-
docs-site/
|
|
306
|
-
├── pages/
|
|
307
|
-
│ ├── index.yaml
|
|
308
|
-
│ └── docs/
|
|
309
|
-
│ ├── getting-started.md
|
|
310
|
-
│ ├── api/
|
|
311
|
-
│ │ ├── overview.md
|
|
312
|
-
│ │ └── reference.yaml
|
|
313
|
-
│ └── guides/
|
|
314
|
-
│ ├── installation.md
|
|
315
|
-
│ └── configuration.md
|
|
316
|
-
├── templates/
|
|
317
|
-
│ ├── base.yaml
|
|
318
|
-
│ └── docs.yaml
|
|
319
|
-
├── partials/
|
|
320
|
-
│ ├── nav.yaml
|
|
321
|
-
│ └── sidebar.yaml
|
|
322
|
-
└── static/
|
|
323
|
-
└── css/
|
|
324
|
-
└── docs.css
|
|
325
|
-
```
|
|
133
|
+
- **default** - Basic site with homepage, blog, and about page
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rettangoli/sites",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
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",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Luciano Hanyon Wu",
|
package/src/cli/index.js
CHANGED
package/src/cli/init.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, cpSync, readdirSync } from 'fs';
|
|
2
|
+
import { resolve, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
|
|
7
|
+
export function initSite({ projectName, template = 'default' }) {
|
|
8
|
+
const templatesDir = resolve(__dirname, '../../templates');
|
|
9
|
+
const templatePath = resolve(templatesDir, template);
|
|
10
|
+
const targetPath = resolve(process.cwd(), projectName);
|
|
11
|
+
|
|
12
|
+
// Check if template exists
|
|
13
|
+
if (!existsSync(templatePath)) {
|
|
14
|
+
const available = readdirSync(templatesDir).filter(f =>
|
|
15
|
+
existsSync(resolve(templatesDir, f, 'package.json'))
|
|
16
|
+
);
|
|
17
|
+
console.error(`Template "${template}" not found.`);
|
|
18
|
+
console.error(`Available templates: ${available.join(', ')}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Check if target directory already exists
|
|
23
|
+
if (existsSync(targetPath)) {
|
|
24
|
+
console.error(`Directory "${projectName}" already exists.`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Create target directory and copy template
|
|
29
|
+
mkdirSync(targetPath, { recursive: true });
|
|
30
|
+
cpSync(templatePath, targetPath, { recursive: true });
|
|
31
|
+
|
|
32
|
+
console.log(`Created "${projectName}" from template "${template}"`);
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log('Next steps:');
|
|
35
|
+
console.log(` cd ${projectName}`);
|
|
36
|
+
console.log(' bun install');
|
|
37
|
+
console.log(' bun run build');
|
|
38
|
+
}
|
|
@@ -32,7 +32,7 @@ export async function loadSiteConfig(rootDir, throwOnError = true, bustCache = f
|
|
|
32
32
|
return configExport || {};
|
|
33
33
|
} catch (e) {
|
|
34
34
|
// Only ignore file not found errors
|
|
35
|
-
if (e.code === 'ENOENT') {
|
|
35
|
+
if (e.code === 'ENOENT' || e.code === 'ERR_MODULE_NOT_FOUND') {
|
|
36
36
|
// Config file is optional, return empty config
|
|
37
37
|
return {};
|
|
38
38
|
} else if (throwOnError) {
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# My Site
|
|
2
|
+
|
|
3
|
+
A static site built with [Rettangoli Sites](https://github.com/yuusoft-org/rettangoli) using the [rtgl UI](https://github.com/yuusoft-org/rettangoli/tree/main/packages/rettangoli-ui) framework.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun install
|
|
9
|
+
bun run build
|
|
10
|
+
bun run serve
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Scripts
|
|
14
|
+
|
|
15
|
+
| Script | Description |
|
|
16
|
+
|--------|-------------|
|
|
17
|
+
| `bun run build` | Build site to `_site/` |
|
|
18
|
+
| `bun run watch` | Build and watch for changes |
|
|
19
|
+
| `bun run serve` | Serve `_site/` locally |
|
|
20
|
+
| `bun run screenshot` | Build and capture screenshots |
|
|
21
|
+
|
|
22
|
+
## Project Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
├── pages/ # Content (YAML and Markdown files)
|
|
26
|
+
├── templates/ # Page layouts
|
|
27
|
+
├── partials/ # Reusable components
|
|
28
|
+
├── data/ # Global data files
|
|
29
|
+
├── static/ # Static assets (copied as-is)
|
|
30
|
+
├── sites.config.js # Configuration and custom functions
|
|
31
|
+
└── _site/ # Generated output
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Pages
|
|
35
|
+
|
|
36
|
+
Pages can be **YAML** or **Markdown** files in `pages/`.
|
|
37
|
+
|
|
38
|
+
**YAML page:**
|
|
39
|
+
```yaml
|
|
40
|
+
---
|
|
41
|
+
template: base
|
|
42
|
+
title: Home
|
|
43
|
+
---
|
|
44
|
+
- rtgl-text s="h1": Welcome
|
|
45
|
+
- rtgl-text: Hello world
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Markdown page:**
|
|
49
|
+
```markdown
|
|
50
|
+
---
|
|
51
|
+
template: base
|
|
52
|
+
title: About
|
|
53
|
+
---
|
|
54
|
+
# About Us
|
|
55
|
+
|
|
56
|
+
Content in **markdown**.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Frontmatter
|
|
60
|
+
|
|
61
|
+
| Field | Description |
|
|
62
|
+
|-------|-------------|
|
|
63
|
+
| `template` | Template to use (e.g., `base`, `post`) |
|
|
64
|
+
| `title` | Page title |
|
|
65
|
+
| `tags` | Array of tags for collections (e.g., `[blog]`) |
|
|
66
|
+
|
|
67
|
+
### URL Mapping
|
|
68
|
+
|
|
69
|
+
- `pages/index.yaml` → `/`
|
|
70
|
+
- `pages/about.md` → `/about/`
|
|
71
|
+
- `pages/blog/post.md` → `/blog/post/`
|
|
72
|
+
|
|
73
|
+
## rtgl UI Components
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
# Layout with rtgl-view
|
|
77
|
+
- rtgl-view d="h" g="lg" av="c": # horizontal, gap, align vertical center
|
|
78
|
+
- rtgl-view flex="1": # flex grow
|
|
79
|
+
- rtgl-view w="200" h="100": # fixed width/height
|
|
80
|
+
|
|
81
|
+
# Text with rtgl-text
|
|
82
|
+
- rtgl-text s="h1": Heading 1
|
|
83
|
+
- rtgl-text s="lg" c="mu-fg": Large muted text
|
|
84
|
+
- rtgl-text fw="bold" ta="c": Bold centered
|
|
85
|
+
|
|
86
|
+
# Buttons
|
|
87
|
+
- rtgl-button: Click me
|
|
88
|
+
- rtgl-button v="se": Secondary
|
|
89
|
+
|
|
90
|
+
# Links with hover states
|
|
91
|
+
- 'a href="/about" style="text-decoration: none"':
|
|
92
|
+
- rtgl-text h-c="pr" h-cur="p": Hover link
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Common Attributes
|
|
96
|
+
|
|
97
|
+
| Attr | Description | Values |
|
|
98
|
+
|------|-------------|--------|
|
|
99
|
+
| `w` | Width | `f` (full), number, `100vw` |
|
|
100
|
+
| `h` | Height | number, `100vh` |
|
|
101
|
+
| `d` | Direction | `h` (horizontal), `v` (vertical) |
|
|
102
|
+
| `g` | Gap | `xs`, `sm`, `md`, `lg`, `xl` |
|
|
103
|
+
| `p` | Padding | `xs`, `sm`, `md`, `lg`, `xl` |
|
|
104
|
+
| `m` | Margin | `xs`, `sm`, `md`, `lg`, `xl` |
|
|
105
|
+
| `av` | Align vertical | `s` (start), `c` (center), `e` (end) |
|
|
106
|
+
| `ah` | Align horizontal | `s`, `c`, `e` |
|
|
107
|
+
| `bgc` | Background color | `bg`, `su`, `mu`, `pr` |
|
|
108
|
+
| `c` | Text color | `fg`, `mu-fg`, `pr` |
|
|
109
|
+
| `s` | Text size | `h1`, `h2`, `h3`, `h4`, `lg`, `md`, `sm` |
|
|
110
|
+
| `br` | Border radius | `xs`, `sm`, `md`, `lg`, `xl` |
|
|
111
|
+
| `flex` | Flex grow | `1`, `2`, etc. |
|
|
112
|
+
|
|
113
|
+
### Responsive Prefixes
|
|
114
|
+
|
|
115
|
+
```yaml
|
|
116
|
+
- rtgl-view md-w="100vw" lg-w="768" w="1024":
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
| Prefix | Breakpoint |
|
|
120
|
+
|--------|------------|
|
|
121
|
+
| `md-` | Mobile (< 768px) |
|
|
122
|
+
| `lg-` | Tablet (< 1024px) |
|
|
123
|
+
| (none) | Desktop |
|
|
124
|
+
|
|
125
|
+
### Hover States
|
|
126
|
+
|
|
127
|
+
Prefix with `h-` for hover:
|
|
128
|
+
```yaml
|
|
129
|
+
- rtgl-text h-c="pr" h-cur="p": Hover to highlight
|
|
130
|
+
- rtgl-view h-bgc="suv": Hover background
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Syntax
|
|
134
|
+
|
|
135
|
+
```yaml
|
|
136
|
+
# Variables
|
|
137
|
+
- rtgl-text: ${title}
|
|
138
|
+
- rtgl-text: ${site.name}
|
|
139
|
+
|
|
140
|
+
# Conditionals
|
|
141
|
+
- $if showBanner:
|
|
142
|
+
- rtgl-view bgc="pr" p="lg":
|
|
143
|
+
- rtgl-text: Hello!
|
|
144
|
+
|
|
145
|
+
# Loops
|
|
146
|
+
- $for item in items:
|
|
147
|
+
- rtgl-text: ${item.name}
|
|
148
|
+
|
|
149
|
+
# Partials
|
|
150
|
+
- $partial: header
|
|
151
|
+
- $partial: card
|
|
152
|
+
title: My Card
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Data Files
|
|
156
|
+
|
|
157
|
+
Files in `data/` are available globally. Filename becomes the variable name.
|
|
158
|
+
|
|
159
|
+
`data/site.yaml` → `${site.name}`, `${site.nav}`, etc.
|
|
160
|
+
|
|
161
|
+
## Collections
|
|
162
|
+
|
|
163
|
+
Tag pages to create collections:
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
# pages/blog/post.md
|
|
167
|
+
---
|
|
168
|
+
tags: [blog]
|
|
169
|
+
date: '2024-01-15'
|
|
170
|
+
---
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
# List posts
|
|
175
|
+
- rtgl-view g="md":
|
|
176
|
+
- $for post in collections.blog:
|
|
177
|
+
- 'a href="${post.url}" style="text-decoration: none"':
|
|
178
|
+
- rtgl-view p="lg" bgc="su" br="lg" h-bgc="suv" h-cur="p":
|
|
179
|
+
- rtgl-text s="lg": ${post.data.title}
|
|
180
|
+
- rtgl-text s="sm" c="mu-fg": ${post.data.date}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Collection item properties:
|
|
184
|
+
- `item.url` - Page URL
|
|
185
|
+
- `item.data` - Frontmatter (title, date, etc.)
|
|
186
|
+
- `item.content` - Raw content
|
|
187
|
+
|
|
188
|
+
## Configuration
|
|
189
|
+
|
|
190
|
+
`sites.config.js` for custom functions:
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
export default {
|
|
194
|
+
functions: {
|
|
195
|
+
sortDate: (list) => [...list].sort((a, b) =>
|
|
196
|
+
new Date(b.data.date) - new Date(a.data.date)
|
|
197
|
+
),
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Use in templates:
|
|
203
|
+
```yaml
|
|
204
|
+
- $for post in sortDate(collections.blog):
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Static Files
|
|
208
|
+
|
|
209
|
+
Everything in `static/` is copied to `_site/`:
|
|
210
|
+
|
|
211
|
+
- `static/css/theme.css` → `_site/css/theme.css`
|
|
212
|
+
- `static/images/logo.png` → `_site/images/logo.png`
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: My Site
|
|
2
|
+
|
|
3
|
+
nav:
|
|
4
|
+
- text: Home
|
|
5
|
+
href: /
|
|
6
|
+
- text: Blog
|
|
7
|
+
href: /blog/
|
|
8
|
+
- text: About
|
|
9
|
+
href: /about/
|
|
10
|
+
|
|
11
|
+
footer:
|
|
12
|
+
links:
|
|
13
|
+
- text: Privacy
|
|
14
|
+
href: /privacy/
|
|
15
|
+
- text: Terms
|
|
16
|
+
href: /terms/
|
|
17
|
+
|
|
18
|
+
landing:
|
|
19
|
+
features:
|
|
20
|
+
- title: Simple
|
|
21
|
+
description: Write content in YAML and Markdown
|
|
22
|
+
- title: Fast
|
|
23
|
+
description: Static site generation for optimal performance
|
|
24
|
+
- title: Flexible
|
|
25
|
+
description: Templates, partials, and collections
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-site",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"build": "rtgl sites build",
|
|
6
|
+
"watch": "rtgl sites watch",
|
|
7
|
+
"serve": "serve _site",
|
|
8
|
+
"screenshot": "rtgl sites build -s"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"rtgl": "0.0.37",
|
|
12
|
+
"serve": "latest"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
template: base
|
|
3
|
+
title: Blog
|
|
4
|
+
---
|
|
5
|
+
- rtgl-text s="h1" mb="xl": Blog
|
|
6
|
+
|
|
7
|
+
- rtgl-view g="md" w="f":
|
|
8
|
+
- $for post in collections.blog:
|
|
9
|
+
- 'a href="${post.url}" style="text-decoration: none"':
|
|
10
|
+
- rtgl-view w="f" p="lg" bgc="su" br="lg" h-bgc="suv" h-cur="p":
|
|
11
|
+
- rtgl-view d="h" av="c" w="f":
|
|
12
|
+
- rtgl-text s="lg": ${post.data.title}
|
|
13
|
+
- rtgl-view flex="1":
|
|
14
|
+
- rtgl-text s="sm" c="mu-fg": ${post.data.date}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
template: base
|
|
3
|
+
title: My Site
|
|
4
|
+
---
|
|
5
|
+
- rtgl-view ah="c" pv="xl":
|
|
6
|
+
- rtgl-text s="h1" ta="c": Welcome to My Site
|
|
7
|
+
- rtgl-view h="lg":
|
|
8
|
+
- rtgl-text s="lg" c="mu-fg" ta="c": Built with Rettangoli Sites
|
|
9
|
+
- rtgl-view h="xl":
|
|
10
|
+
- 'a href="/about/" style="text-decoration: none"':
|
|
11
|
+
- rtgl-button: Learn More
|
|
12
|
+
|
|
13
|
+
- rtgl-view h="100":
|
|
14
|
+
|
|
15
|
+
- rtgl-view w="f":
|
|
16
|
+
- rtgl-text s="h2" mb="lg": Features
|
|
17
|
+
- rtgl-view d="h" g="lg" w="f" md-d="v":
|
|
18
|
+
- $for feature in site.landing.features:
|
|
19
|
+
- rtgl-view flex="1" p="lg" bgc="su" br="lg":
|
|
20
|
+
- rtgl-text s="h4" mb="sm": ${feature.title}
|
|
21
|
+
- rtgl-text c="mu-fg": ${feature.description}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
- rtgl-view h="1" w="f" bgc="bo":
|
|
2
|
+
- rtgl-view md-w="100vw" lg-w="768" w="1024" ph="lg" pv="xl":
|
|
3
|
+
- rtgl-view d="h" w="f" av="c":
|
|
4
|
+
- rtgl-text s="sm" c="mu-fg": © 2024 ${site.name}
|
|
5
|
+
- rtgl-view flex="1":
|
|
6
|
+
- rtgl-view d="h" g="lg":
|
|
7
|
+
- $for link in site.footer.links:
|
|
8
|
+
- 'a href="${link.href}" style="text-decoration: none"':
|
|
9
|
+
- rtgl-text s="sm" c="mu-fg" h-c="fg" h-cur="p": ${link.text}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
- rtgl-view 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
|
+
- 'a href="/" style="text-decoration: none"':
|
|
4
|
+
- rtgl-text s="lg" fw="bold": ${site.name}
|
|
5
|
+
- rtgl-view flex="1":
|
|
6
|
+
- rtgl-view d="h" g="lg" av="c":
|
|
7
|
+
- $for link in site.nav:
|
|
8
|
+
- 'a href="${link.href}" style="text-decoration: none"':
|
|
9
|
+
- rtgl-text c="mu-fg" h-c="fg" h-cur="p": ${link.text}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
html {
|
|
2
|
+
margin: 0;
|
|
3
|
+
-ms-overflow-style: none;
|
|
4
|
+
scrollbar-width: none;
|
|
5
|
+
width: 100%;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
html::-webkit-scrollbar {
|
|
9
|
+
display: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
body::-webkit-scrollbar {
|
|
13
|
+
display: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
* {
|
|
17
|
+
scrollbar-color: var(--input) transparent;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
-ms-overflow-style: none;
|
|
22
|
+
scrollbar-width: none;
|
|
23
|
+
height: 100%;
|
|
24
|
+
width: 100%;
|
|
25
|
+
margin: 0;
|
|
26
|
+
font-family: system-ui, -apple-system, "Helvetica Neue", sans-serif;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
background-color: var(--background);
|
|
30
|
+
color: var(--foreground);
|
|
31
|
+
overscroll-behavior: none;
|
|
32
|
+
overflow: auto;
|
|
33
|
+
-webkit-overflow-scrolling: touch;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
a {
|
|
37
|
+
color: inherit;
|
|
38
|
+
text-decoration: underline;
|
|
39
|
+
text-decoration-thickness: 1px;
|
|
40
|
+
text-underline-offset: 4px;
|
|
41
|
+
text-decoration-color: var(--muted-foreground);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
a:hover {
|
|
45
|
+
text-decoration-color: var(--foreground);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
::selection {
|
|
49
|
+
background-color: var(--accent);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:root {
|
|
53
|
+
--width-stretch: 100%;
|
|
54
|
+
|
|
55
|
+
--spacing-xs: 2px;
|
|
56
|
+
--spacing-sm: 4px;
|
|
57
|
+
--spacing-md: 8px;
|
|
58
|
+
--spacing-lg: 16px;
|
|
59
|
+
--spacing-xl: 32px;
|
|
60
|
+
|
|
61
|
+
--border-radius-xs: 1px;
|
|
62
|
+
--border-radius-sm: 2px;
|
|
63
|
+
--border-radius-md: 4px;
|
|
64
|
+
--border-radius-lg: 8px;
|
|
65
|
+
--border-radius-xl: 16px;
|
|
66
|
+
--border-radius-f: 50%;
|
|
67
|
+
|
|
68
|
+
--border-width-xs: 1px;
|
|
69
|
+
--border-width-sm: 2px;
|
|
70
|
+
--border-width-md: 4px;
|
|
71
|
+
--border-width-lg: 8px;
|
|
72
|
+
--border-width-xl: 16px;
|
|
73
|
+
|
|
74
|
+
--shadow-sm: 0px 2px 6px rgba(0, 0, 0, .45);
|
|
75
|
+
--shadow-md: 0px 5px 12px rgba(0, 0, 0, .45);
|
|
76
|
+
--shadow-lg: 0px 10px 24px rgba(0, 0, 0, .45);
|
|
77
|
+
|
|
78
|
+
--h1-font-size: 3rem;
|
|
79
|
+
--h1-font-weight: 600;
|
|
80
|
+
--h1-line-height: 1;
|
|
81
|
+
--h1-letter-spacing: -.025em;
|
|
82
|
+
|
|
83
|
+
--h2-font-size: 1.875rem;
|
|
84
|
+
--h2-font-weight: 500;
|
|
85
|
+
--h2-line-height: 2.25rem;
|
|
86
|
+
--h2-letter-spacing: -.025em;
|
|
87
|
+
|
|
88
|
+
--h3-font-size: 1.5rem;
|
|
89
|
+
--h3-font-weight: 600;
|
|
90
|
+
--h3-line-height: 2rem;
|
|
91
|
+
--h3-letter-spacing: -.025em;
|
|
92
|
+
|
|
93
|
+
--h4-font-size: 1.25rem;
|
|
94
|
+
--h4-font-weight: 600;
|
|
95
|
+
--h4-line-height: 1.75rem;
|
|
96
|
+
--h4-letter-spacing: -.025em;
|
|
97
|
+
|
|
98
|
+
--lg-font-size: 1.125rem;
|
|
99
|
+
--lg-font-weight: 400;
|
|
100
|
+
--lg-line-height: 1.75rem;
|
|
101
|
+
--lg-letter-spacing: normal;
|
|
102
|
+
|
|
103
|
+
--md-font-size: 1rem;
|
|
104
|
+
--md-font-weight: normal;
|
|
105
|
+
--md-line-height: 1.625rem;
|
|
106
|
+
--md-letter-spacing: normal;
|
|
107
|
+
|
|
108
|
+
--sm-font-size: .875rem;
|
|
109
|
+
--sm-font-weight: 400;
|
|
110
|
+
--sm-line-height: 1.25;
|
|
111
|
+
--sm-letter-spacing: normal;
|
|
112
|
+
|
|
113
|
+
--xs-font-size: .75rem;
|
|
114
|
+
--xs-font-weight: normal;
|
|
115
|
+
--xs-line-height: 1;
|
|
116
|
+
--xs-letter-spacing: normal;
|
|
117
|
+
|
|
118
|
+
--primary: oklch(0.205 0 0);
|
|
119
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
120
|
+
--secondary: oklch(0.97 0 0);
|
|
121
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
122
|
+
--background: oklch(1 0 0);
|
|
123
|
+
--foreground: oklch(0.145 0 0);
|
|
124
|
+
--muted: oklch(0.97 0 0);
|
|
125
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
126
|
+
--accent: oklch(0.95 0 0);
|
|
127
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
128
|
+
--border: oklch(0.922 0 0);
|
|
129
|
+
--input: oklch(0.922 0 0);
|
|
130
|
+
--ring: oklch(0.708 0 0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.dark {
|
|
134
|
+
--background: oklch(0.145 0 0);
|
|
135
|
+
--foreground: oklch(0.985 0 0);
|
|
136
|
+
--primary: oklch(0.922 0 0);
|
|
137
|
+
--primary-foreground: oklch(0.305 0 0);
|
|
138
|
+
--secondary: oklch(0.269 0 0);
|
|
139
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
140
|
+
--muted: oklch(0.269 0 0);
|
|
141
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
142
|
+
--accent: oklch(0.371 0 0);
|
|
143
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
144
|
+
--border: oklch(1 0 0 / 10%);
|
|
145
|
+
--input: oklch(1 0 0 / 15%);
|
|
146
|
+
--ring: oklch(0.556 0 0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
h1 {
|
|
150
|
+
font-size: var(--h1-font-size);
|
|
151
|
+
font-weight: var(--h1-font-weight);
|
|
152
|
+
line-height: var(--h1-line-height);
|
|
153
|
+
letter-spacing: var(--h1-letter-spacing);
|
|
154
|
+
margin-top: 32px;
|
|
155
|
+
margin-bottom: 16px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
h2 {
|
|
159
|
+
font-size: var(--h2-font-size);
|
|
160
|
+
font-weight: var(--h2-font-weight);
|
|
161
|
+
line-height: var(--h2-line-height);
|
|
162
|
+
letter-spacing: var(--h2-letter-spacing);
|
|
163
|
+
margin-top: 32px;
|
|
164
|
+
margin-bottom: 16px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
h3 {
|
|
168
|
+
font-size: var(--h3-font-size);
|
|
169
|
+
font-weight: var(--h3-font-weight);
|
|
170
|
+
line-height: var(--h3-line-height);
|
|
171
|
+
letter-spacing: var(--h3-letter-spacing);
|
|
172
|
+
margin-top: 32px;
|
|
173
|
+
margin-bottom: 16px;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
h4 {
|
|
177
|
+
font-size: var(--h4-font-size);
|
|
178
|
+
font-weight: var(--h4-font-weight);
|
|
179
|
+
line-height: var(--h4-line-height);
|
|
180
|
+
letter-spacing: var(--h4-letter-spacing);
|
|
181
|
+
margin-top: 32px;
|
|
182
|
+
margin-bottom: 16px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
p {
|
|
186
|
+
font-size: var(--md-font-size);
|
|
187
|
+
font-weight: var(--md-font-weight);
|
|
188
|
+
line-height: var(--md-line-height);
|
|
189
|
+
letter-spacing: var(--md-letter-spacing);
|
|
190
|
+
margin-top: 0;
|
|
191
|
+
margin-bottom: 16px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
ul {
|
|
195
|
+
margin-top: 0;
|
|
196
|
+
margin-bottom: 16px;
|
|
197
|
+
margin-left: 4px;
|
|
198
|
+
padding-left: 16px;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
li {
|
|
202
|
+
margin-bottom: 8px;
|
|
203
|
+
font-size: var(--md-font-size);
|
|
204
|
+
font-weight: var(--md-font-weight);
|
|
205
|
+
line-height: var(--md-line-height);
|
|
206
|
+
letter-spacing: var(--md-letter-spacing);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
blockquote {
|
|
210
|
+
margin-top: 0;
|
|
211
|
+
margin-bottom: 16px;
|
|
212
|
+
margin-left: 0;
|
|
213
|
+
margin-right: 0;
|
|
214
|
+
padding-left: 16px;
|
|
215
|
+
border-left: 2px solid var(--foreground);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
blockquote > p {
|
|
219
|
+
margin-bottom: 0px;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
|
|
223
|
+
scroll-margin-top: 80px;
|
|
224
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
- html lang="en":
|
|
2
|
+
- head:
|
|
3
|
+
- meta charset="utf-8":
|
|
4
|
+
- meta name="viewport" content="width=device-width,initial-scale=1":
|
|
5
|
+
- title: ${title} - ${site.name}
|
|
6
|
+
- link rel="stylesheet" href="/css/theme.css":
|
|
7
|
+
- script src="https://cdn.jsdelivr.net/npm/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.min.js":
|
|
8
|
+
- script src="https://cdn.jsdelivr.net/npm/@rettangoli/ui@0.1.31/dist/rettangoli-iife-ui.min.js":
|
|
9
|
+
- body.dark:
|
|
10
|
+
- rtgl-view w="f":
|
|
11
|
+
- rtgl-view h="64":
|
|
12
|
+
- rtgl-view w="f" ah="c":
|
|
13
|
+
- rtgl-view w="f" ph="lg" pb="lg" ah="c" md-w="100vw" lg-w="768" w="1024":
|
|
14
|
+
- "${content}"
|
|
15
|
+
- rtgl-view h="30vh":
|
|
16
|
+
- $partial: footer
|
|
17
|
+
- rtgl-view pos="abs" cor="top" ah="c" bgc="bg":
|
|
18
|
+
- $partial: header
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
- html lang="en":
|
|
2
|
+
- head:
|
|
3
|
+
- meta charset="utf-8":
|
|
4
|
+
- meta name="viewport" content="width=device-width,initial-scale=1":
|
|
5
|
+
- title: ${title} - ${site.name}
|
|
6
|
+
- link rel="stylesheet" href="/css/theme.css":
|
|
7
|
+
- script src="https://cdn.jsdelivr.net/npm/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.min.js":
|
|
8
|
+
- script src="https://cdn.jsdelivr.net/npm/@rettangoli/ui@0.1.31/dist/rettangoli-iife-ui.min.js":
|
|
9
|
+
- body.dark:
|
|
10
|
+
- rtgl-view h="64":
|
|
11
|
+
- rtgl-view w="f" ah="c":
|
|
12
|
+
- rtgl-view d="h" g="xl" pb="lg" md-w="100vw" lg-w="768" w="1024" ph="lg":
|
|
13
|
+
- rtgl-view id="content-container" lg-w="100%" w="624":
|
|
14
|
+
- rtgl-text s="sm" c="mu-fg" mb="md": ${date}
|
|
15
|
+
- "${content}"
|
|
16
|
+
- rtgl-view h="xl":
|
|
17
|
+
- 'a href="/blog/" style="text-decoration: none"':
|
|
18
|
+
- rtgl-text c="pr" h-cur="p": ← Back to Blog
|
|
19
|
+
- 'rtgl-view lg-hide flex="1" style="position: sticky; top: 64px;"':
|
|
20
|
+
- rtgl-page-outline id="page-outline" target-id="content-container":
|
|
21
|
+
- rtgl-view h="30vh":
|
|
22
|
+
- $partial: footer
|
|
23
|
+
- rtgl-view pos="abs" cor="top" ah="c" bgc="bg":
|
|
24
|
+
- $partial: header
|