create-ampless 1.0.0-beta.170 → 1.0.0-beta.172

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.
@@ -186,6 +186,7 @@ interface AmplessPlugin {
186
186
  publicBodyEnd?(ctx): readonly PublicBodyDescriptor[]
187
187
  publicBodyForPost?(post: Post, ctx): readonly PublicPostBodyDescriptor[]
188
188
  publicHtmlForPost?(post: Post, ctx): readonly PublicPostHtmlDescriptor[]
189
+ tiptapNodeToMarkdown?: TiptapNodeMarkdownAdapters // server-safe markdown export adapters
189
190
  ogImage?: OgImageConfig
190
191
  settings?: {
191
192
  public?: readonly PluginSettingField[]
@@ -875,6 +876,48 @@ export function EditorBootstrap({ children }: { children: React.ReactNode }) {
875
876
  }
876
877
  ```
877
878
 
879
+ ### アダプターの置き場所: `./editor.tsx` ではなく `./adapters.ts`
880
+
881
+ `./editor.tsx` は `'use client'` かつ `@tiptap/core` を import している —
882
+ admin バンドルには問題ないが、server コード(や将来の `postToMarkdown`
883
+ public runtime)からこれを import すると両方を巻き込んでしまう。アダプター
884
+ (および `Node.renderHTML` と共有する `placeholderAttrs` のような plain
885
+ object ヘルパ)は、tiptap 非依存の別モジュール `./adapters.ts` に置き、
886
+ `./editor.tsx` からは 2 つの named symbol を **re-export** する:
887
+
888
+ ```ts
889
+ // packages/plugin-youtube/src/adapters.ts — 'use client' なし、@tiptap/* import なし
890
+ export const tiptapNodeToMarkdown: TiptapNodeMarkdownAdapters = { /* ... */ }
891
+ export const tiptapNodeToHtml: TiptapNodeHtmlAdapters = { /* ... */ }
892
+ ```
893
+
894
+ ```ts
895
+ // packages/plugin-youtube/src/editor.tsx
896
+ export { tiptapNodeToMarkdown, tiptapNodeToHtml } from './adapters.js'
897
+ ```
898
+
899
+ この re-export により `update-ampless` の codegen 契約は無改修で維持される
900
+ (下記「配線」の通り、`./editor` の namespace import から `ns.tiptapNodeToMarkdown ?? {}` /
901
+ `ns.tiptapNodeToHtml ?? {}` を読む挙動は変わらない)。同時に server 側
902
+ entry(`./index.tsx`)も同じアダプターを `./adapters.js` から import して
903
+ manifest に設定できる:
904
+
905
+ ```ts
906
+ // packages/plugin-youtube/src/index.tsx
907
+ import { tiptapNodeToMarkdown } from './adapters.js'
908
+
909
+ export default function youtubePlugin(opts = {}) {
910
+ return definePlugin({
911
+ // ...
912
+ tiptapNodeToMarkdown, // AmplessPlugin.tiptapNodeToMarkdown — server 側 canonical
913
+ })
914
+ }
915
+ ```
916
+
917
+ `definePlugin()` は `contentFields` の `kind: 'tiptap'` エントリの
918
+ `nodeType` に対応する `tiptapNodeToMarkdown` のキーが無い場合に warn する
919
+ — 両方をセットで宣言し、warning が出ない状態を保つ。
920
+
878
921
  ### フォーマット切り替えの可逆アダプター(`tiptapNodeToMarkdown` + `tiptapNodeToHtml`)
879
922
 
880
923
  operator が admin UI でポストのフォーマットを切り替える場合(例: `tiptap → markdown`、`tiptap → html`)、admin はボディコンテンツを変換する必要がある。通常の prose node は tiptap の built-in レンダラーで処理されるが、**atom node**(`amplessYoutube` のような embed ブロック)は子要素を持たず、children が空のまま fallthrough し、embed が無音で消えてしまう。
@@ -911,6 +954,7 @@ embed node を持つが `htmlPlaceholder` を**宣言しない** plugin は従
911
954
  **文字列**(空文字 `''` も含む)を返すと、その出力を使う。**`null`** を返すとデフォルトの switch へ fallthrough する(対応しない node や video id が欠損している場合などに使う)。
912
955
 
913
956
  ```ts
957
+ // packages/plugin-youtube/src/adapters.ts
914
958
  import type { TiptapNodeMarkdownAdapters, TiptapNodeHtmlAdapters } from 'ampless'
915
959
 
916
960
  export const tiptapNodeToMarkdown: TiptapNodeMarkdownAdapters = {
@@ -939,7 +983,7 @@ export const tiptapNodeToHtml: TiptapNodeHtmlAdapters = {
939
983
 
940
984
  #### 配線
941
985
 
942
- `update-ampless` が各プラグインの `./editor` モジュールから `tiptapNodeToMarkdown` と `tiptapNodeToHtml` の named export を読み取り、両方の install に自動で配線する。**手動での配線は不要。** プラグインがいずれかのマップを export しない場合、生成ファイルの `?? {}` fallback が no-op になる。
986
+ `update-ampless` が各プラグインの `./editor` モジュールから `tiptapNodeToMarkdown` と `tiptapNodeToHtml` の named export を読み取り、両方の install に自動で配線する。**手動での配線は不要。** プラグインがいずれかのマップを export しない場合、生成ファイルの `?? {}` fallback が no-op になる。上記の通り、`./editor` が re-export するこれらの export は通常 `./adapters.ts` に実装されている — codegen は `./editor` の namespace から到達可能であることだけを見ており、定義場所は問わない。
943
987
 
944
988
  #### `markdown → html` 2-hop
945
989
 
@@ -214,6 +214,7 @@ interface AmplessPlugin {
214
214
  publicBodyEnd?(ctx): readonly PublicBodyDescriptor[]
215
215
  publicBodyForPost?(post: Post, ctx): readonly PublicPostBodyDescriptor[]
216
216
  publicHtmlForPost?(post: Post, ctx): readonly PublicPostHtmlDescriptor[]
217
+ tiptapNodeToMarkdown?: TiptapNodeMarkdownAdapters // server-safe markdown export adapters
217
218
  ogImage?: OgImageConfig
218
219
  settings?: {
219
220
  public?: readonly PluginSettingField[]
@@ -1132,6 +1133,48 @@ export function EditorBootstrap({ children }: { children: React.ReactNode }) {
1132
1133
  }
1133
1134
  ```
1134
1135
 
1136
+ ### Where the adapters live: `./adapters.ts`, not `./editor.tsx`
1137
+
1138
+ `./editor.tsx` carries `'use client'` and imports `@tiptap/core` — fine for
1139
+ the admin bundle, but importing it from server code (or the future
1140
+ `postToMarkdown` public runtime) would drag both along. Put the adapters
1141
+ (and any plain-object helpers they share with `Node.renderHTML`, like
1142
+ `placeholderAttrs`) in a separate, tiptap-free module — `./adapters.ts` —
1143
+ and have `./editor.tsx` **re-export** the two named symbols:
1144
+
1145
+ ```ts
1146
+ // packages/plugin-youtube/src/adapters.ts — no 'use client', no @tiptap/* import
1147
+ export const tiptapNodeToMarkdown: TiptapNodeMarkdownAdapters = { /* ... */ }
1148
+ export const tiptapNodeToHtml: TiptapNodeHtmlAdapters = { /* ... */ }
1149
+ ```
1150
+
1151
+ ```ts
1152
+ // packages/plugin-youtube/src/editor.tsx
1153
+ export { tiptapNodeToMarkdown, tiptapNodeToHtml } from './adapters.js'
1154
+ ```
1155
+
1156
+ The re-export keeps `update-ampless`'s codegen contract intact (it still
1157
+ reads `ns.tiptapNodeToMarkdown ?? {}` / `ns.tiptapNodeToHtml ?? {}` from a
1158
+ namespace import of `./editor` — see Wiring below) while also letting your
1159
+ server entry (`./index.tsx`) import the same adapter from `./adapters.js`
1160
+ and set it on the manifest:
1161
+
1162
+ ```ts
1163
+ // packages/plugin-youtube/src/index.tsx
1164
+ import { tiptapNodeToMarkdown } from './adapters.js'
1165
+
1166
+ export default function youtubePlugin(opts = {}) {
1167
+ return definePlugin({
1168
+ // ...
1169
+ tiptapNodeToMarkdown, // AmplessPlugin.tiptapNodeToMarkdown — server-side canonical
1170
+ })
1171
+ }
1172
+ ```
1173
+
1174
+ `definePlugin()` warns if a `contentFields` `kind: 'tiptap'` entry's
1175
+ `nodeType` has no matching key in `tiptapNodeToMarkdown` — declare both
1176
+ together so the warning stays silent.
1177
+
1135
1178
  ### Lossless format-switch adapters (`tiptapNodeToMarkdown` + `tiptapNodeToHtml`)
1136
1179
 
1137
1180
  When the operator switches the post format in the admin UI (e.g. `tiptap →
@@ -1196,7 +1239,7 @@ Return **`null`** to fall through to the default switch (useful for nodes
1196
1239
  you don't handle or for degenerate inputs like a missing video id).
1197
1240
 
1198
1241
  ```ts
1199
- // packages/plugin-youtube/src/editor.tsx
1242
+ // packages/plugin-youtube/src/adapters.ts
1200
1243
  import type { TiptapNodeMarkdownAdapters, TiptapNodeHtmlAdapters } from 'ampless'
1201
1244
 
1202
1245
  export const tiptapNodeToMarkdown: TiptapNodeMarkdownAdapters = {
@@ -1232,7 +1275,10 @@ export const tiptapNodeToHtml: TiptapNodeHtmlAdapters = {
1232
1275
  named exports from each plugin's `./editor` module (via namespace import `*
1233
1276
  as`) and wires them into both installs automatically — **no hand-wiring
1234
1277
  required**. If your plugin does not export one of the maps, the `?? {}`
1235
- fallback in the generated file is a no-op.
1278
+ fallback in the generated file is a no-op. As noted above, the exports
1279
+ `./editor` re-exports normally live in `./adapters.ts` — the codegen only
1280
+ cares that they're reachable from the `./editor` namespace, not where
1281
+ they're defined.
1236
1282
 
1237
1283
  #### `markdown → html` 2-hop
1238
1284
 
@@ -26,21 +26,21 @@
26
26
  "@tiptap/pm": "^3.23.6",
27
27
  "@tiptap/react": "^3.23.6",
28
28
  "@tiptap/starter-kit": "^3.23.6",
29
- "@ampless/plugin-analytics-ga4": "^0.2.0-beta.38",
30
- "@ampless/plugin-cookie-consent": "^0.1.0-beta.29",
31
- "@ampless/plugin-gtm": "^0.2.0-beta.37",
32
- "@ampless/plugin-og-image": "^0.2.0-beta.54",
33
- "@ampless/plugin-plausible": "^0.2.0-beta.37",
34
- "@ampless/plugin-reading-time": "^0.1.0-beta.27",
35
- "@ampless/plugin-rss": "^0.2.0-beta.54",
36
- "@ampless/plugin-schema-jsonld": "^0.1.1-beta.33",
37
- "@ampless/plugin-seo": "^0.2.0-beta.54",
38
- "@ampless/plugin-webhook": "^0.2.0-beta.55",
39
- "@ampless/admin": "^1.0.0-beta.101",
40
- "@ampless/backend": "^1.0.0-beta.84",
41
- "@ampless/runtime": "^1.0.0-beta.66",
29
+ "@ampless/plugin-analytics-ga4": "^0.2.0-beta.39",
30
+ "@ampless/plugin-cookie-consent": "^0.1.0-beta.30",
31
+ "@ampless/plugin-gtm": "^0.2.0-beta.38",
32
+ "@ampless/plugin-og-image": "^0.2.0-beta.55",
33
+ "@ampless/plugin-plausible": "^0.2.0-beta.38",
34
+ "@ampless/plugin-reading-time": "^0.1.0-beta.28",
35
+ "@ampless/plugin-rss": "^0.2.0-beta.55",
36
+ "@ampless/plugin-schema-jsonld": "^0.1.1-beta.34",
37
+ "@ampless/plugin-seo": "^0.2.0-beta.55",
38
+ "@ampless/plugin-webhook": "^0.2.0-beta.56",
39
+ "@ampless/admin": "^1.0.0-beta.102",
40
+ "@ampless/backend": "^1.0.0-beta.85",
41
+ "@ampless/runtime": "^1.0.0-beta.67",
42
42
  "@digital-go-jp/tailwind-theme-plugin": "^0.3.4",
43
- "ampless": "^1.0.0-beta.54",
43
+ "ampless": "^1.0.0-beta.55",
44
44
  "aws-amplify": "^6.17.0",
45
45
  "class-variance-authority": "^0.7.1",
46
46
  "clsx": "^2.1.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ampless",
3
- "version": "1.0.0-beta.170",
3
+ "version": "1.0.0-beta.172",
4
4
  "description": "Create a new ampless project",
5
5
  "license": "MIT",
6
6
  "type": "module",