seemore 1.6.1 → 1.8.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/README.md CHANGED
@@ -100,11 +100,11 @@ The preview is not just for reading — it is the fastest way to fix what you ar
100
100
  <img src="https://raw.githubusercontent.com/arifszn/seemore/main/packages/site/assets/inline-editor.png" alt="seemore rendering a folder of Markdown in the browser, with a paragraph's Markdown source open in the inline editor" width="640"/>
101
101
  </p>
102
102
 
103
- Inline editing is for local previews only — `seemore build` output is static, so nothing is emitted there. It is on by default in dev; switch it off with the `!` prefix:
103
+ Inline editing is for local previews only — `seemore build` output is static, so nothing is emitted there. It is on by default in dev; switch it off like this:
104
104
 
105
105
  ```ts
106
106
  export default {
107
- features: ['!content.edit'],
107
+ features: { 'content.edit': false },
108
108
  };
109
109
  ```
110
110
 
@@ -158,7 +158,7 @@ export default {
158
158
  base: '/my-repo/',
159
159
  theme: 'ocean',
160
160
  css: './custom.css',
161
- features: ['navigation.path', 'navigation.instant.preview'],
161
+ features: { 'navigation.path': true, 'navigation.instant.preview': true },
162
162
  nav: [{ text: 'GitHub', link: 'https://github.com/you/repo' }],
163
163
  footer: { text: '© 2026' },
164
164
  editLink: { base: 'https://github.com/you/repo/edit/main/docs' },
@@ -201,15 +201,15 @@ Twelve built-in colour presets: `neutral` (default), `black`, `catppuccin`, `dus
201
201
 
202
202
  ### Features
203
203
 
204
- A flat list of switches for fine control, set as an array on the `features` key. Turn something on by adding its flag name, turn something off with the `!` prefix; flags you don't mention keep their default.
204
+ A set of switches for fine control, set on the `features` key. Name the ones you want to change and set each `true` or `false`; flags you don't mention keep their default.
205
205
 
206
206
  ```ts
207
207
  // seemore.config.ts
208
208
  export default {
209
- features: [
210
- 'navigation.path', // off by default → this turns it on
211
- '!navigation.instant.prefetch', // on by default → this turns it off
212
- ],
209
+ features: {
210
+ 'navigation.path': true, // off by default → this turns it on
211
+ 'navigation.instant.prefetch': false, // on by default → this turns it off
212
+ },
213
213
  };
214
214
  ```
215
215
 
package/dist/cli/index.js CHANGED
@@ -147,7 +147,7 @@ var FEATURE_DEFAULTS = {
147
147
  "content.action.edit": false,
148
148
  // On by default, but only ever active in dev: the stamping that makes a block editable is
149
149
  // not emitted by `seemore build`, and the endpoint that writes is registered only by the
150
- // dev server. Switch it off with '!content.edit'.
150
+ // dev server. Switch it off with `'content.edit': false`.
151
151
  "content.edit": true,
152
152
  "content.image.zoom": true,
153
153
  "search.suggest": true,
@@ -169,17 +169,12 @@ var RULES = [
169
169
  }
170
170
  ];
171
171
  function resolveFeatures(input, implicit = {}) {
172
- const resolved = { ...FEATURE_DEFAULTS, ...implicit };
173
- for (const flag of input) {
174
- const off = flag.startsWith("!");
175
- const name = off ? flag.slice(1) : flag;
176
- resolved[name] = !off;
177
- }
172
+ const resolved = { ...FEATURE_DEFAULTS, ...implicit, ...toMap(input) };
178
173
  const problems = [];
179
174
  for (const rule of RULES) {
180
175
  if (rule.kind === "conflict") {
181
176
  if (!resolved[rule.a] || !resolved[rule.b]) continue;
182
- const fix = FEATURE_DEFAULTS[rule.b] ? `Add '!${rule.b}' to \`features\` to switch it off.` : `Remove '${rule.b}' from \`features\`.`;
177
+ const fix = `Set \`'${rule.b}': false\` in \`features\`.`;
183
178
  problems.push(`\`${rule.a}\` cannot be combined with \`${rule.b}\`. ${rule.why} ${fix}`);
184
179
  } else if (resolved[rule.flag] && !resolved[rule.needs]) {
185
180
  problems.push(
@@ -195,6 +190,19 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`
195
190
  }
196
191
  return resolved;
197
192
  }
193
+ function featuresFromFlags(flags) {
194
+ const map = {};
195
+ for (const flag of flags) {
196
+ const off = flag.startsWith("!");
197
+ map[off ? flag.slice(1) : flag] = !off;
198
+ }
199
+ return map;
200
+ }
201
+ function toMap(input) {
202
+ if (Array.isArray(input)) return featuresFromFlags(input);
203
+ const set = Object.entries(input).filter(([, on]) => on !== void 0);
204
+ return Object.fromEntries(set);
205
+ }
198
206
 
199
207
  // src/node/config/schema.ts
200
208
  import { z } from "zod";
@@ -212,7 +220,10 @@ var THEMES = [
212
220
  "vitepress",
213
221
  "shadcn"
214
222
  ];
215
- var featureFlag = z.enum([...FEATURES, ...FEATURES.map((f) => `!${f}`)]);
223
+ var featuresSchema = z.preprocess((input) => {
224
+ const isFlagArray = Array.isArray(input) && input.every((flag) => typeof flag === "string");
225
+ return isFlagArray ? featuresFromFlags(input) : input;
226
+ }, z.partialRecord(z.enum(FEATURES), z.boolean()));
216
227
  var navItem = z.lazy(
217
228
  () => z.object({
218
229
  text: z.string(),
@@ -249,7 +260,7 @@ var configSchema = z.object({
249
260
  theme: z.enum(THEMES).default("neutral"),
250
261
  /** A CSS file appended after everything else, so it wins. */
251
262
  css: z.string().optional(),
252
- features: z.array(featureFlag).default([]),
263
+ features: featuresSchema.default({}),
253
264
  nav: z.array(navItem).optional(),
254
265
  footer: z.object({
255
266
  text: z.string().optional(),
@@ -356,6 +367,10 @@ function explain(issue) {
356
367
  if (issue.code === "invalid_value" && issue.path.join(".") === "theme") {
357
368
  return `unknown theme. Valid themes: ${THEMES.join(", ")}.`;
358
369
  }
370
+ if (issue.code === "unrecognized_keys" && issue.path.join(".") === "features") {
371
+ const named = issue.keys.map((key) => `\`${key}\``).join(", ");
372
+ return `unknown feature ${issue.keys.length === 1 ? "flag" : "flags"}: ${named}. Valid flags: ${FEATURES.join(", ")}.`;
373
+ }
359
374
  return issue.message;
360
375
  }
361
376