ampless 1.0.0-alpha.44 → 1.0.0-alpha.46
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/dist/index.d.ts +16 -1
- package/docs/plugin-author-guide.ja.md +10 -2
- package/docs/plugin-author-guide.md +37 -9
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -999,6 +999,21 @@ interface TiptapRenderNode {
|
|
|
999
999
|
}[];
|
|
1000
1000
|
text?: string;
|
|
1001
1001
|
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Adapter that converts a single tiptap node back to its markdown form.
|
|
1004
|
+
* Plugins that ship an embed node (e.g. amplessYoutube → bare YouTube URL)
|
|
1005
|
+
* export a map from nodeType to adapter from their `./editor` module
|
|
1006
|
+
* (named export `tiptapNodeToMarkdown`); `update-ampless` wires the map
|
|
1007
|
+
* into `installAdminTiptapNodeMarkdown` so the admin's
|
|
1008
|
+
* `tiptap → markdown` format switch can losslessly serialise the embed
|
|
1009
|
+
* (the round-trip back to tiptap goes through markdown's bare-URL paste
|
|
1010
|
+
* rule + `extractSingleUrl` in the runtime).
|
|
1011
|
+
*
|
|
1012
|
+
* Return `null` (or simply omit the nodeType from the map) to fall
|
|
1013
|
+
* through to the runtime's default markdown switch.
|
|
1014
|
+
*/
|
|
1015
|
+
type TiptapNodeToMarkdown = (node: TiptapRenderNode) => string | null;
|
|
1016
|
+
type TiptapNodeMarkdownAdapters = Readonly<Record<string, TiptapNodeToMarkdown>>;
|
|
1002
1017
|
/**
|
|
1003
1018
|
* Match object passed to a `contentFields` `markdown-url` renderer. The
|
|
1004
1019
|
* runtime walks the markdown body via `marked.lexer`, tests the trimmed
|
|
@@ -1886,4 +1901,4 @@ declare function pickDefaultEntrypoint(files: readonly {
|
|
|
1886
1901
|
|
|
1887
1902
|
declare const VERSION = "0.0.1";
|
|
1888
1903
|
|
|
1889
|
-
export { type AmplessEvent, type AmplessPlugin, type AuthContext, type BundleExtractResult, type CacheConfig, type CacheStrategy, type Config, type ContentEventPayload, type ContentEventType, type ContentFieldRenderer, type ContentFormat, type ContentTypeDefinition, type CreatePostInput, DEFAULT_ENTRYPOINT, type DateFormat, type EventPayloadOf, type EventType, type ExtractedFile, type FieldDefinition, type FieldType, type HistoryConfig, type ImageDisplay, type KvItem, type KvStore, type LinkListItem, type ListOptions, type ListPostHistoryOptions, type LocalizedString, MAX_BUNDLE_BYTES, type MarkdownEmbedMatch, type Media, type MediaEventPayload, type MediaEventType, type MediaMetadata, type MediaProcessingDefaults, type OgImageConfig, type OgImageFont, type OgImageRenderContext, PLUGIN_KEY_PATTERN, type Page, type PluginBooleanField, type PluginCapability, type PluginCodeField, type PluginEventHandler, type PluginHookResult, type PluginJsonField, type PluginMetadata, type PluginNumberField, type PluginPackageManifest, type PluginPublicRenderContext, type PluginRepeatableField, type PluginRepeatableSubField, type PluginRuntimeContext, type PluginSecretField, type PluginSelectField, type PluginSettingField, type PluginSettingsManifest, type PluginTextField, type PluginTextareaField, type PluginUninstallContext, type PluginUrlField, type Post, type PostIndexEventPayload, type PostIndexEventType, type PostMetadata, type PostRevision, type PostRevisionConnection, type PostStatus, type PostsProvider, type PublicBodyDescriptor, type PublicHeadDescriptor, type PublicPostBodyDescriptor, type PublicPostHtmlDescriptor, type PublicPostHtmlPosition, type PublicPostScriptDescriptor, type Role, SITE_CONFIG_PK, type ScriptStrategy, type SiteSettingsEventPayload, type SiteSettingsEventType, type StaticPostBody, type StaticPostFileMeta, type StreamEventName, TEXT_EXTENSIONS, type ThemeColorField, type ThemeField, type ThemeFieldType, type ThemeFontFamilyField, type ThemeImageField, type ThemeLengthField, type ThemeLinkListField, type ThemeManifest, type ThemeModule, type ThemeRouteContext, type ThemeSelectField, type ThemeTextField, type TiptapRenderNode, type TrustLevel, type TrustedPluginRuntimeContext, VERSION, type ValidationIssue, bundlePrefix, createPost, decodeAwsJson, defineConfig, definePlugin, defineSchema, defineTheme, defineThemeModule, deletePost, deleteSiteSetting, detectContentEvents, encodeAwsJson, escapeXml, extractFirstImageUrl, findAbsolutePathRefs, flattenSettings, formatColorPair, formatDate, formatPublicAssetUrl, getKvStore, getPost, getPostById, getSiteSetting, hasKvStore, hasPostsProvider, isTagListUrl, isValidPluginKey, listPostHistory, listPosts, listSiteSettings, mimeTypeFor, parseColorPair, parseLinkList, pickDefaultEntrypoint, resolveLocalized, resolvePluginSettings, resolveThemeValues, setKvStore, setPostsProvider, setSiteSetting, stringifyLinkList, stripCommonPrefix, themeSettingKey, unflattenSettings, updatePost, validateBundle, validateBundlePath, validatePluginSettingValue, validatePublicAssetKey, validateThemeValue };
|
|
1904
|
+
export { type AmplessEvent, type AmplessPlugin, type AuthContext, type BundleExtractResult, type CacheConfig, type CacheStrategy, type Config, type ContentEventPayload, type ContentEventType, type ContentFieldRenderer, type ContentFormat, type ContentTypeDefinition, type CreatePostInput, DEFAULT_ENTRYPOINT, type DateFormat, type EventPayloadOf, type EventType, type ExtractedFile, type FieldDefinition, type FieldType, type HistoryConfig, type ImageDisplay, type KvItem, type KvStore, type LinkListItem, type ListOptions, type ListPostHistoryOptions, type LocalizedString, MAX_BUNDLE_BYTES, type MarkdownEmbedMatch, type Media, type MediaEventPayload, type MediaEventType, type MediaMetadata, type MediaProcessingDefaults, type OgImageConfig, type OgImageFont, type OgImageRenderContext, PLUGIN_KEY_PATTERN, type Page, type PluginBooleanField, type PluginCapability, type PluginCodeField, type PluginEventHandler, type PluginHookResult, type PluginJsonField, type PluginMetadata, type PluginNumberField, type PluginPackageManifest, type PluginPublicRenderContext, type PluginRepeatableField, type PluginRepeatableSubField, type PluginRuntimeContext, type PluginSecretField, type PluginSelectField, type PluginSettingField, type PluginSettingsManifest, type PluginTextField, type PluginTextareaField, type PluginUninstallContext, type PluginUrlField, type Post, type PostIndexEventPayload, type PostIndexEventType, type PostMetadata, type PostRevision, type PostRevisionConnection, type PostStatus, type PostsProvider, type PublicBodyDescriptor, type PublicHeadDescriptor, type PublicPostBodyDescriptor, type PublicPostHtmlDescriptor, type PublicPostHtmlPosition, type PublicPostScriptDescriptor, type Role, SITE_CONFIG_PK, type ScriptStrategy, type SiteSettingsEventPayload, type SiteSettingsEventType, type StaticPostBody, type StaticPostFileMeta, type StreamEventName, TEXT_EXTENSIONS, type ThemeColorField, type ThemeField, type ThemeFieldType, type ThemeFontFamilyField, type ThemeImageField, type ThemeLengthField, type ThemeLinkListField, type ThemeManifest, type ThemeModule, type ThemeRouteContext, type ThemeSelectField, type ThemeTextField, type TiptapNodeMarkdownAdapters, type TiptapNodeToMarkdown, type TiptapRenderNode, type TrustLevel, type TrustedPluginRuntimeContext, VERSION, type ValidationIssue, bundlePrefix, createPost, decodeAwsJson, defineConfig, definePlugin, defineSchema, defineTheme, defineThemeModule, deletePost, deleteSiteSetting, detectContentEvents, encodeAwsJson, escapeXml, extractFirstImageUrl, findAbsolutePathRefs, flattenSettings, formatColorPair, formatDate, formatPublicAssetUrl, getKvStore, getPost, getPostById, getSiteSetting, hasKvStore, hasPostsProvider, isTagListUrl, isValidPluginKey, listPostHistory, listPosts, listSiteSettings, mimeTypeFor, parseColorPair, parseLinkList, pickDefaultEntrypoint, resolveLocalized, resolvePluginSettings, resolveThemeValues, setKvStore, setPostsProvider, setSiteSetting, stringifyLinkList, stripCommonPrefix, themeSettingKey, unflattenSettings, updatePost, validateBundle, validateBundlePath, validatePluginSettingValue, validatePublicAssetKey, validateThemeValue };
|
|
@@ -848,6 +848,12 @@ export default createAdminLayout(admin, { editorBootstrap: EditorBootstrap })
|
|
|
848
848
|
|
|
849
849
|
`installAdminEditorExtensions` は idempotent で、render 時に client component 内で呼ばれる。admin の `<TiptapEditor>` は毎回 render 時に登録済みリストを built-in extensions の末尾に spread する。
|
|
850
850
|
|
|
851
|
+
### markdown → tiptap の復元
|
|
852
|
+
|
|
853
|
+
editor Node が markdown へ bare URL line として serialise される場合、逆方向の復元は paste rule ではなく `Node.parseHTML()` で扱う必要がある。admin の `markdown → tiptap` format switch は、まず markdown を HTML に変換する。GFM autolink により bare URL line は `<p><a href="https://...">https://...</a></p>` になり、その HTML を tiptap が document として parse する。paste rule は user paste / typing event 用なので、この HTML parse 経路では発火しない。
|
|
854
|
+
|
|
855
|
+
embed 系 Node は、上記 paragraph shape 用の high-priority parse rule を追加し、必要に応じて他の HTML-to-tiptap 経路向けに `a[href]` rule も追加する。paragraph rule は「paragraph が単一 link だけを含み、その link text が `href` と同じ」場合だけ match させる。これにより parser は paragraph 全体を block embed Node に置換でき、embed の前に空 paragraph が残らない。`getAttrs` は URL を検証し、match しない link では `false` を返して通常の Link mark にフォールバックさせる。
|
|
856
|
+
|
|
851
857
|
### active source と完全無効化
|
|
852
858
|
|
|
853
859
|
**エディタ配線の active source は `package.json#dependencies`**(= `node_modules`)であり、`cms.config.ts` ではない。
|
|
@@ -857,7 +863,7 @@ export default createAdminLayout(admin, { editorBootstrap: EditorBootstrap })
|
|
|
857
863
|
|
|
858
864
|
### エディタプレビューのパイプライン
|
|
859
865
|
|
|
860
|
-
admin の edit / new post フォームは preview ペインを `<iframe sandbox="allow-scripts">` で表示する。`srcDoc` はテンプレート側 preview Route Handler が返す HTML。テンプレート scaffold は handler を `app/(admin)/admin/preview/route.tsx` に同梱する:
|
|
866
|
+
admin の edit / new post フォームは preview ペインを `<iframe sandbox="allow-scripts allow-same-origin">` で表示する。`srcDoc` はテンプレート側 preview Route Handler が返す HTML。テンプレート scaffold は handler を `app/(admin)/admin/preview/route.tsx` に同梱する:
|
|
861
867
|
|
|
862
868
|
```tsx
|
|
863
869
|
// templates/_shared/app/(admin)/admin/preview/route.tsx
|
|
@@ -911,7 +917,9 @@ export default createEditPostPage(admin, { previewEndpoint: '/cms/admin/preview'
|
|
|
911
917
|
|
|
912
918
|
Server Action ではなく Route Handler を採用した理由: `'use server'` モジュール内部で `react-dom/server` 由来の rendering を行うと、Next.js 15+ が edit-post page の compile に失敗する。build 時に Client Component から Server Action モジュール経由で import graph を辿るため、その経路上で `react-dom/server` に到達した時点で「You're importing a component that imports react-dom/server」チェックが発火する。Route Handler に切り出すことで rendering を import graph から完全に切り離せる — `<PostForm>` は plain な HTTP endpoint を fetch するだけで、bundler は form から handler 側へ踏み込まない。さらに handler 自身が `admin.isEditor()` を明示的にチェックすることで、将来 `(admin)` route-group gate が誤設定された場合の安全側のフェールセーフになる。`react-dom/server` の import 自体を dynamic にしているのは Next.js 16 の Turbopack が、Route Handler を含む app router build 経路で reach できる top-level の `react-dom/server` static import を一律で flag するため。request 時に解決することで build-time import-graph walker から外しつつ、runtime では同じ Node.js subpath からロードする。
|
|
913
919
|
|
|
914
|
-
iframe
|
|
920
|
+
**Preview iframe sandbox — v1 trust boundary 拡張:** iframe は `sandbox="allow-scripts allow-same-origin"` を使う。`srcDoc` とともに使用すると iframe は admin の origin を継承し、サードパーティ embed widget(YouTube SDK、x.com `widgets.js`)が動作できるようになる — opaque-origin(`allow-scripts` のみ)の iframe では動作を拒否する(非 HttpOnly storage / cache へのアクセスと real-origin requests が必要なため)。同時に same-origin により preview スクリプトは admin の auth state / 非 HttpOnly storage / DOM へのアクセスと authenticated same-origin XHR / fetch の発行が可能になる。
|
|
921
|
+
|
|
922
|
+
これは単なる sandbox 緩和ではなく、**v1 の明示的な設計判断**です: **ampless v1 は admin preview content / plugin script を全部 trusted とみなす**。エンジニアは npm install 前に plugin を審査するし(カスタマイズベース CMS モデル)、body content はこのサイトの trusted editor が作成する。`<PostHistoryPanel>` では別の editor が作成した過去 revision(revision author ≠ preview viewer)をプレビューするケースも通常発生するが、v1 ではそれも明示的に trust ring 内と位置づける。より安全な代替案(別 origin preview route + CSP / COEP / COOP)は v2.0+ でリアルなプラグインマーケットプレイスが必要になった場合に再検討する。
|
|
915
923
|
|
|
916
924
|
---
|
|
917
925
|
|
|
@@ -1104,6 +1104,24 @@ export default createAdminLayout(admin, { editorBootstrap: EditorBootstrap })
|
|
|
1104
1104
|
inside a client component. The admin's `<TiptapEditor>` spreads the
|
|
1105
1105
|
registered list onto its built-in extensions on every render.
|
|
1106
1106
|
|
|
1107
|
+
### Markdown to tiptap restoration
|
|
1108
|
+
|
|
1109
|
+
If an editor Node serializes to markdown as a bare URL line, the reverse
|
|
1110
|
+
direction must be handled by `Node.parseHTML()`, not by paste rules. The
|
|
1111
|
+
admin's `markdown → tiptap` format switch first converts markdown to HTML;
|
|
1112
|
+
GFM autolinks emit a bare URL line as
|
|
1113
|
+
`<p><a href="https://...">https://...</a></p>`, then tiptap parses that
|
|
1114
|
+
HTML into a document. Paste rules only run for user paste / typing events,
|
|
1115
|
+
so they do not fire on this HTML parse path.
|
|
1116
|
+
|
|
1117
|
+
Embed-style Nodes should add a high-priority parse rule for the paragraph
|
|
1118
|
+
shape above, and may also add an `a[href]` rule for other HTML-to-tiptap
|
|
1119
|
+
paths. The paragraph rule should only match when the paragraph contains a
|
|
1120
|
+
single link whose text equals its `href`; that lets the parser replace the
|
|
1121
|
+
whole paragraph with the block embed Node instead of leaving an empty
|
|
1122
|
+
paragraph before the embed. `getAttrs` should validate the URL and return
|
|
1123
|
+
`false` for non-matching links so the normal Link mark remains in place.
|
|
1124
|
+
|
|
1107
1125
|
### Active source and full disable
|
|
1108
1126
|
|
|
1109
1127
|
**The active source for editor wiring is `package.json#dependencies`**
|
|
@@ -1120,7 +1138,7 @@ registered list onto its built-in extensions on every render.
|
|
|
1120
1138
|
### Editor preview pipeline
|
|
1121
1139
|
|
|
1122
1140
|
The admin's edit / new post forms render the preview pane in an
|
|
1123
|
-
`<iframe sandbox="allow-scripts">` whose `srcDoc` is the HTML returned
|
|
1141
|
+
`<iframe sandbox="allow-scripts allow-same-origin">` whose `srcDoc` is the HTML returned
|
|
1124
1142
|
by the template's preview Route Handler. The template scaffold ships
|
|
1125
1143
|
the handler at `app/(admin)/admin/preview/route.tsx`:
|
|
1126
1144
|
|
|
@@ -1195,14 +1213,24 @@ included; deferring it to request time keeps the module outside the
|
|
|
1195
1213
|
build-time import-graph walker while still loading it from the same
|
|
1196
1214
|
Node.js subpath at runtime.
|
|
1197
1215
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1216
|
+
**Preview iframe sandbox — v1 trust boundary expansion:** The iframe uses
|
|
1217
|
+
`sandbox="allow-scripts allow-same-origin"`. With `srcDoc`, this gives
|
|
1218
|
+
the iframe the admin's origin, which 3rd-party embed widgets (YouTube SDK,
|
|
1219
|
+
x.com `widgets.js`) require — they refuse to initialise in an opaque-origin
|
|
1220
|
+
(`allow-scripts`-only) iframe because they need access to non-HttpOnly
|
|
1221
|
+
storage / cache and real-origin requests. Same-origin also gives the
|
|
1222
|
+
preview script access to the admin's auth state / non-HttpOnly storage /
|
|
1223
|
+
DOM and lets it issue authenticated same-origin XHR / fetch.
|
|
1224
|
+
|
|
1225
|
+
This is an explicit v1 design decision, not a no-op sandbox relax:
|
|
1226
|
+
**ampless v1 treats admin preview content / plugin script as trusted**.
|
|
1227
|
+
The engineer audits plugins before npm-installing them (customization-based
|
|
1228
|
+
CMS model), and body content is produced by trusted editors of this site.
|
|
1229
|
+
`<PostHistoryPanel>` can also surface a past revision authored by a
|
|
1230
|
+
different editor (revision author ≠ preview viewer) — v1 explicitly puts
|
|
1231
|
+
both inside the trust ring. The safer alternative — separate-origin preview
|
|
1232
|
+
route + CSP / COEP / COOP — is parked for v2.0+ if/when a real plugin
|
|
1233
|
+
marketplace lands.
|
|
1206
1234
|
|
|
1207
1235
|
---
|
|
1208
1236
|
|