scavold 0.2.0-rc.1 → 0.2.0-rc.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable changes to Scavold are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), versions follow
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ While the version stays below `1.0.0` and carries a pre-release suffix, breaking
8
+ changes may occur in any release.
9
+
10
+ ## [0.2.0-rc.2] — 2026-08-06
11
+
12
+ ### Fixed
13
+
14
+ - `media_folder` from `.cratly.config.yaml` is honoured again. `augmentConfig()` read
15
+ every other folder declaration but this one, so image resolution fell back to the
16
+ pages folder: any image stored in the editor-managed media folder was reported as
17
+ missing and failed the build. No site could use an image from `media/`.
18
+
19
+ ### Changed
20
+
21
+ - The folder precedence rules moved into an exported, pure `resolveFolders()`, so an
22
+ explicit `srcDir` / `mediaDir` in the VitePress config beating the YAML declaration
23
+ is covered by unit tests instead of only by a running site.
24
+
25
+ ## [0.2.0-rc.1] — 2026-08-05
26
+
27
+ First published release. Version `0.1.0` existed in-tree only.
28
+
29
+ ### Added
30
+
31
+ - **Section-type manifest.** The build emits `.cratly/sections.json`, describing the
32
+ typed properties each container accepts, so the cratly editor can render matching
33
+ controls. Container declarations in `.cratly.config.yaml` support `props` (with
34
+ `flags` and `kv` as shorthands) and are merged with Scavold's built-in sections.
35
+ - **Background videos.** The `video` container accepts `overlay` to place the video
36
+ behind the block's content, plus `controls` to bring the native controls back in
37
+ that mode.
38
+ - Type declarations for both entry points (`scavold`, `scavold/config`), a `typecheck`
39
+ script, and the MIT licence text the package always claimed to carry.
40
+
41
+ ### Fixed
42
+
43
+ - `Scavold.UserConfig` in the shipped declarations was a self-referential type alias
44
+ (TS2456) and now aliases VitePress's `UserConfig`.
45
+
46
+ ### Known issues
47
+
48
+ - Flag arguments on the `video` container have no effect: bare words become the
49
+ container's `class`, while `useVideo()` reads its booleans from `data-*` props, which
50
+ only `key=value` arguments produce. Use `overlay=1 autoplay=1 loop=1` until this is
51
+ resolved.
52
+ - Container names that are neither built in nor declared in `.cratly.config.yaml` are
53
+ not parsed as containers at all, despite `ScavoldContainer` being documented as a
54
+ catch-all fallback.
55
+ - Only images are processed out of `media_folder`; other file types (video, documents)
56
+ are never copied into the build output and have to live in the static folder.
57
+
58
+ [0.2.0-rc.2]: https://gitlab.com/cepharum-foss/cratly/scavold/-/compare/v0.2.0-rc.1...v0.2.0-rc.2
59
+ [0.2.0-rc.1]: https://gitlab.com/cepharum-foss/cratly/scavold/-/tags/v0.2.0-rc.1
package/README.md CHANGED
@@ -9,11 +9,11 @@ custom containers for Markdown-driven structures on your pages such as galleries
9
9
  bun add vitepress vue scavold
10
10
  ```
11
11
 
12
- Scavold is currently published as a pre-release, so install it explicitly while
13
- `latest` does not exist yet:
12
+ Scavold is currently a **pre-release**: breaking changes may occur between releases,
13
+ so pin the version you develop against rather than following the range blindly.
14
14
 
15
15
  ```sh
