@jsnchn/buntastic 0.1.0 → 0.3.0
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/AGENTS.md +4 -4
- package/README.md +21 -1
- package/package.json +1 -1
- package/src/index.ts +14 -15
- package/src/layouts/base.html +0 -1
- package/src/layouts/post.html +2 -1
package/AGENTS.md
CHANGED
|
@@ -64,7 +64,6 @@ draft: false # Set true to exclude from production build
|
|
|
64
64
|
| `{{ description }}` | Page description |
|
|
65
65
|
| `{{ url }}` | Current page URL |
|
|
66
66
|
| `{{ collection }}` | Array of posts in current folder (for index pages) |
|
|
67
|
-
| `{{ head \| safe }}` | Head content from child layouts (appended to parent) |
|
|
68
67
|
|
|
69
68
|
## Layout System
|
|
70
69
|
|
|
@@ -85,22 +84,23 @@ The `{{ content | safe }}` placeholder is where child content gets injected.
|
|
|
85
84
|
|
|
86
85
|
## Head Block
|
|
87
86
|
|
|
88
|
-
Layouts can inject content into the `<head>` section using `
|
|
87
|
+
Layouts can inject content into the `<head>` section using `[head]...[/head]` blocks. Content inside these blocks is automatically merged and appended to the `<head>` element in the parent layout:
|
|
89
88
|
|
|
90
89
|
```html
|
|
91
90
|
<!-- layouts/post.html -->
|
|
92
91
|
---
|
|
93
92
|
extends: base.html
|
|
94
93
|
---
|
|
94
|
+
[head]
|
|
95
95
|
<link rel="stylesheet" href="/post.css">
|
|
96
|
-
|
|
96
|
+
[/head]
|
|
97
97
|
<article class="post">
|
|
98
98
|
<h1>{{ title }}</h1>
|
|
99
99
|
{{ content | safe }}
|
|
100
100
|
</article>
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
Head content from child layouts is appended to parent head content.
|
|
104
104
|
|
|
105
105
|
## Development
|
|
106
106
|
|
package/README.md
CHANGED
|
@@ -164,7 +164,7 @@ extends: base.html
|
|
|
164
164
|
| Variable | Description |
|
|
165
165
|
|----------|-------------|
|
|
166
166
|
| `{{ title }}` | Page title |
|
|
167
|
-
| `{{ content
|
|
167
|
+
| `{{ content | safe }}` | Rendered markdown HTML |
|
|
168
168
|
| `{{ date }}` | Page date |
|
|
169
169
|
| `{{ description }}` | Meta description |
|
|
170
170
|
| `{{ url }}` | Current page URL |
|
|
@@ -187,6 +187,26 @@ Use `extends:` to build on top of other layouts:
|
|
|
187
187
|
</html>
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
+
### Head Block
|
|
191
|
+
|
|
192
|
+
Layouts can inject content into the `<head>` section using `[head]...[/head]` blocks. Content inside these blocks is automatically merged and appended to the `<head>` element in the parent layout:
|
|
193
|
+
|
|
194
|
+
```html
|
|
195
|
+
<!-- layouts/post.html -->
|
|
196
|
+
---
|
|
197
|
+
extends: base.html
|
|
198
|
+
---
|
|
199
|
+
[head]
|
|
200
|
+
<link rel="stylesheet" href="/post.css">
|
|
201
|
+
[/head]
|
|
202
|
+
<article class="post">
|
|
203
|
+
<h1>{{ title }}</h1>
|
|
204
|
+
{{ content | safe }}
|
|
205
|
+
</article>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Head content from child layouts is appended to parent head content.
|
|
209
|
+
|
|
190
210
|
## Collections
|
|
191
211
|
|
|
192
212
|
For folder index pages (e.g., `content/posts/index.md`), use `{{ collection }}` to list all pages in that folder:
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -101,25 +101,25 @@ async function resolveLayout(frontmatter: Frontmatter): Promise<{ template: stri
|
|
|
101
101
|
const extendsMatch = template.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
102
102
|
|
|
103
103
|
let childHead = "";
|
|
104
|
-
let childBody =
|
|
104
|
+
let childBody = "";
|
|
105
105
|
|
|
106
106
|
if (extendsMatch) {
|
|
107
107
|
const parentLayout = extendsMatch[1].match(/extends:\s*(\w+)/);
|
|
108
108
|
if (parentLayout) {
|
|
109
|
-
|
|
110
|
-
const headPlaceholderMatch = childBody.match(/(\{\{\s*head\s*\|\s*safe\s*\}\})/);
|
|
109
|
+
const childContent = extendsMatch[2];
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const afterPlaceholder = childBody.substring(placeholderIdx + headPlaceholderMatch[0].length).trim();
|
|
116
|
-
childHead = beforePlaceholder;
|
|
117
|
-
childBody = afterPlaceholder;
|
|
111
|
+
const headMatch = childContent.match(/\[head\]([\s\S]*?)\[\/head\]/);
|
|
112
|
+
if (headMatch) {
|
|
113
|
+
childHead = headMatch[1].trim();
|
|
118
114
|
}
|
|
115
|
+
|
|
116
|
+
childBody = childContent;
|
|
119
117
|
|
|
120
118
|
const parentResult = await resolveLayout({ extends: parentLayout[1] } as Frontmatter);
|
|
121
119
|
|
|
122
|
-
let contentReplaced = parentResult.template
|
|
120
|
+
let contentReplaced = parentResult.template;
|
|
121
|
+
|
|
122
|
+
contentReplaced = contentReplaced.replace(
|
|
123
123
|
/\{\{\s*content\s*\|\s*safe\s*\}\}/g,
|
|
124
124
|
childBody
|
|
125
125
|
);
|
|
@@ -127,8 +127,8 @@ async function resolveLayout(frontmatter: Frontmatter): Promise<{ template: stri
|
|
|
127
127
|
const mergedHead = parentResult.head + (childHead ? "\n" + childHead : "");
|
|
128
128
|
|
|
129
129
|
contentReplaced = contentReplaced.replace(
|
|
130
|
-
|
|
131
|
-
mergedHead
|
|
130
|
+
/<\/head>/i,
|
|
131
|
+
`\n${mergedHead}\n</head>`
|
|
132
132
|
);
|
|
133
133
|
|
|
134
134
|
return { template: contentReplaced, head: mergedHead };
|
|
@@ -137,9 +137,8 @@ async function resolveLayout(frontmatter: Frontmatter): Promise<{ template: stri
|
|
|
137
137
|
|
|
138
138
|
let ownHead = "";
|
|
139
139
|
if (extendsMatch) {
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
ownHead = headMatch ? headMatch[0] : "";
|
|
140
|
+
const headMatch = extendsMatch[2].match(/\[head\]([\s\S]*?)\[\/head\]/);
|
|
141
|
+
ownHead = headMatch ? headMatch[1].trim() : "";
|
|
143
142
|
}
|
|
144
143
|
|
|
145
144
|
return { template, head: ownHead };
|
package/src/layouts/base.html
CHANGED