mechanica 2.0.0 → 2.0.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/README.md +48 -2
- package/bin/mechanica.js +0 -0
- package/dist/chunks/{ImagePickerDialog-6skSAzJh.js → ImagePickerDialog-DJGhtW3r.js} +1 -1
- package/dist/chunks/{editor-B0r4EOIM.js → editor-JV0Nhfw4.js} +1 -1
- package/dist/chunks/{page-assets-Bp6mxPSy.js → page-assets-CM_MCuoa.js} +7 -1
- package/dist/cli.js +1 -1
- package/dist/composer.js +2 -2
- package/dist/editor.js +2 -2
- package/dist/plugin.js +1 -1
- package/dist/types/cli/page-assets.d.ts +6 -0
- package/dist/widgets.js +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -30,6 +30,37 @@ npm run export
|
|
|
30
30
|
|
|
31
31
|
Prefer Bun? `bun create mechanica my-site`, then `bun install` and `bun run dev`.
|
|
32
32
|
|
|
33
|
+
### With an AI coding agent
|
|
34
|
+
|
|
35
|
+
Claude Code, Codex and similar agents can set the site up and build it for you. Open an empty folder in the agent and paste:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
Create a Mechanica site in this folder.
|
|
39
|
+
|
|
40
|
+
1. Check for Node.js 20.19+ (`node -v`) or Bun (`bun -v`). If neither is
|
|
41
|
+
installed, ask me before installing Bun from https://bun.sh.
|
|
42
|
+
2. Run `npm create mechanica@latest .` (or `bun create mechanica .`), install
|
|
43
|
+
the dependencies, and start the dev server in the background.
|
|
44
|
+
3. Read AGENTS.md in the project and follow it for everything else.
|
|
45
|
+
|
|
46
|
+
Then build: <describe your site>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
To skip the pasting, install the skill once. It does the same setup and also handles a machine with no Node.js.
|
|
50
|
+
|
|
51
|
+
Claude Code:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
claude plugin marketplace add den59k/mechanica
|
|
55
|
+
claude plugin install mechanica@mechanica
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Codex: save [SKILL.md](https://github.com/den59k/mechanica/blob/main/plugins/mechanica/skills/create-mechanica-site/SKILL.md) as `~/.agents/skills/create-mechanica-site/SKILL.md`.
|
|
59
|
+
|
|
60
|
+
Then ask the agent to create a Mechanica site.
|
|
61
|
+
|
|
62
|
+
The starter's `AGENTS.md` teaches the agent how to write blocks and pages and how to check its work with screenshots, and points it at the documentation of the installed version. Run the agent on your own machine: the editor opens in your browser from the local dev server.
|
|
63
|
+
|
|
33
64
|
## A Mechanica project
|
|
34
65
|
|
|
35
66
|
```text
|
|
@@ -45,7 +76,7 @@ src/composer.ts optional: your design system for the Block Composer
|
|
|
45
76
|
.mech/data.json site-wide data values
|
|
46
77
|
```
|
|
47
78
|
|
|
48
|
-
`.mech/` is content — commit it. Scaffolded projects also include
|
|
79
|
+
`.mech/` is content — commit it. Scaffolded projects also include an `AGENTS.md` that teaches AI coding assistants (Claude Code, Codex and others) to author blocks and pages in this format.
|
|
49
80
|
|
|
50
81
|
### Adding Mechanica to an existing Vite + Vue project
|
|
51
82
|
|
|
@@ -139,14 +170,29 @@ data:
|
|
|
139
170
|
|
|
140
171
|
::: hero
|
|
141
172
|
title: About us
|
|
173
|
+
cta: { url: /contacts, title: Write to us }
|
|
142
174
|
@subtitle
|
|
143
175
|
We build fast websites
|
|
144
176
|
for people who care about the details.
|
|
145
177
|
:::
|
|
178
|
+
|
|
179
|
+
::: columns
|
|
180
|
+
gap: lg
|
|
181
|
+
::: card slot=left
|
|
182
|
+
title: Fast
|
|
183
|
+
:::
|
|
184
|
+
::: card slot=right
|
|
185
|
+
title: Readable
|
|
186
|
+
:::
|
|
187
|
+
::: /columns
|
|
146
188
|
```
|
|
147
189
|
|
|
148
190
|
- The YAML frontmatter holds the editor label (`name`), page-scoped data (`data`) and optional `layout`, `draft: true` (hidden from listings and the export) and `meta` (`noindex: true`, `lastmod`).
|
|
149
|
-
- Each block is a fence: `::: <blockId>`, then its props as YAML, then `@field` regions for long text, closed by `:::`.
|
|
191
|
+
- Each block is a fence: `::: <blockId>`, then its props as YAML, then `@field` regions for long text, then any child blocks, closed by `:::`. Keep that order: once a region has started, a `key: value` line is part of its text.
|
|
192
|
+
- A region runs until the next `@field`, child block or `:::`, and is taken as written, blank lines and Markdown included. It fills a `text` prop with that text, and a `richText` prop with its Markdown turned into rich text.
|
|
193
|
+
- Blocks nest by placing fences inside a container's fence, and `slot=<name>` puts a child into a named slot (a container's children go either all to the default slot or all to named ones). Nothing is indented: every `:::` and `@field` starts at the beginning of its line, and a block is a child of whichever fence is still open. A container may close with `::: /<blockId>`, which reports a missing `:::` at the line where the fences stop pairing up.
|
|
194
|
+
- Props are YAML, so quote a value that starts with `#` or contains `: `, as in `href: "#pricing"`. Inside a region nothing needs quoting; only a line that starts with `:::`, or consists of just `@name`, takes a leading backslash (`\:::`), and not even that inside a code fence.
|
|
195
|
+
- An `image` prop points at an uploaded file: `photo: { src: /@mechanica/assets/team.jpg, alt: "Our team" }`.
|
|
150
196
|
- Props left out take their schema defaults, so a hand-written page renders exactly like one made in the editor.
|
|
151
197
|
|
|
152
198
|
With `npm run dev` running, edits you make to these files show up in the editor live, and the editor won't overwrite a file that changed on disk underneath it.
|
package/bin/mechanica.js
CHANGED
|
File without changes
|
|
@@ -6,7 +6,7 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
|
6
6
|
return target;
|
|
7
7
|
};
|
|
8
8
|
//#endregion
|
|
9
|
-
//#region \0svg-glob
|
|
9
|
+
//#region \0svg-glob:/home/runner/work/mechanica/mechanica/packages/mechanica/src/editor/icons
|
|
10
10
|
var contents = {
|
|
11
11
|
"align-center": `<path d="M4 6h16M7 12h10M6 18h12"/>`,
|
|
12
12
|
"align-left": `<path d="M4 6h16M4 12h10M4 18h13"/>`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as renderCrop, c as useDialog, d as _plugin_vue_export_helper_default, i as readImageSize, l as VIcon_default, n as VDialog_default, r as analyzeImageFile, s as dialogKey, t as ImagePickerDialog_default } from "./ImagePickerDialog-
|
|
1
|
+
import { a as renderCrop, c as useDialog, d as _plugin_vue_export_helper_default, i as readImageSize, l as VIcon_default, n as VDialog_default, r as analyzeImageFile, s as dialogKey, t as ImagePickerDialog_default } from "./ImagePickerDialog-DJGhtW3r.js";
|
|
2
2
|
import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onErrorCaptured, onMounted, openBlock, provide, reactive, ref, renderList, renderSlot, resolveDynamicComponent, shallowRef, toDisplayString, unref, vShow, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
3
3
|
import { deepEqual, getDefaultValue } from "mechanica-shared";
|
|
4
4
|
import { unfoldSchema } from "compact-json-schema";
|
|
@@ -975,6 +975,12 @@ function resolveChunkAssets(manifest, key, into = {
|
|
|
975
975
|
* Build the `<link>` tags for one page: stylesheets first (they must apply
|
|
976
976
|
* before first paint — the server-rendered blocks are already in the HTML),
|
|
977
977
|
* then `modulepreload` for the block chunks and their shared imports.
|
|
978
|
+
*
|
|
979
|
+
* Every tag carries `crossorigin`, like the ones Vite writes into the built
|
|
980
|
+
* index: a later `import()` of the same chunk always fetches in CORS mode, and
|
|
981
|
+
* on a cross-origin CDN a copy cached by a no-CORS hint has no
|
|
982
|
+
* `Access-Control-Allow-Origin`, so the browser would block the import. The
|
|
983
|
+
* attribute is a no-op for same-origin builds.
|
|
978
984
|
*/
|
|
979
985
|
function blockAssetLinks(options) {
|
|
980
986
|
const keyByFile = /* @__PURE__ */ new Map();
|
|
@@ -991,7 +997,7 @@ function blockAssetLinks(options) {
|
|
|
991
997
|
}
|
|
992
998
|
const wanted = (file) => !options.alreadyLinked?.(file);
|
|
993
999
|
const href = (file) => `${options.base ?? ""}/${file}`;
|
|
994
|
-
return [...assets.css.filter(wanted).map((file) => `<link rel="stylesheet" href="${href(file)}">`), ...assets.js.filter(wanted).map((file) => `<link rel="modulepreload" href="${href(file)}">`)];
|
|
1000
|
+
return [...assets.css.filter(wanted).map((file) => `<link rel="stylesheet" crossorigin href="${href(file)}">`), ...assets.js.filter(wanted).map((file) => `<link rel="modulepreload" crossorigin href="${href(file)}">`)];
|
|
995
1001
|
}
|
|
996
1002
|
//#endregion
|
|
997
1003
|
export { renamePage as A, readImageManifest as B, getPagePath as C, pageUrlOf as D, movePage as E, translationsOf as F, wasRecentlyMutated as G, saveUpload as H, UPLOADS_PREFIX as I, hasSharp as J, writeFileAtomic as K, assetFileOf as L, setPageBlocks as M, setPageCodec as N, pageVersion as O, setPageDraft as P, isDerivedAsset as R, fillImageMeta as S, listPages as T, updateImageManifest as U, saveDerivedAsset as V, markMutated as W, isRasterImage as Y, createTranslation as _, toBlockMeta as a, duplicatePage as b, mergeLocaleFolderData as c, readFolderData as d, readFoldersData as f, createPage as g, PageExistsError as h, composedBlockMeta as i, savePage as j, readPage as k, mergeLocaleSiteData as l, readSiteLocaleOverride as m, blockAssetLinks as n, folderOf as o, readSiteData as p, analyzeImageBuffer as q, buildRichTextCodec as r, mergeFolderData as s, BLOCKS_MANIFEST_FILE as t, mergeSiteData as u, deletePage as v, listFolders as w, fillContentDefaults as x, deleteTranslation as y, listImages as z };
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as readImageManifest, C as getPagePath, I as UPLOADS_PREFIX, J as hasSharp, L as assetFileOf, N as setPageCodec, R as isDerivedAsset, T as listPages, U as updateImageManifest, Y as isRasterImage, a as toBlockMeta, d as readFolderData, f as readFoldersData, i as composedBlockMeta, m as readSiteLocaleOverride, n as blockAssetLinks, p as readSiteData, q as analyzeImageBuffer, r as buildRichTextCodec, t as BLOCKS_MANIFEST_FILE } from "./chunks/page-assets-
|
|
1
|
+
import { B as readImageManifest, C as getPagePath, I as UPLOADS_PREFIX, J as hasSharp, L as assetFileOf, N as setPageCodec, R as isDerivedAsset, T as listPages, U as updateImageManifest, Y as isRasterImage, a as toBlockMeta, d as readFolderData, f as readFoldersData, i as composedBlockMeta, m as readSiteLocaleOverride, n as blockAssetLinks, p as readSiteData, q as analyzeImageBuffer, r as buildRichTextCodec, t as BLOCKS_MANIFEST_FILE } from "./chunks/page-assets-CM_MCuoa.js";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import { dirname, join, parse, relative } from "node:path";
|
|
4
4
|
import { applySeoTags, auditPageHtml, buildRobotsTxt, buildSitemap, findUnknownBlocks, generateProject, isPaginatedQuery, localePath, mergeTranslation, migrateContent, paginationVariantPath, registerFieldSchemas, resolveQueryKey, templateBlockIds, validateLinks, walkSchema, walkTree } from "mechanica-shared";
|
package/dist/composer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './editor.css';
|
|
2
2
|
import { a as renderBlocks, l as ANCHOR_H, t as createMechanica, u as ANCHOR_V } from "./chunks/create-mechanica-CYaKXuQd.js";
|
|
3
|
-
import { C as placeBlock, D as registerBuiltinFieldEditors, E as uid, M as SmartLinkField_default, R as VSelect_default, S as moveBlock, T as removeBlock, _ as duplicateBlock, b as findParentList, c as shortcutChar, g as cloneBlock, h as humanize, i as normalizeTemplate, m as toBlockMeta, n as createSaveQueue, o as SchemaField_default, s as FieldControl_default, t as SaveConflictError, v as ensureSlotList, w as relocateBlock, x as findParentSlot, y as findBlock, z as VPopover_default } from "./chunks/editor-
|
|
4
|
-
import { d as _plugin_vue_export_helper_default, l as VIcon_default, u as contents } from "./chunks/ImagePickerDialog-
|
|
3
|
+
import { C as placeBlock, D as registerBuiltinFieldEditors, E as uid, M as SmartLinkField_default, R as VSelect_default, S as moveBlock, T as removeBlock, _ as duplicateBlock, b as findParentList, c as shortcutChar, g as cloneBlock, h as humanize, i as normalizeTemplate, m as toBlockMeta, n as createSaveQueue, o as SchemaField_default, s as FieldControl_default, t as SaveConflictError, v as ensureSlotList, w as relocateBlock, x as findParentSlot, y as findBlock, z as VPopover_default } from "./chunks/editor-JV0Nhfw4.js";
|
|
4
|
+
import { d as _plugin_vue_export_helper_default, l as VIcon_default, u as contents } from "./chunks/ImagePickerDialog-DJGhtW3r.js";
|
|
5
5
|
import { Fragment, Teleport, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, onScopeDispose, openBlock, provide, reactive, ref, renderList, renderSlot, resolveComponent, toDisplayString, unref, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
|
|
6
6
|
import { buildPreviewData, getDefaultValue, isBinding, lookupBinding, registerFieldSchemas, resolveBindings, walkTree } from "mechanica-shared";
|
|
7
7
|
import { unfoldSchema } from "compact-json-schema";
|
package/dist/editor.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import './editor.css';
|
|
2
2
|
import { _ as mechanicaKey, a as renderBlocks, c as registerElements, i as createComposedComponent, m as createRouter, n as pushStateUpdate, r as runtimeLayoutNames } from "./chunks/create-mechanica-CYaKXuQd.js";
|
|
3
3
|
import { i as getDataEntries, t as buildPreviewContent } from "./chunks/preview-CbUxh2gL.js";
|
|
4
|
-
import { A as createContextMenu, C as placeBlock, D as registerBuiltinFieldEditors, E as uid, F as groupPagesByFolder, I as pageThumbUrl, L as pathFromName, N as fetchPages, O as registerRichTextWidgets, P as filterPages, R as VSelect_default, S as moveBlock, T as removeBlock, _ as duplicateBlock, a as SchemaForm_default, c as shortcutChar, d as compareBlocks, f as createContentBlock, g as cloneBlock, h as humanize, j as VSegmented_default, k as contextMenuKey, l as blockAvailableForLayout, m as toBlockMeta, n as createSaveQueue, p as isUnderFolder, r as createRootFrame, t as SaveConflictError, u as blockAvailableIn, w as relocateBlock, x as findParentSlot, y as findBlock, z as VPopover_default } from "./chunks/editor-
|
|
5
|
-
import { c as useDialog, d as _plugin_vue_export_helper_default, l as VIcon_default, n as VDialog_default, o as createDialogStore, s as dialogKey } from "./chunks/ImagePickerDialog-
|
|
4
|
+
import { A as createContextMenu, C as placeBlock, D as registerBuiltinFieldEditors, E as uid, F as groupPagesByFolder, I as pageThumbUrl, L as pathFromName, N as fetchPages, O as registerRichTextWidgets, P as filterPages, R as VSelect_default, S as moveBlock, T as removeBlock, _ as duplicateBlock, a as SchemaForm_default, c as shortcutChar, d as compareBlocks, f as createContentBlock, g as cloneBlock, h as humanize, j as VSegmented_default, k as contextMenuKey, l as blockAvailableForLayout, m as toBlockMeta, n as createSaveQueue, p as isUnderFolder, r as createRootFrame, t as SaveConflictError, u as blockAvailableIn, w as relocateBlock, x as findParentSlot, y as findBlock, z as VPopover_default } from "./chunks/editor-JV0Nhfw4.js";
|
|
5
|
+
import { c as useDialog, d as _plugin_vue_export_helper_default, l as VIcon_default, n as VDialog_default, o as createDialogStore, s as dialogKey } from "./chunks/ImagePickerDialog-DJGhtW3r.js";
|
|
6
6
|
import { Fragment, Teleport, Transition, TransitionGroup, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, markRaw, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onErrorCaptured, onMounted, onScopeDispose, openBlock, provide, reactive, ref, renderList, resolveComponent, resolveDynamicComponent, shallowRef, toDisplayString, unref, useTemplateRef, vModelCheckbox, vModelText, watch, withCtx, withDirectives, withModifiers } from "vue";
|
|
7
7
|
import { getDefaultValue, localeLabel, localePath, parseLocalePath, registerFieldSchemas } from "mechanica-shared";
|
|
8
8
|
import { blocksList } from "virtual:mechanica/blocks";
|
package/dist/plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as renamePage, D as pageUrlOf, E as movePage, F as translationsOf, G as wasRecentlyMutated, H as saveUpload, K as writeFileAtomic, M as setPageBlocks, N as setPageCodec, O as pageVersion, P as setPageDraft, S as fillImageMeta, T as listPages, V as saveDerivedAsset, W as markMutated, _ as createTranslation, a as toBlockMeta, b as duplicatePage, c as mergeLocaleFolderData, d as readFolderData, g as createPage, h as PageExistsError, i as composedBlockMeta, j as savePage, k as readPage, l as mergeLocaleSiteData, o as folderOf, p as readSiteData, r as buildRichTextCodec, s as mergeFolderData, t as BLOCKS_MANIFEST_FILE, u as mergeSiteData, v as deletePage, w as listFolders, x as fillContentDefaults, y as deleteTranslation, z as listImages } from "./chunks/page-assets-
|
|
1
|
+
import { A as renamePage, D as pageUrlOf, E as movePage, F as translationsOf, G as wasRecentlyMutated, H as saveUpload, K as writeFileAtomic, M as setPageBlocks, N as setPageCodec, O as pageVersion, P as setPageDraft, S as fillImageMeta, T as listPages, V as saveDerivedAsset, W as markMutated, _ as createTranslation, a as toBlockMeta, b as duplicatePage, c as mergeLocaleFolderData, d as readFolderData, g as createPage, h as PageExistsError, i as composedBlockMeta, j as savePage, k as readPage, l as mergeLocaleSiteData, o as folderOf, p as readSiteData, r as buildRichTextCodec, s as mergeFolderData, t as BLOCKS_MANIFEST_FILE, u as mergeSiteData, v as deletePage, w as listFolders, x as fillContentDefaults, y as deleteTranslation, z as listImages } from "./chunks/page-assets-CM_MCuoa.js";
|
|
2
2
|
import fs, { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
3
|
import { basename, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { parseVueRequest } from "@vitejs/plugin-vue";
|
|
@@ -68,5 +68,11 @@ export interface BlockAssetLinkOptions {
|
|
|
68
68
|
* Build the `<link>` tags for one page: stylesheets first (they must apply
|
|
69
69
|
* before first paint — the server-rendered blocks are already in the HTML),
|
|
70
70
|
* then `modulepreload` for the block chunks and their shared imports.
|
|
71
|
+
*
|
|
72
|
+
* Every tag carries `crossorigin`, like the ones Vite writes into the built
|
|
73
|
+
* index: a later `import()` of the same chunk always fetches in CORS mode, and
|
|
74
|
+
* on a cross-origin CDN a copy cached by a no-CORS hint has no
|
|
75
|
+
* `Access-Control-Allow-Origin`, so the browser would block the import. The
|
|
76
|
+
* attribute is a no-op for same-origin builds.
|
|
71
77
|
*/
|
|
72
78
|
export declare function blockAssetLinks(options: BlockAssetLinkOptions): string[];
|
package/dist/widgets.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as dialogKey, t as ImagePickerDialog_default } from "./chunks/ImagePickerDialog-
|
|
1
|
+
import { s as dialogKey, t as ImagePickerDialog_default } from "./chunks/ImagePickerDialog-DJGhtW3r.js";
|
|
2
2
|
import { inject } from "vue";
|
|
3
3
|
//#region src/editor/widget-api.ts
|
|
4
4
|
/**
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mechanica",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Build Vue 3 websites with a visual block editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://
|
|
8
|
+
"url": "git+https://github.com/den59k/mechanica.git",
|
|
9
|
+
"directory": "packages/mechanica"
|
|
9
10
|
},
|
|
10
11
|
"keywords": [
|
|
11
12
|
"vue",
|
|
@@ -54,10 +55,10 @@
|
|
|
54
55
|
"test": "vitest run",
|
|
55
56
|
"test:watch": "vitest",
|
|
56
57
|
"typecheck": "tsc --noEmit",
|
|
57
|
-
"prepublishOnly": "bun run build"
|
|
58
|
+
"prepublishOnly": "bun ../../scripts/ensure-bun-publish.js && bun run build"
|
|
58
59
|
},
|
|
59
60
|
"dependencies": {
|
|
60
|
-
"mechanica-shared": "
|
|
61
|
+
"mechanica-shared": "2.0.2",
|
|
61
62
|
"@vue/compiler-sfc": "^3.5.38",
|
|
62
63
|
"compact-json-schema": "^0.1.5",
|
|
63
64
|
"estree-walker": "^3.0.3",
|