16
- bun add vitepress vue scavold@next
16
+ bun add vitepress vue scavold@^0.2.0-rc.2
17
17
  ```
18
18
 
19
19
  Responsive image generation uses [sharp](https://sharp.pixelplumbing.com/), which
package/lib/config.js CHANGED
@@ -130,6 +130,35 @@ function parseSizesFromTitle( title ) {
130
130
  return match?.[1] ?? match?.[2] ?? undefined;
131
131
  }
132
132
 
133
+ /**
134
+ * Resolves the three content folders from the VitePress config and the declarations
135
+ * of `.cratly.config.yaml`. An explicit value in the VitePress config always wins,
136
+ * so a site can express a path in code instead of in the YAML.
137
+ *
138
+ * Kept pure and exported so the precedence rules are testable without a filesystem.
139
+ *
140
+ * @param {object} rawConfig VitePress user config as passed to augmentConfig()
141
+ * @param {object} declared folders declared in .cratly.config.yaml (null when absent)
142
+ * @param {string|null} [declared.pagesFolder] `pages_folder`
143
+ * @param {string|null} [declared.mediaFolder] `media_folder`
144
+ * @param {string|null} [declared.staticFolder] `static_folder`
145
+ * @returns {{srcDir: string|undefined, mediaDir: string|undefined, staticFolder: string|null}}
146
+ */
147
+ export function resolveFolders( rawConfig = {}, declared = {} ) {
148
+ const srcDir = rawConfig.srcDir ?? declared.pagesFolder ?? undefined;
149
+
150
+ // Media folder for image resolution. Without either source, useMedia() falls back
151
+ // to srcDir, i.e. images living next to the pages that reference them.
152
+ const mediaDir = rawConfig.mediaDir ?? declared.mediaFolder ?? undefined;
153
+
154
+ // Prevent VitePress/Vite from defaulting publicDir to {srcDir}/public when content
155
+ // lives in a subfolder — static assets must not appear inside the pages folder.
156
+ // Falls back to "public" at the project root only when srcDir is a subfolder.
157
+ const staticFolder = declared.staticFolder ?? ( srcDir && srcDir !== "." ? "public" : null );
158
+
159
+ return { srcDir, mediaDir, staticFolder };
160
+ }
161
+
133
162
  /**
134
163
  * Augments provided VitePress configuration to integrate extended theme
135
164
  * features.
@@ -144,6 +173,7 @@ export async function augmentConfig( rawConfig, options = {} ) {
144
173
  // Read .crate.config.yaml for structural config and container declarations (Tier 2)
145
174
  let crateContainers = {};
146
175
  let crateSrcDir = null;
176
+ let crateMediaDir = null;
147
177
  let crateStaticDir = null;
148
178
  let crateImageSizes = null;
149
179
  let crateImageWidths = null;
@@ -155,6 +185,7 @@ export async function augmentConfig( rawConfig, options = {} ) {
155
185
  const crate = YAML.parse( raw ) ?? {};
156
186
  crateContainers = crate.containers ?? {};
157
187
  crateSrcDir = crate.pages_folder ?? null;
188
+ crateMediaDir = crate.media_folder ?? null;
158
189
  crateStaticDir = crate.static_folder ?? null;
159
190
  crateImageSizes = crate.image_sizes ?? null;
160
191
  crateImageWidths = crate.image_widths ?? null;
@@ -164,16 +195,12 @@ export async function augmentConfig( rawConfig, options = {} ) {
164
195
 
165
196
  const containerMap = resolveContainerMap( crateContainers, options.containers );
166
197
 
167
- // Apply srcDir from crate config if not already set in rawConfig
168
- const srcDir = rawConfig.srcDir ?? crateSrcDir ?? undefined;
198
+ const { srcDir, mediaDir, staticFolder } = resolveFolders( rawConfig, {
199
+ pagesFolder: crateSrcDir,
200
+ mediaFolder: crateMediaDir,
201
+ staticFolder: crateStaticDir,
202
+ } );
169
203
 
170
- // Prevent VitePress/Vite from defaulting publicDir to {srcDir}/public when
171
- // content lives in a subfolder — static assets must not appear inside the
172
- // pages folder. VitePress passes srcDir as Vite's root, so publicDir must be
173
- // an absolute path to be unambiguous. Derived from static_folder in
174
- // .crate.config.yaml; falls back to "public" at the project root only when
175
- // srcDir is a subfolder and no explicit value is set by the caller.
176
- const staticFolder = crateStaticDir ?? ( srcDir && srcDir !== "." ? "public" : null );
177
204
  const vitePublicDir = rawConfig.vite?.publicDir
178
205
  ?? ( staticFolder ? resolve( process.cwd(), staticFolder ) : undefined );
179
206
 
@@ -182,6 +209,7 @@ export async function augmentConfig( rawConfig, options = {} ) {
182
209
  const resolvedConfig = {
183
210
  ...rawConfig,
184
211
  ...(srcDir !== undefined && { srcDir }),
212
+ ...(mediaDir !== undefined && { mediaDir }),
185
213
  vite: {
186
214
  ...rawConfig.vite,
187
215
  ...(vitePublicDir !== undefined && { publicDir: vitePublicDir }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scavold",
3
- "version": "0.2.0-rc.1",
3
+ "version": "0.2.0-rc.2",
4
4
  "type": "module",
5
5
  "description": "VitePress theme framework — a scaffold for building custom VitePress themes with Vue at the core",
6
6
  "keywords": [
@@ -49,6 +49,7 @@
49
49
  "lib",
50
50
  "scripts",
51
51
  "index.d.ts",
52
+ "CHANGELOG.md",
52
53
  "COMPONENTS.md",
53
54
  "FRONTMATTER.md",
54
55
  "README.md",