@ampless/plugin-x-embed 1.0.0-alpha.1
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/LICENSE +21 -0
- package/README.ja.md +54 -0
- package/README.md +54 -0
- package/dist/chunk-6SPJOY2C.js +53 -0
- package/dist/editor.d.ts +27 -0
- package/dist/editor.js +83 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +55 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ampless contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ja.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @ampless/plugin-x-embed
|
|
2
|
+
|
|
3
|
+
> English: [README.md](./README.md)
|
|
4
|
+
|
|
5
|
+
ampless の投稿に x.com (Twitter) 埋め込みをインラインで表示するプラグイン。`https://x.com/<handle>/status/<id>` および `https://twitter.com/<handle>/status/<id>` 形式の URL を `<blockquote class="twitter-tweet">` として描画し、x の `widgets.js` がカード型の埋め込みに hydrate する。
|
|
6
|
+
|
|
7
|
+
## インストール
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm i @ampless/plugin-x-embed
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 配線
|
|
14
|
+
|
|
15
|
+
`cms.config.ts`:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { defineConfig } from 'ampless'
|
|
19
|
+
import xEmbedPlugin from '@ampless/plugin-x-embed'
|
|
20
|
+
|
|
21
|
+
export default defineConfig({
|
|
22
|
+
plugins: [xEmbedPlugin()],
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
tiptap エディタ側は `templates/_shared/app/(admin)/admin/_editor-bootstrap.tsx` で Node を登録する:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
'use client'
|
|
30
|
+
import { installAdminEditorExtensions } from '@ampless/admin/editor'
|
|
31
|
+
import { tweetEditor } from '@ampless/plugin-x-embed/editor'
|
|
32
|
+
|
|
33
|
+
export function EditorBootstrap({ children }: { children: React.ReactNode }) {
|
|
34
|
+
installAdminEditorExtensions([tweetEditor.extension])
|
|
35
|
+
return <>{children}</>
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
その上で `createAdminLayout(admin, { editorBootstrap: EditorBootstrap })` に渡す。
|
|
40
|
+
|
|
41
|
+
## ページレベルスクリプト (widgets.js)
|
|
42
|
+
|
|
43
|
+
本プラグインは `publicPostScript` capability を宣言している。`{await ampless.publicPostScriptsForPage([post])}` を呼んでいるテーマ(Phase 7 以降の first-party テーマはすべて該当)は、ページ上の投稿のいずれかに tweet 埋め込みが含まれる場合に `platform.twitter.com/widgets.js` を 1 回だけ出力する。
|
|
44
|
+
|
|
45
|
+
## CSP
|
|
46
|
+
|
|
47
|
+
ページレベルスクリプトは `platform.twitter.com/widgets.js` を読み込み、これが `<blockquote>` 要素を `platform.twitter.com` を src とする iframe に置き換える。サイト側 CSP には以下が必要:
|
|
48
|
+
|
|
49
|
+
- `script-src https://platform.twitter.com`
|
|
50
|
+
- `frame-src https://platform.twitter.com`
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @ampless/plugin-x-embed
|
|
2
|
+
|
|
3
|
+
> 日本語版: [README.ja.md](./README.ja.md)
|
|
4
|
+
|
|
5
|
+
Inline x.com (Twitter) embeds for ampless posts. Renders `https://x.com/<handle>/status/<id>` and `https://twitter.com/<handle>/status/<id>` URLs as `<blockquote class="twitter-tweet">` elements that x's `widgets.js` hydrates into the rich embed card.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm i @ampless/plugin-x-embed
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Wire up
|
|
14
|
+
|
|
15
|
+
`cms.config.ts`:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { defineConfig } from 'ampless'
|
|
19
|
+
import xEmbedPlugin from '@ampless/plugin-x-embed'
|
|
20
|
+
|
|
21
|
+
export default defineConfig({
|
|
22
|
+
plugins: [xEmbedPlugin()],
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For the tiptap editor side, register the Node in `templates/_shared/app/(admin)/admin/_editor-bootstrap.tsx`:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
'use client'
|
|
30
|
+
import { installAdminEditorExtensions } from '@ampless/admin/editor'
|
|
31
|
+
import { tweetEditor } from '@ampless/plugin-x-embed/editor'
|
|
32
|
+
|
|
33
|
+
export function EditorBootstrap({ children }: { children: React.ReactNode }) {
|
|
34
|
+
installAdminEditorExtensions([tweetEditor.extension])
|
|
35
|
+
return <>{children}</>
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then thread it into `createAdminLayout(admin, { editorBootstrap: EditorBootstrap })`.
|
|
40
|
+
|
|
41
|
+
## Page-level script (widgets.js)
|
|
42
|
+
|
|
43
|
+
The plugin declares the `publicPostScript` capability. Themes that already call `{await ampless.publicPostScriptsForPage([post])}` (the first-party themes all do as of Phase 7) automatically pick up `platform.twitter.com/widgets.js` — emitted once per page when any post on that page contains a tweet.
|
|
44
|
+
|
|
45
|
+
## CSP
|
|
46
|
+
|
|
47
|
+
The page-level script loads `platform.twitter.com/widgets.js`, which in turn hydrates `<blockquote>` elements into iframes pointing at `platform.twitter.com`. Your site's CSP needs:
|
|
48
|
+
|
|
49
|
+
- `script-src https://platform.twitter.com`
|
|
50
|
+
- `frame-src https://platform.twitter.com`
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/shared.tsx
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
var TWEET_URL = /^https:\/\/(?:x\.com|twitter\.com)\/[A-Za-z0-9_]{1,15}\/status\/(\d{1,25})(?:[?&#]\S*)?$/;
|
|
4
|
+
var TWEET_ID = /^\d{1,25}$/;
|
|
5
|
+
function TweetEmbed({ tweetId }) {
|
|
6
|
+
if (typeof tweetId !== "string" || !TWEET_ID.test(tweetId)) return null;
|
|
7
|
+
return /* @__PURE__ */ jsx("blockquote", { className: "twitter-tweet", "data-dnt": "true", children: /* @__PURE__ */ jsx("a", { href: `https://twitter.com/i/status/${tweetId}` }) });
|
|
8
|
+
}
|
|
9
|
+
function parseTweetUrl(url) {
|
|
10
|
+
const trimmed = url.trim();
|
|
11
|
+
const m = trimmed.match(TWEET_URL);
|
|
12
|
+
if (!m) return null;
|
|
13
|
+
return m[1] ?? null;
|
|
14
|
+
}
|
|
15
|
+
function hasTweetIn(post) {
|
|
16
|
+
if (post.format === "tiptap") {
|
|
17
|
+
return hasTweetNodeInTiptap(post.body);
|
|
18
|
+
}
|
|
19
|
+
if (post.format === "markdown") {
|
|
20
|
+
if (typeof post.body !== "string") return false;
|
|
21
|
+
return hasTweetUrlInMarkdown(post.body);
|
|
22
|
+
}
|
|
23
|
+
if (post.format === "html") {
|
|
24
|
+
if (typeof post.body !== "string") return false;
|
|
25
|
+
return post.body.includes("twitter-tweet");
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
function hasTweetNodeInTiptap(body) {
|
|
30
|
+
if (typeof body === "string") return body.includes("twitter-tweet");
|
|
31
|
+
if (!body || typeof body !== "object") return false;
|
|
32
|
+
const node = body;
|
|
33
|
+
if (node.type === "amplessTweet") return true;
|
|
34
|
+
if (Array.isArray(node.content)) {
|
|
35
|
+
for (const child of node.content) {
|
|
36
|
+
if (hasTweetNodeInTiptap(child)) return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
function hasTweetUrlInMarkdown(md) {
|
|
42
|
+
for (const line of md.split(/\r?\n/)) {
|
|
43
|
+
if (TWEET_URL.test(line.trim())) return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
TWEET_URL,
|
|
50
|
+
TweetEmbed,
|
|
51
|
+
parseTweetUrl,
|
|
52
|
+
hasTweetIn
|
|
53
|
+
};
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
|
|
3
|
+
declare module '@tiptap/core' {
|
|
4
|
+
interface Commands<ReturnType> {
|
|
5
|
+
amplessTweet: {
|
|
6
|
+
/** Insert a tweet embed node with the given tweet id. */
|
|
7
|
+
setTweet: (opts: {
|
|
8
|
+
tweetId: string;
|
|
9
|
+
}) => ReturnType;
|
|
10
|
+
/**
|
|
11
|
+
* Insert a tweet embed from a URL. Returns false (and does
|
|
12
|
+
* nothing) if the URL doesn't match the canonical x.com /
|
|
13
|
+
* twitter.com /status/ form.
|
|
14
|
+
*/
|
|
15
|
+
insertTweetFromUrl: (url: string) => ReturnType;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
declare const AmplessTweetNode: Node<any, any>;
|
|
20
|
+
/**
|
|
21
|
+
* Named export consumed by templates' `_editor-bootstrap.tsx`.
|
|
22
|
+
*/
|
|
23
|
+
declare const tweetEditor: {
|
|
24
|
+
extension: Node<any, any>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { AmplessTweetNode, tweetEditor };
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
TWEET_URL,
|
|
4
|
+
parseTweetUrl
|
|
5
|
+
} from "./chunk-6SPJOY2C.js";
|
|
6
|
+
|
|
7
|
+
// src/editor.tsx
|
|
8
|
+
import { Node, mergeAttributes } from "@tiptap/core";
|
|
9
|
+
var AmplessTweetNode = Node.create({
|
|
10
|
+
name: "amplessTweet",
|
|
11
|
+
group: "block",
|
|
12
|
+
atom: true,
|
|
13
|
+
selectable: true,
|
|
14
|
+
draggable: true,
|
|
15
|
+
addAttributes() {
|
|
16
|
+
return {
|
|
17
|
+
tweetId: {
|
|
18
|
+
default: "",
|
|
19
|
+
parseHTML: (el) => el.getAttribute("data-tweet-id") ?? "",
|
|
20
|
+
renderHTML: (attrs) => ({
|
|
21
|
+
"data-tweet-id": String(attrs.tweetId ?? "")
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
parseHTML() {
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
tag: "div[data-ampless-tweet]"
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
},
|
|
33
|
+
renderHTML({ HTMLAttributes }) {
|
|
34
|
+
return [
|
|
35
|
+
"div",
|
|
36
|
+
mergeAttributes(HTMLAttributes, {
|
|
37
|
+
"data-ampless-tweet": "",
|
|
38
|
+
class: "ampless-tweet-placeholder"
|
|
39
|
+
}),
|
|
40
|
+
["span", {}, `Tweet: ${HTMLAttributes["data-tweet-id"] ?? ""}`]
|
|
41
|
+
];
|
|
42
|
+
},
|
|
43
|
+
addCommands() {
|
|
44
|
+
return {
|
|
45
|
+
setTweet: (opts) => ({ commands }) => commands.insertContent({
|
|
46
|
+
type: this.name,
|
|
47
|
+
attrs: { tweetId: opts.tweetId }
|
|
48
|
+
}),
|
|
49
|
+
insertTweetFromUrl: (url) => ({ commands }) => {
|
|
50
|
+
const tweetId = parseTweetUrl(url);
|
|
51
|
+
if (!tweetId) return false;
|
|
52
|
+
return commands.insertContent({
|
|
53
|
+
type: this.name,
|
|
54
|
+
attrs: { tweetId }
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
addPasteRules() {
|
|
60
|
+
return [
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
{
|
|
63
|
+
find: TWEET_URL,
|
|
64
|
+
handler: ({ range, match, commands }) => {
|
|
65
|
+
const tweetId = match[1];
|
|
66
|
+
if (!tweetId) return;
|
|
67
|
+
commands.deleteRange(range);
|
|
68
|
+
commands.insertContent({
|
|
69
|
+
type: this.name,
|
|
70
|
+
attrs: { tweetId }
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
var tweetEditor = {
|
|
78
|
+
extension: AmplessTweetNode
|
|
79
|
+
};
|
|
80
|
+
export {
|
|
81
|
+
AmplessTweetNode,
|
|
82
|
+
tweetEditor
|
|
83
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { AmplessPlugin } from 'ampless';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tweet URL pattern. Accepts both `x.com` and `twitter.com` hosts, any
|
|
6
|
+
* valid handle (1-15 chars, [A-Za-z0-9_]), and a numeric status id
|
|
7
|
+
* (1-25 digits — far above any actual real tweet id but safely capped
|
|
8
|
+
* to prevent overflow / abuse). Anchored with `^...$` so the markdown
|
|
9
|
+
* walker only intercepts single-URL paragraphs.
|
|
10
|
+
*
|
|
11
|
+
* Captures:
|
|
12
|
+
* - Group 1: tweet status id
|
|
13
|
+
*/
|
|
14
|
+
declare const TWEET_URL: RegExp;
|
|
15
|
+
interface TweetEmbedProps {
|
|
16
|
+
tweetId: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Render a tweet as a `<blockquote class="twitter-tweet">` with a link
|
|
20
|
+
* to the canonical twitter.com URL. Widgets.js (injected via the
|
|
21
|
+
* plugin's `publicPostScript`) finds blockquotes with this class on
|
|
22
|
+
* page load and replaces them with the rich embed card.
|
|
23
|
+
*
|
|
24
|
+
* Defensive: an invalid `tweetId` (not matching the numeric pattern)
|
|
25
|
+
* renders nothing.
|
|
26
|
+
*/
|
|
27
|
+
declare function TweetEmbed({ tweetId }: TweetEmbedProps): ReactElement | null;
|
|
28
|
+
/**
|
|
29
|
+
* Extract the tweet id from a URL string. Returns `null` if the URL
|
|
30
|
+
* doesn't match the canonical x.com / twitter.com status form. Used
|
|
31
|
+
* by the tiptap editor's paste rule + the `contentFields` markdown
|
|
32
|
+
* walker + `hasTweetIn`.
|
|
33
|
+
*/
|
|
34
|
+
declare function parseTweetUrl(url: string): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* Scan a post body for any tweet embed. Used by the plugin's
|
|
37
|
+
* `publicPostScript` to decide whether widgets.js is actually needed
|
|
38
|
+
* for a given page — pages with no tweets don't pay for the script
|
|
39
|
+
* round trip.
|
|
40
|
+
*/
|
|
41
|
+
declare function hasTweetIn(post: {
|
|
42
|
+
format?: string;
|
|
43
|
+
body?: unknown;
|
|
44
|
+
}): boolean;
|
|
45
|
+
|
|
46
|
+
interface XEmbedPluginOptions {
|
|
47
|
+
/**
|
|
48
|
+
* Override the plugin's `name` (and admin-side namespace). Multi-
|
|
49
|
+
* instance is not currently supported by the contentFields registry.
|
|
50
|
+
*/
|
|
51
|
+
name?: string;
|
|
52
|
+
}
|
|
53
|
+
declare function xEmbedPlugin(opts?: XEmbedPluginOptions): AmplessPlugin;
|
|
54
|
+
|
|
55
|
+
export { TWEET_URL, TweetEmbed, type XEmbedPluginOptions, xEmbedPlugin as default, hasTweetIn, parseTweetUrl };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TWEET_URL,
|
|
3
|
+
TweetEmbed,
|
|
4
|
+
hasTweetIn,
|
|
5
|
+
parseTweetUrl
|
|
6
|
+
} from "./chunk-6SPJOY2C.js";
|
|
7
|
+
|
|
8
|
+
// src/index.tsx
|
|
9
|
+
import { definePlugin } from "ampless";
|
|
10
|
+
import { jsx } from "react/jsx-runtime";
|
|
11
|
+
function xEmbedPlugin(opts = {}) {
|
|
12
|
+
return definePlugin({
|
|
13
|
+
name: opts.name ?? "@ampless/plugin-x-embed",
|
|
14
|
+
apiVersion: 1,
|
|
15
|
+
packageName: "@ampless/plugin-x-embed",
|
|
16
|
+
trust_level: "trusted",
|
|
17
|
+
capabilities: ["contentFields", "publicPostScript"],
|
|
18
|
+
displayName: { en: "x.com (Twitter) embeds", ja: "x.com (Twitter) \u57CB\u3081\u8FBC\u307F" },
|
|
19
|
+
contentFields: [
|
|
20
|
+
{
|
|
21
|
+
kind: "tiptap",
|
|
22
|
+
nodeType: "amplessTweet",
|
|
23
|
+
render: (node) => {
|
|
24
|
+
const tweetId = String(node.attrs?.tweetId ?? "");
|
|
25
|
+
return /* @__PURE__ */ jsx(TweetEmbed, { tweetId });
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
kind: "markdown-url",
|
|
30
|
+
pattern: TWEET_URL,
|
|
31
|
+
render: ({ match }) => {
|
|
32
|
+
const tweetId = match[1] ?? "";
|
|
33
|
+
return /* @__PURE__ */ jsx(TweetEmbed, { tweetId });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
publicPostScript(post) {
|
|
38
|
+
if (!hasTweetIn(post)) return [];
|
|
39
|
+
return [
|
|
40
|
+
{
|
|
41
|
+
id: "amplessTweet:widgets",
|
|
42
|
+
src: "https://platform.twitter.com/widgets.js",
|
|
43
|
+
async: true
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
TWEET_URL,
|
|
51
|
+
TweetEmbed,
|
|
52
|
+
xEmbedPlugin as default,
|
|
53
|
+
hasTweetIn,
|
|
54
|
+
parseTweetUrl
|
|
55
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ampless/plugin-x-embed",
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "x.com (Twitter) embed plugin for ampless — renders tweet URLs inline as blockquotes hydrated by widgets.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./editor": {
|
|
13
|
+
"import": "./dist/editor.js",
|
|
14
|
+
"types": "./dist/editor.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/heavymoons/ampless.git",
|
|
28
|
+
"directory": "packages/plugin-x-embed"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/heavymoons/ampless/tree/main/packages/plugin-x-embed#readme",
|
|
31
|
+
"bugs": "https://github.com/heavymoons/ampless/issues",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@tiptap/core": "^3",
|
|
34
|
+
"react": "^18 || ^19",
|
|
35
|
+
"ampless": "1.0.0-alpha.42"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@tiptap/core": "^3.23.6",
|
|
39
|
+
"@types/react": "^19.2.15",
|
|
40
|
+
"@types/react-dom": "^19.2.3",
|
|
41
|
+
"react": "^19.2.6",
|
|
42
|
+
"react-dom": "^19.2.6"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"ampless",
|
|
46
|
+
"plugin",
|
|
47
|
+
"ampless-plugin",
|
|
48
|
+
"twitter",
|
|
49
|
+
"x.com",
|
|
50
|
+
"embed",
|
|
51
|
+
"cms"
|
|
52
|
+
],
|
|
53
|
+
"amplessPlugin": {
|
|
54
|
+
"apiVersion": 1,
|
|
55
|
+
"name": "@ampless/plugin-x-embed",
|
|
56
|
+
"trustLevel": "trusted",
|
|
57
|
+
"capabilities": [
|
|
58
|
+
"contentFields",
|
|
59
|
+
"publicPostScript"
|
|
60
|
+
],
|
|
61
|
+
"displayName": {
|
|
62
|
+
"en": "x.com (Twitter) embeds",
|
|
63
|
+
"ja": "x.com (Twitter) 埋め込み"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsup",
|
|
68
|
+
"dev": "tsup --watch",
|
|
69
|
+
"lint": "tsc --noEmit",
|
|
70
|
+
"test": "vitest run --passWithNoTests"
|
|
71
|
+
}
|
|
72
|
+
}
|