uniweb 0.8.26 → 0.8.28
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/package.json +6 -6
- package/partials/agents.md +42 -8
- package/src/index.js +22 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.28",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"js-yaml": "^4.1.0",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.0.0",
|
|
44
|
-
"@uniweb/core": "0.5.
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
44
|
+
"@uniweb/core": "0.5.17",
|
|
45
|
+
"@uniweb/kit": "0.7.18",
|
|
46
|
+
"@uniweb/runtime": "0.6.23"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@uniweb/build": "0.8.
|
|
49
|
+
"@uniweb/build": "0.8.27",
|
|
50
50
|
"@uniweb/content-reader": "1.1.4",
|
|
51
|
-
"@uniweb/semantic-parser": "1.1.
|
|
51
|
+
"@uniweb/semantic-parser": "1.1.8"
|
|
52
52
|
},
|
|
53
53
|
"peerDependenciesMeta": {
|
|
54
54
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -138,6 +138,15 @@ The decision rule: **would a content author need to change this?** Yes → it be
|
|
|
138
138
|
|
|
139
139
|
Start with the content, not the component. Write the markdown a content author would naturally write, check what content shape the parser produces, *then* build the component to receive it.
|
|
140
140
|
|
|
141
|
+
**Markdown order ≠ rendering order.** The parser extracts content into a flat structure (`title`, `icons`, `images`, `paragraphs`). The component decides how to arrange these visually. Don't write markdown in visual order — write it in semantic order. Start sections with the heading, then add icons, images, and text in any order:
|
|
142
|
+
|
|
143
|
+
```markdown
|
|
144
|
+
# Site Name ← title — always start with the heading
|
|
145
|
+
 ← icon — component controls where this renders
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Placing content *before* the first heading changes the parse: headings after body content become items, not the section title. This is by design — it's how repeating content groups (cards, features) are created.
|
|
149
|
+
|
|
141
150
|
### Section Format
|
|
142
151
|
|
|
143
152
|
Each `.md` file is a section. Frontmatter on top, content below:
|
|
@@ -173,7 +182,7 @@ content = {
|
|
|
173
182
|
pretitle: '', // Heading before main title (auto-detected)
|
|
174
183
|
subtitle: '', // Heading after title (string or string[] for multi-line)
|
|
175
184
|
paragraphs: [], // Text blocks
|
|
176
|
-
links: [], // { href, label, role } — standalone links
|
|
185
|
+
links: [], // { href, label, role } — standalone links (not inside lists)
|
|
177
186
|
images: [], // { src, alt, role, href }
|
|
178
187
|
icons: [], // { library, name, role }
|
|
179
188
|
videos: [], // { src, alt, role, poster, href }
|
|
@@ -249,6 +258,20 @@ Enterprise-grade security. │ content.items[1].paragraphs[0] = "Enterprise
|
|
|
249
258
|
|
|
250
259
|
Headings before the main title become `pretitle`. Headings after the main title at a lower importance become `subtitle`. Headings that appear after body content (paragraphs, links, images) start the `items` array.
|
|
251
260
|
|
|
261
|
+
**Subtitle vs items:** A heading immediately after the title becomes `subtitle` only when it is **exactly one level deeper** (H1→H2, H2→H3). Skipping levels (H1→H3) breaks the group — the deeper heading starts items instead. If you want items without a subtitle, use a `---` divider or a paragraph to close the title group:
|
|
262
|
+
|
|
263
|
+
```markdown
|
|
264
|
+
# Our Stats │ content.title = "Our Stats"
|
|
265
|
+
--- │ ← divider closes the title group
|
|
266
|
+
## 15,000+ │ content.items[0].title = "15,000+"
|
|
267
|
+
Students from 90 countries │ content.items[0].paragraphs[0]
|
|
268
|
+
│
|
|
269
|
+
## 200+ │ content.items[1].title = "200+"
|
|
270
|
+
Programs offered │ content.items[1].paragraphs[0]
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Without the `---`, `## 15,000+` would become `content.subtitle` instead of an item.
|
|
274
|
+
|
|
252
275
|
### Choosing how to model content
|
|
253
276
|
|
|
254
277
|
You have three layers. Most of the design skill is choosing between them:
|
|
@@ -477,6 +500,8 @@ export default function Grid({ block, params }) {
|
|
|
477
500
|
}
|
|
478
501
|
```
|
|
479
502
|
|
|
503
|
+
**Data and child blocks:** Page-level `data:` is available to all blocks on the page, including children. Each child block resolves data independently through the same page → site hierarchy. If a child component needs data, declare it in the child's `meta.js` or in the child section's frontmatter (`data: articles`).
|
|
504
|
+
|
|
480
505
|
### Section Backgrounds
|
|
481
506
|
|
|
482
507
|
Set `background` in frontmatter — the runtime renders it automatically:
|
|
@@ -529,6 +554,7 @@ id: about # Stable identity (for page: links, survives moves)
|
|
|
529
554
|
order: 2 # Navigation sort position
|
|
530
555
|
pages: [team, history, ...] # Child page order (... = rest). Without ... = strict (hides unlisted)
|
|
531
556
|
index: getting-started # Which child page is the index
|
|
557
|
+
redirect: academic # Redirect to child page (relative or absolute path, or URL)
|
|
532
558
|
```
|
|
533
559
|
|
|
534
560
|
**site.yml:**
|
|
@@ -720,6 +746,8 @@ export const vars = {
|
|
|
720
746
|
|
|
721
747
|
Sites override in `theme.yml` under `vars:`. Components use: `py-[var(--section-padding-y)]`, `h-[var(--header-height)]`.
|
|
722
748
|
|
|
749
|
+
Tailwind v4 also supports a shorthand: `py-(--section-padding-y)`. This requires registering the variable in `styles.css` via `@theme inline { --section-padding-y: <default>; }`. Use the shorthand for vars referenced across many components; otherwise the bracket syntax works without registration.
|
|
750
|
+
|
|
723
751
|
### Design richness beyond tokens
|
|
724
752
|
|
|
725
753
|
Tokens handle context adaptation — the hard problem. **They are a floor, not a ceiling.** A great foundation adds design vocabulary on top:
|
|
@@ -764,6 +792,7 @@ All non-reserved frontmatter fields become `params`. Reserved: `type`, `preset`,
|
|
|
764
792
|
| `block.insets` | Block[] | Inline `@Component` references |
|
|
765
793
|
| `block.getInset(refId)` | Block | Lookup inset by refId |
|
|
766
794
|
| `block.properties` | object | Raw frontmatter |
|
|
795
|
+
| `block.rawContent` | object | ProseMirror document — passed internally when using `<Article block={block} />` |
|
|
767
796
|
| `block.themeName` | string | `"light"`, `"medium"`, `"dark"` |
|
|
768
797
|
| `block.stableId` | string | Stable ID from filename or `id:` |
|
|
769
798
|
|
|
@@ -817,10 +846,10 @@ Kit provides `H1` through `H6` — use the appropriate level for semantic hierar
|
|
|
817
846
|
**Full content rendering** (article/docs sections where the author controls the flow):
|
|
818
847
|
|
|
819
848
|
```jsx
|
|
820
|
-
import { Section,
|
|
849
|
+
import { Section, Article } from '@uniweb/kit'
|
|
821
850
|
|
|
822
851
|
<Section block={block} width="lg" padding="md" />
|
|
823
|
-
<
|
|
852
|
+
<Article block={block} />
|
|
824
853
|
```
|
|
825
854
|
|
|
826
855
|
**Visuals:**
|
|
@@ -835,7 +864,7 @@ import { Visual } from '@uniweb/kit'
|
|
|
835
864
|
|
|
836
865
|
**Rendering text:** `H1`–`H6`, `P`, `Span`, `Div`, `Text` (with `as` prop)
|
|
837
866
|
|
|
838
|
-
**Rendering content:** `Section` (
|
|
867
|
+
**Rendering content:** `Section` (full section with prose + layout), `Article` (prose content from `block.rawContent`), `Render` (ProseMirror nodes → React), `ChildBlocks` (render child sections)
|
|
839
868
|
|
|
840
869
|
**Rendering media:** `Visual` (first non-empty: inset/video/image), `Image`, `Media`, `Icon`
|
|
841
870
|
|
|
@@ -867,15 +896,20 @@ useColorContext(block) → 'light' | 'medium' | 'dark' // current section cont
|
|
|
867
896
|
|
|
868
897
|
### Icon Component
|
|
869
898
|
|
|
870
|
-
The `<Icon>` renders icons from content or explicit props
|
|
899
|
+
The `<Icon>` renders icons from content or explicit props:
|
|
871
900
|
|
|
872
901
|
```jsx
|
|
873
|
-
{content.icons.map((icon, i) => <Icon key={i} {...icon} />)}
|
|
902
|
+
{content.icons.map((icon, i) => <Icon key={i} {...icon} />)} // From content
|
|
903
|
+
<Icon name="search" /> // Lucide (default)
|
|
904
|
+
<Icon name="hi2-arrow-right" /> // Other library
|
|
905
|
+
<Icon name="close" /> // Built-in (no network)
|
|
874
906
|
```
|
|
875
907
|
|
|
876
|
-
|
|
908
|
+
The `name` prop handles everything: built-in names, Lucide icons (default when no library prefix), and other libraries via prefix (`hi2-arrow-right`, `tb-star`). From content, spread the icon object which has `library` + `name` fields.
|
|
909
|
+
|
|
910
|
+
Other props: `svg` (direct SVG string), `url` (fetch from URL), `size` (default `'24'`), `className`.
|
|
877
911
|
|
|
878
|
-
Built-in icons (no
|
|
912
|
+
Built-in icons (instant, no network): `check`, `close`, `menu`, `chevronDown`, `chevronRight`, `externalLink`, `download`, `play`, and a few others.
|
|
879
913
|
|
|
880
914
|
### Content Patterns for Header and Footer
|
|
881
915
|
|
package/src/index.js
CHANGED
|
@@ -727,19 +727,32 @@ async function main() {
|
|
|
727
727
|
|
|
728
728
|
// Initialize git repository
|
|
729
729
|
if (!noGit) {
|
|
730
|
+
// Skip git init if already inside a git repo (common for monorepos/workspaces)
|
|
731
|
+
let insideGitRepo = false
|
|
730
732
|
try {
|
|
731
|
-
execSync('git --
|
|
733
|
+
execSync('git rev-parse --is-inside-work-tree', { cwd: projectDir, stdio: 'ignore' })
|
|
734
|
+
insideGitRepo = true
|
|
735
|
+
} catch {
|
|
736
|
+
// Not inside a git repo — proceed with init
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if (insideGitRepo) {
|
|
740
|
+
log(` ${colors.dim}Skipping git init — already inside a git repository${colors.reset}`)
|
|
741
|
+
} else {
|
|
732
742
|
try {
|
|
733
|
-
execSync('git
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
743
|
+
execSync('git --version', { stdio: 'ignore' })
|
|
744
|
+
try {
|
|
745
|
+
execSync('git init', { cwd: projectDir, stdio: 'ignore' })
|
|
746
|
+
execSync('git add -A', { cwd: projectDir, stdio: 'ignore' })
|
|
747
|
+
execSync('git commit -m "Initial commit from uniweb"', { cwd: projectDir, stdio: 'ignore' })
|
|
748
|
+
success('Git repository initialized')
|
|
749
|
+
} catch {
|
|
750
|
+
log(` ${colors.yellow}Warning: Git repository initialized but initial commit failed${colors.reset}`)
|
|
751
|
+
log(` ${colors.dim}Run 'git commit -m "Initial commit"' after configuring git${colors.reset}`)
|
|
752
|
+
}
|
|
737
753
|
} catch {
|
|
738
|
-
|
|
739
|
-
log(` ${colors.dim}Run 'git commit -m "Initial commit"' after configuring git${colors.reset}`)
|
|
754
|
+
// git not available — skip silently
|
|
740
755
|
}
|
|
741
|
-
} catch {
|
|
742
|
-
// git not available — skip silently
|
|
743
756
|
}
|
|
744
757
|
}
|
|
745
758
|
|