@riebeckite/plugin-text-fragment 0.0.14 → 0.0.15
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 +12 -7
- package/README_ja.md +9 -7
- package/dist/client.d.ts +1 -1
- package/dist/client.js +17 -7
- package/dist/index.d.ts +6 -2
- package/dist/index.js +22 -9
- package/dist/src/text-fragment.client.d.ts +12 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ you select in an article.
|
|
|
10
10
|
Client-only plugin. On page load it installs one selection popover with two
|
|
11
11
|
actions:
|
|
12
12
|
|
|
13
|
-
-
|
|
13
|
+
- **Copy link** — builds a URL with a
|
|
14
14
|
[Text Fragment directive](https://wicg.github.io/scroll-to-text-fragment/)
|
|
15
15
|
that highlights the selected text.
|
|
16
|
-
-
|
|
16
|
+
- **Copy quote** — builds a Markdown block quote with a link back to the page.
|
|
17
17
|
|
|
18
18
|
## Usage
|
|
19
19
|
|
|
@@ -28,7 +28,8 @@ export default defineConfig({
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
`textFragmentPlugin()` registers `style.css` and the `initTextFragmentShare`
|
|
31
|
-
client entry, which the app calls during page initialization.
|
|
31
|
+
client entry, which the app calls during page initialization. Pass
|
|
32
|
+
`textFragmentPlugin({ labels })` to override individual UI labels.
|
|
32
33
|
|
|
33
34
|
## Behavior
|
|
34
35
|
|
|
@@ -56,15 +57,19 @@ The fragment follows `#:~:text=[prefix-,]start[,end][,-suffix]`:
|
|
|
56
57
|
|
|
57
58
|
## API
|
|
58
59
|
|
|
59
|
-
- `textFragmentPlugin()` — plugin factory
|
|
60
|
-
|
|
60
|
+
- `textFragmentPlugin(options?)` — plugin factory; `options.labels` overrides
|
|
61
|
+
the UI labels
|
|
62
|
+
- `initTextFragmentShare(labels?)` — client initializer (also via
|
|
61
63
|
`@riebeckite/plugin-text-fragment/client`)
|
|
62
64
|
- `encodeTextFragment(text)` — percent-encodes one text fragment term
|
|
63
65
|
- `buildTextFragmentUrl(pageUrl, selection, options?)` — builds the deep link;
|
|
64
66
|
`options` is `{ prefix?, suffix? }`
|
|
65
67
|
- `buildQuoteMarkdown({ url, title, selection })` — builds the Markdown quote
|
|
66
|
-
-
|
|
68
|
+
- `DEFAULT_TEXT_FRAGMENT_LABELS` — the default English UI labels
|
|
69
|
+
- Types: `TextFragmentOptions`, `TextFragmentLabels`,
|
|
70
|
+
`TextFragmentPluginOptions`
|
|
67
71
|
|
|
68
72
|
## See also
|
|
69
73
|
|
|
70
|
-
- [Plugin guide](../../../docs/en/reference/plugin-api.md)
|
|
74
|
+
- [Plugin guide](../../../docs/en/docs/reference/plugin-api.md)
|
|
75
|
+
|
package/README_ja.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
クライアント専用のプラグインです。ページ表示時に、選択範囲のそばへ小さなポップオーバーを出し、次の二つをコピーできます。
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
11
|
+
- **Copy link**: 選択したテキストをハイライトする [Text Fragment](https://wicg.github.io/scroll-to-text-fragment/) 付き URL を作ります。
|
|
12
|
+
- **Copy quote**: ページへのリンク付きで Markdown の引用ブロックを作ります。
|
|
13
13
|
|
|
14
14
|
## 設定する
|
|
15
15
|
|
|
@@ -23,7 +23,7 @@ export default defineConfig({
|
|
|
23
23
|
});
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
`textFragmentPlugin()` はスタイルと `initTextFragmentShare`
|
|
26
|
+
`textFragmentPlugin()` はスタイルと `initTextFragmentShare` を登録します。初期化処理はアプリのページ初期化時に呼ばれます。`textFragmentPlugin({ labels })` で UI ラベルだけを差し替えられます。
|
|
27
27
|
|
|
28
28
|
## 挙動
|
|
29
29
|
|
|
@@ -45,13 +45,15 @@ export default defineConfig({
|
|
|
45
45
|
|
|
46
46
|
## 公開 API
|
|
47
47
|
|
|
48
|
-
- `textFragmentPlugin()` —
|
|
49
|
-
- `initTextFragmentShare()` — ブラウザ初期化関数(`@riebeckite/plugin-text-fragment/client` からも読み込める)
|
|
48
|
+
- `textFragmentPlugin(options?)` — プラグインファクトリ。`options.labels` で UI ラベルを上書きする
|
|
49
|
+
- `initTextFragmentShare(labels?)` — ブラウザ初期化関数(`@riebeckite/plugin-text-fragment/client` からも読み込める)
|
|
50
50
|
- `encodeTextFragment(text)` — テキスト片をパーセントエンコードする
|
|
51
51
|
- `buildTextFragmentUrl(pageUrl, selection, options?)` — ディープリンクを作る。`options` は `{ prefix?, suffix? }`
|
|
52
52
|
- `buildQuoteMarkdown({ url, title, selection })` — 引用ブロックを作る
|
|
53
|
-
- `
|
|
53
|
+
- `DEFAULT_TEXT_FRAGMENT_LABELS` — 既定の英語 UI ラベル
|
|
54
|
+
- `TextFragmentOptions`、`TextFragmentLabels`、`TextFragmentPluginOptions` — 型
|
|
54
55
|
|
|
55
56
|
## 関連資料
|
|
56
57
|
|
|
57
|
-
- [プラグインシステム](../../../docs/ja/reference/plugin-api.md)
|
|
58
|
+
- [プラグインシステム](../../../docs/ja/docs/reference/plugin-api.md)
|
|
59
|
+
|
package/dist/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { initTextFragmentShare } from "./src/text-fragment.client.js";
|
|
1
|
+
export { DEFAULT_TEXT_FRAGMENT_LABELS, initTextFragmentShare, type TextFragmentLabels, } from "./src/text-fragment.client.js";
|
package/dist/client.js
CHANGED
|
@@ -53,20 +53,29 @@ function stripUrlFragment(url) {
|
|
|
53
53
|
var ARTICLE_SELECTOR = "[data-slot='article-body'], .rb-article-body, .prose, article";
|
|
54
54
|
var EXCLUDED_SELECTOR = "pre, code, a[href], [data-no-share]";
|
|
55
55
|
var POPOVER_GAP = 8;
|
|
56
|
+
var DEFAULT_TEXT_FRAGMENT_LABELS = {
|
|
57
|
+
regionLabel: "Share selected text",
|
|
58
|
+
copyLinkLabel: "Copy link",
|
|
59
|
+
copyQuoteLabel: "Copy quote",
|
|
60
|
+
linkCopiedLabel: "Link copied",
|
|
61
|
+
quoteCopiedLabel: "Quote copied",
|
|
62
|
+
copyFailedLabel: "Could not copy. Select the text again."
|
|
63
|
+
};
|
|
56
64
|
var initialized = false;
|
|
57
|
-
function initTextFragmentShare() {
|
|
65
|
+
function initTextFragmentShare(labels = {}) {
|
|
58
66
|
if (typeof document === "undefined") return;
|
|
59
67
|
if (initialized) return;
|
|
60
68
|
initialized = true;
|
|
69
|
+
const resolved = { ...DEFAULT_TEXT_FRAGMENT_LABELS, ...labels };
|
|
61
70
|
const popover = document.createElement("div");
|
|
62
71
|
popover.className = "rr-text-fragment";
|
|
63
72
|
popover.hidden = true;
|
|
64
73
|
popover.setAttribute("role", "group");
|
|
65
|
-
popover.setAttribute("aria-label",
|
|
74
|
+
popover.setAttribute("aria-label", resolved.regionLabel);
|
|
66
75
|
const actions = document.createElement("div");
|
|
67
76
|
actions.className = "rr-text-fragment__actions";
|
|
68
|
-
const linkButton = createButton(
|
|
69
|
-
const quoteButton = createButton(
|
|
77
|
+
const linkButton = createButton(resolved.copyLinkLabel);
|
|
78
|
+
const quoteButton = createButton(resolved.copyQuoteLabel);
|
|
70
79
|
const status = document.createElement("p");
|
|
71
80
|
status.className = "rr-text-fragment__status";
|
|
72
81
|
status.setAttribute("role", "status");
|
|
@@ -104,7 +113,7 @@ function initTextFragmentShare() {
|
|
|
104
113
|
isCopying = true;
|
|
105
114
|
try {
|
|
106
115
|
const copied = await copyToClipboard(buildValue(selection.text));
|
|
107
|
-
status.textContent = copied ? successMessage :
|
|
116
|
+
status.textContent = copied ? successMessage : resolved.copyFailedLabel;
|
|
108
117
|
active = selection;
|
|
109
118
|
popover.hidden = false;
|
|
110
119
|
positionPopover(popover, selection.rect);
|
|
@@ -117,7 +126,7 @@ function initTextFragmentShare() {
|
|
|
117
126
|
linkButton.addEventListener("click", () => {
|
|
118
127
|
void copy(
|
|
119
128
|
(selection) => buildTextFragmentUrl(resolvePageUrl(), selection),
|
|
120
|
-
|
|
129
|
+
resolved.linkCopiedLabel
|
|
121
130
|
);
|
|
122
131
|
});
|
|
123
132
|
quoteButton.addEventListener("click", () => {
|
|
@@ -127,7 +136,7 @@ function initTextFragmentShare() {
|
|
|
127
136
|
title: document.title,
|
|
128
137
|
selection
|
|
129
138
|
}),
|
|
130
|
-
|
|
139
|
+
resolved.quoteCopiedLabel
|
|
131
140
|
);
|
|
132
141
|
});
|
|
133
142
|
popover.addEventListener("mousedown", (event) => event.preventDefault());
|
|
@@ -232,5 +241,6 @@ function copyWithExecCommand(value) {
|
|
|
232
241
|
return copied;
|
|
233
242
|
}
|
|
234
243
|
export {
|
|
244
|
+
DEFAULT_TEXT_FRAGMENT_LABELS,
|
|
235
245
|
initTextFragmentShare
|
|
236
246
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { type RiebeckitePlugin } from "@riebeckite/core";
|
|
2
|
-
|
|
2
|
+
import { type TextFragmentLabels } from "./src/text-fragment.client.js";
|
|
3
|
+
export { DEFAULT_TEXT_FRAGMENT_LABELS, initTextFragmentShare, type TextFragmentLabels, } from "./src/text-fragment.client.js";
|
|
3
4
|
export { buildQuoteMarkdown, buildTextFragmentUrl, encodeTextFragment, type TextFragmentOptions, } from "./src/text-fragment.js";
|
|
5
|
+
export type TextFragmentPluginOptions = {
|
|
6
|
+
labels?: Partial<TextFragmentLabels>;
|
|
7
|
+
};
|
|
4
8
|
/**
|
|
5
9
|
* Registers the client-only text fragment share plugin: a selection popover
|
|
6
10
|
* that copies a `#:~:text=` deep link or a Markdown quote.
|
|
7
11
|
*/
|
|
8
|
-
export declare function textFragmentPlugin(): RiebeckitePlugin;
|
|
12
|
+
export declare function textFragmentPlugin(options?: TextFragmentPluginOptions): RiebeckitePlugin;
|
package/dist/index.js
CHANGED
|
@@ -60,20 +60,29 @@ function stripUrlFragment(url) {
|
|
|
60
60
|
var ARTICLE_SELECTOR = "[data-slot='article-body'], .rb-article-body, .prose, article";
|
|
61
61
|
var EXCLUDED_SELECTOR = "pre, code, a[href], [data-no-share]";
|
|
62
62
|
var POPOVER_GAP = 8;
|
|
63
|
+
var DEFAULT_TEXT_FRAGMENT_LABELS = {
|
|
64
|
+
regionLabel: "Share selected text",
|
|
65
|
+
copyLinkLabel: "Copy link",
|
|
66
|
+
copyQuoteLabel: "Copy quote",
|
|
67
|
+
linkCopiedLabel: "Link copied",
|
|
68
|
+
quoteCopiedLabel: "Quote copied",
|
|
69
|
+
copyFailedLabel: "Could not copy. Select the text again."
|
|
70
|
+
};
|
|
63
71
|
var initialized = false;
|
|
64
|
-
function initTextFragmentShare() {
|
|
72
|
+
function initTextFragmentShare(labels = {}) {
|
|
65
73
|
if (typeof document === "undefined") return;
|
|
66
74
|
if (initialized) return;
|
|
67
75
|
initialized = true;
|
|
76
|
+
const resolved = { ...DEFAULT_TEXT_FRAGMENT_LABELS, ...labels };
|
|
68
77
|
const popover = document.createElement("div");
|
|
69
78
|
popover.className = "rr-text-fragment";
|
|
70
79
|
popover.hidden = true;
|
|
71
80
|
popover.setAttribute("role", "group");
|
|
72
|
-
popover.setAttribute("aria-label",
|
|
81
|
+
popover.setAttribute("aria-label", resolved.regionLabel);
|
|
73
82
|
const actions = document.createElement("div");
|
|
74
83
|
actions.className = "rr-text-fragment__actions";
|
|
75
|
-
const linkButton = createButton(
|
|
76
|
-
const quoteButton = createButton(
|
|
84
|
+
const linkButton = createButton(resolved.copyLinkLabel);
|
|
85
|
+
const quoteButton = createButton(resolved.copyQuoteLabel);
|
|
77
86
|
const status = document.createElement("p");
|
|
78
87
|
status.className = "rr-text-fragment__status";
|
|
79
88
|
status.setAttribute("role", "status");
|
|
@@ -111,7 +120,7 @@ function initTextFragmentShare() {
|
|
|
111
120
|
isCopying = true;
|
|
112
121
|
try {
|
|
113
122
|
const copied = await copyToClipboard(buildValue(selection.text));
|
|
114
|
-
status.textContent = copied ? successMessage :
|
|
123
|
+
status.textContent = copied ? successMessage : resolved.copyFailedLabel;
|
|
115
124
|
active = selection;
|
|
116
125
|
popover.hidden = false;
|
|
117
126
|
positionPopover(popover, selection.rect);
|
|
@@ -124,7 +133,7 @@ function initTextFragmentShare() {
|
|
|
124
133
|
linkButton.addEventListener("click", () => {
|
|
125
134
|
void copy(
|
|
126
135
|
(selection) => buildTextFragmentUrl(resolvePageUrl(), selection),
|
|
127
|
-
|
|
136
|
+
resolved.linkCopiedLabel
|
|
128
137
|
);
|
|
129
138
|
});
|
|
130
139
|
quoteButton.addEventListener("click", () => {
|
|
@@ -134,7 +143,7 @@ function initTextFragmentShare() {
|
|
|
134
143
|
title: document.title,
|
|
135
144
|
selection
|
|
136
145
|
}),
|
|
137
|
-
|
|
146
|
+
resolved.quoteCopiedLabel
|
|
138
147
|
);
|
|
139
148
|
});
|
|
140
149
|
popover.addEventListener("mousedown", (event) => event.preventDefault());
|
|
@@ -240,16 +249,20 @@ function copyWithExecCommand(value) {
|
|
|
240
249
|
}
|
|
241
250
|
|
|
242
251
|
// index.ts
|
|
243
|
-
function textFragmentPlugin() {
|
|
252
|
+
function textFragmentPlugin(options = {}) {
|
|
244
253
|
return definePlugin({
|
|
245
254
|
name: "text-fragment",
|
|
246
255
|
assets: [createStyleAsset("text-fragment")],
|
|
247
256
|
clientEntries: [
|
|
248
|
-
createClientEntry("text-fragment", "initTextFragmentShare"
|
|
257
|
+
createClientEntry("text-fragment", "initTextFragmentShare", {
|
|
258
|
+
...DEFAULT_TEXT_FRAGMENT_LABELS,
|
|
259
|
+
...options.labels
|
|
260
|
+
})
|
|
249
261
|
]
|
|
250
262
|
});
|
|
251
263
|
}
|
|
252
264
|
export {
|
|
265
|
+
DEFAULT_TEXT_FRAGMENT_LABELS,
|
|
253
266
|
buildQuoteMarkdown,
|
|
254
267
|
buildTextFragmentUrl,
|
|
255
268
|
encodeTextFragment,
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
export type TextFragmentLabels = {
|
|
2
|
+
regionLabel: string;
|
|
3
|
+
copyLinkLabel: string;
|
|
4
|
+
copyQuoteLabel: string;
|
|
5
|
+
linkCopiedLabel: string;
|
|
6
|
+
quoteCopiedLabel: string;
|
|
7
|
+
copyFailedLabel: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const DEFAULT_TEXT_FRAGMENT_LABELS: TextFragmentLabels;
|
|
1
10
|
/**
|
|
2
|
-
* Enables a popover with
|
|
3
|
-
*
|
|
11
|
+
* Enables a popover with copy-link (Text Fragment deep link) and copy-quote
|
|
12
|
+
* (Markdown quote) actions for the current text selection.
|
|
4
13
|
*
|
|
5
14
|
* Client-only: returns immediately when there is no `document`, and only wires
|
|
6
15
|
* its listeners once per page.
|
|
7
16
|
*/
|
|
8
|
-
export declare function initTextFragmentShare(): void;
|
|
17
|
+
export declare function initTextFragmentShare(labels?: Partial<TextFragmentLabels>): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-text-fragment",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"./style.css": "./style.css"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@riebeckite/core": "0.0.
|
|
24
|
+
"@riebeckite/core": "0.0.15"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsx": "^4.22.4"
|