@riebeckite/plugin-shortcodes 0.0.18 → 0.0.20
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 +44 -31
- package/README_ja.md +37 -26
- package/dist/index.d.ts +4 -4
- package/dist/index.js +66 -13
- package/dist/src/builtins.d.ts +1 -0
- package/dist/src/remark.d.ts +1 -0
- package/dist/src/render.d.ts +1 -0
- package/dist/src/types.d.ts +4 -1
- package/package.json +3 -3
- package/style.css +2 -1
package/README.md
CHANGED
|
@@ -6,13 +6,15 @@ A generic shortcode system for Markdown, built on `remark-directive`.
|
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
9
|
-
`shortcodes()` turns `remark-directive` syntax into HTML at Markdown time.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
`shortcodes()` turns `remark-directive` syntax into HTML at Markdown time. It
|
|
10
|
+
supports inline shortcodes (`:name[label]{key=value}`), block leaf shortcodes
|
|
11
|
+
(`::name[label]{key=value}`), and container shortcodes
|
|
12
|
+
(`:::name[label]{attrs}` … `:::`), and ships an extensible registry so projects
|
|
13
|
+
can add their own renderers on top of the built-ins.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
`div
|
|
15
|
+
Inline shortcodes render as a `span` inside the surrounding paragraph; block and
|
|
16
|
+
container shortcodes render as a `div`. Every wrapper carries
|
|
17
|
+
`rb-shortcode rb-shortcode--<name>`.
|
|
16
18
|
|
|
17
19
|
## Usage
|
|
18
20
|
|
|
@@ -31,6 +33,8 @@ Styles ship in `style.css`.
|
|
|
31
33
|
## Syntax
|
|
32
34
|
|
|
33
35
|
```
|
|
36
|
+
:badge[New]{variant=success}
|
|
37
|
+
|
|
34
38
|
::kbd[Ctrl+S]
|
|
35
39
|
|
|
36
40
|
::youtube[id=dQw4w9WgXcQ]
|
|
@@ -40,30 +44,34 @@ Container bodies support **Markdown**.
|
|
|
40
44
|
:::
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
-
|
|
47
|
+
- `:name[label]{key=value}` — inline shortcode, rendered as a `span` inside the
|
|
48
|
+
current paragraph. Only names in `inlineShortcodes` can be used inline;
|
|
49
|
+
built-ins opt in with `badge`, `kbd`, `link-card`, and `file`.
|
|
50
|
+
- `::name[label]{key=value}` — block leaf shortcode, rendered as a `div`.
|
|
44
51
|
- `:::name[label]{key=value}` … `:::` — container shortcode; the body is
|
|
45
52
|
rendered by the normal Markdown pipeline.
|
|
46
53
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
A shortcode that is only defined as a block emits a
|
|
55
|
+
`shortcodes-inline-unsupported` diagnostic when written with `:` and stays on
|
|
56
|
+
the page as escaped text. Unknown shortcodes emit a `shortcodes-unknown`
|
|
57
|
+
diagnostic, and malformed attributes emit `shortcodes-invalid` and are ignored.
|
|
50
58
|
|
|
51
59
|
## Built-in shortcodes
|
|
52
60
|
|
|
53
|
-
| Name | Kind | Attributes | Output |
|
|
54
|
-
| ---- | ---- | ---------- | ------ |
|
|
55
|
-
| `figure` | leaf / container | `src`/`url`/`image`, `alt`, `caption`, `width`, `height` | `<figure>` with image and caption |
|
|
56
|
-
| `youtube` | leaf | `id`/`video` or `url`/`src`, `title` | Privacy-friendly `youtube-nocookie.com` embed |
|
|
57
|
-
| `vimeo` | leaf | `id`/`video` or `url`/`src`, `title` | `player.vimeo.com` embed (`dnt=1`) |
|
|
58
|
-
| `gist` | leaf | `user` + `id`, or `url`, `file` | GitHub Gist embed with `<noscript>` link |
|
|
59
|
-
| `kbd` | leaf | label or `keys` | `<kbd>` elements split on `+` |
|
|
60
|
-
| `badge` | leaf | label or `text`, `variant`/`type`/`color`, `title` | Inline badge |
|
|
61
|
-
| `details` | container | label or `summary`, `open` | `<details>` disclosure |
|
|
62
|
-
| `spoiler` | container | label or `summary`, `open` | `details` alias with a different class |
|
|
63
|
-
| `note` | leaf / container | label or `title`, `type`/`variant` | Callout box |
|
|
64
|
-
| `callout` | leaf / container | label or `title`, `type`/`variant` | `note` alias with a different class |
|
|
65
|
-
| `link-card` | leaf | `url`/`href`, `title`, `description`, `image`/`icon` | Link preview card |
|
|
66
|
-
| `file` | leaf | `url`/`src`/`path`, `name`/`label`, `size` | Download link |
|
|
61
|
+
| Name | Kind | Inline | Attributes | Output |
|
|
62
|
+
| ---- | ---- | ------ | ---------- | ------ |
|
|
63
|
+
| `figure` | leaf / container | – | `src`/`url`/`image`, `alt`, `caption`, `width`, `height` | `<figure>` with image and caption |
|
|
64
|
+
| `youtube` | leaf | – | `id`/`video` or `url`/`src`, `title` | Privacy-friendly `youtube-nocookie.com` embed |
|
|
65
|
+
| `vimeo` | leaf | – | `id`/`video` or `url`/`src`, `title` | `player.vimeo.com` embed (`dnt=1`) |
|
|
66
|
+
| `gist` | leaf | – | `user` + `id`, or `url`, `file` | GitHub Gist embed with `<noscript>` link |
|
|
67
|
+
| `kbd` | leaf | yes | label or `keys` | `<kbd>` elements split on `+` |
|
|
68
|
+
| `badge` | leaf | yes | label or `text`, `variant`/`type`/`color`, `title` | Inline badge |
|
|
69
|
+
| `details` | container | – | label or `summary`, `open` | `<details>` disclosure |
|
|
70
|
+
| `spoiler` | container | – | label or `summary`, `open` | `details` alias with a different class |
|
|
71
|
+
| `note` | leaf / container | – | label or `title`, `type`/`variant` | Callout box |
|
|
72
|
+
| `callout` | leaf / container | – | label or `title`, `type`/`variant` | `note` alias with a different class |
|
|
73
|
+
| `link-card` | leaf | yes | `url`/`href`, `title`, `description`, `image`/`icon` | Link preview card |
|
|
74
|
+
| `file` | leaf | yes | `url`/`src`/`path`, `name`/`label`, `size` | Download link |
|
|
67
75
|
|
|
68
76
|
## Options
|
|
69
77
|
|
|
@@ -73,6 +81,7 @@ ignored.
|
|
|
73
81
|
| `language` | `string` | – | BCP-47 tag applied to wrappers as `lang` |
|
|
74
82
|
| `builtins` | `boolean` | `true` | Register the built-in renderers |
|
|
75
83
|
| `shortcodes` | `Record<string, ShortcodeRenderer>` | `{}` | Custom renderers, merged over the built-ins |
|
|
84
|
+
| `inlineShortcodes` | `readonly string[]` | `[]` | Extra names allowed in the inline `:` form |
|
|
76
85
|
|
|
77
86
|
## Custom renderers
|
|
78
87
|
|
|
@@ -83,16 +92,19 @@ shortcodes({
|
|
|
83
92
|
shortcodes: {
|
|
84
93
|
mark: ({ label, attributes }) => `<mark>${label}</mark>`,
|
|
85
94
|
},
|
|
95
|
+
inlineShortcodes: ["mark"],
|
|
86
96
|
});
|
|
87
97
|
```
|
|
88
98
|
|
|
89
99
|
A `ShortcodeRenderer` receives `{ name, label, attributes, childrenHtml,
|
|
90
|
-
context, container }` and returns a string.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
context, container }` and returns a string. A custom renderer can be used with
|
|
101
|
+
the inline `:` form only when its name is listed in `inlineShortcodes`. For
|
|
102
|
+
container shortcodes the plugin wraps the result in
|
|
103
|
+
`<div class="rb-shortcode rb-shortcode--<name>">` and replaces `childrenHtml`
|
|
104
|
+
with the rendered body, so container renderers must echo `input.childrenHtml`
|
|
105
|
+
where the body belongs. Renderers are synchronous and must escape any user
|
|
106
|
+
input themselves — `escapeHtml` and `escapeHtmlAttribute` are re-exported from
|
|
107
|
+
`@riebeckite/core`.
|
|
96
108
|
|
|
97
109
|
## Exports
|
|
98
110
|
|
|
@@ -101,11 +113,12 @@ re-exported from `@riebeckite/core`.
|
|
|
101
113
|
- `renderShortcode(request, options)` — render a single shortcode
|
|
102
114
|
- `resolveShortcodeOptions(options?)` — normalize options
|
|
103
115
|
- `builtinShortcodes`, `builtinShortcodeNames` — the built-in registry
|
|
116
|
+
- `builtinInlineShortcodes` — built-in names allowed in the inline `:` form
|
|
104
117
|
- Types: `ShortcodeRenderer`, `ShortcodeOptions`, `ResolvedShortcodeOptions`,
|
|
105
118
|
`ShortcodeRenderInput`, `ShortcodeRenderRequest`, `ShortcodeAttributes`,
|
|
106
119
|
`RemarkShortcodesOptions`
|
|
107
120
|
|
|
108
121
|
## See also
|
|
109
122
|
|
|
110
|
-
- [Plugin guide](../../../docs/docs/reference/plugin-api.
|
|
123
|
+
- [Plugin guide](../../../docs/docs/reference/plugin-api.md)
|
|
111
124
|
|
package/README_ja.md
CHANGED
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
## 概要
|
|
8
8
|
|
|
9
9
|
`shortcodes()` は `remark-directive` の記法を Markdown 処理時に HTML へ変換
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
します。インライン型(`:name[label]{key=value}`)、ブロックのリーフ型
|
|
11
|
+
(`::name[label]{key=value}`)、コンテナ型(`:::name[label]{attrs}` … `:::`)
|
|
12
|
+
に対応し、組み込みレンダラーに独自のレンダラーを重ねられる拡張可能な
|
|
13
|
+
レジストリを備えます。
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
インライン型は段落の中の `span` として、リーフ型とコンテナ型は `div` として
|
|
16
|
+
描画されます。ラッパーには `rb-shortcode rb-shortcode--<name>` が付きます。
|
|
16
17
|
|
|
17
18
|
## 使い方
|
|
18
19
|
|
|
@@ -31,6 +32,8 @@ export default defineConfig({
|
|
|
31
32
|
## 記法
|
|
32
33
|
|
|
33
34
|
```
|
|
35
|
+
:badge[新着]{variant=success}
|
|
36
|
+
|
|
34
37
|
::kbd[Ctrl+S]
|
|
35
38
|
|
|
36
39
|
::youtube[id=dQw4w9WgXcQ]
|
|
@@ -40,30 +43,34 @@ export default defineConfig({
|
|
|
40
43
|
:::
|
|
41
44
|
```
|
|
42
45
|
|
|
43
|
-
-
|
|
46
|
+
- `:name[label]{key=value}` — インライン型。現在の段落の中の `span` として
|
|
47
|
+
描画されます。インラインで使えるのは `inlineShortcodes` に含まれる名前だけ
|
|
48
|
+
で、組み込みでは `badge`、`kbd`、`link-card`、`file` が該当します。
|
|
49
|
+
- `::name[label]{key=value}` — ブロックのリーフ型。`div` として描画されます。
|
|
44
50
|
- `:::name[label]{key=value}` … `:::` — コンテナ型。本文は通常の Markdown
|
|
45
51
|
パイプラインで描画されます。
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
ブロック専用のショートコードを `:` で書くと
|
|
54
|
+
`shortcodes-inline-unsupported` 診断を出し、エスケープしたテキストとして
|
|
55
|
+
ページに残します。未知のショートコードは `shortcodes-unknown` 診断を出し、
|
|
56
|
+
不正な属性は `shortcodes-invalid` を出して無視します。
|
|
50
57
|
|
|
51
58
|
## 組み込みショートコード
|
|
52
59
|
|
|
53
|
-
| 名前 | 種類 | 属性 | 出力 |
|
|
54
|
-
| ---- | ---- | ---- | ---- |
|
|
55
|
-
| `figure` | リーフ / コンテナ | `src`/`url`/`image`, `alt`, `caption`, `width`, `height` | 画像とキャプションの `<figure>` |
|
|
56
|
-
| `youtube` | リーフ | `id`/`video` または `url`/`src`, `title` | `youtube-nocookie.com` のプライバシー配慮埋め込み |
|
|
57
|
-
| `vimeo` | リーフ | `id`/`video` または `url`/`src`, `title` | `player.vimeo.com` 埋め込み(`dnt=1`) |
|
|
58
|
-
| `gist` | リーフ | `user` + `id`、または `url`, `file` | `<noscript>` リンク付きの Gist 埋め込み |
|
|
59
|
-
| `kbd` | リーフ | ラベルまたは `keys` | `+` で分割した `<kbd>` |
|
|
60
|
-
| `badge` | リーフ | ラベルまたは `text`, `variant`/`type`/`color`, `title` | インラインバッジ |
|
|
61
|
-
| `details` | コンテナ | ラベルまたは `summary`, `open` | `<details>` 折りたたみ |
|
|
62
|
-
| `spoiler` | コンテナ | ラベルまたは `summary`, `open` | クラス違いの `details` エイリアス |
|
|
63
|
-
| `note` | リーフ / コンテナ | ラベルまたは `title`, `type`/`variant` | コールアウト |
|
|
64
|
-
| `callout` | リーフ / コンテナ | ラベルまたは `title`, `type`/`variant` | クラス違いの `note` エイリアス |
|
|
65
|
-
| `link-card` | リーフ | `url`/`href`, `title`, `description`, `image`/`icon` | リンクプレビューカード |
|
|
66
|
-
| `file` | リーフ | `url`/`src`/`path`, `name`/`label`, `size` | ダウンロードリンク |
|
|
60
|
+
| 名前 | 種類 | インライン | 属性 | 出力 |
|
|
61
|
+
| ---- | ---- | ---------- | ---- | ---- |
|
|
62
|
+
| `figure` | リーフ / コンテナ | – | `src`/`url`/`image`, `alt`, `caption`, `width`, `height` | 画像とキャプションの `<figure>` |
|
|
63
|
+
| `youtube` | リーフ | – | `id`/`video` または `url`/`src`, `title` | `youtube-nocookie.com` のプライバシー配慮埋め込み |
|
|
64
|
+
| `vimeo` | リーフ | – | `id`/`video` または `url`/`src`, `title` | `player.vimeo.com` 埋め込み(`dnt=1`) |
|
|
65
|
+
| `gist` | リーフ | – | `user` + `id`、または `url`, `file` | `<noscript>` リンク付きの Gist 埋め込み |
|
|
66
|
+
| `kbd` | リーフ | 可 | ラベルまたは `keys` | `+` で分割した `<kbd>` |
|
|
67
|
+
| `badge` | リーフ | 可 | ラベルまたは `text`, `variant`/`type`/`color`, `title` | インラインバッジ |
|
|
68
|
+
| `details` | コンテナ | – | ラベルまたは `summary`, `open` | `<details>` 折りたたみ |
|
|
69
|
+
| `spoiler` | コンテナ | – | ラベルまたは `summary`, `open` | クラス違いの `details` エイリアス |
|
|
70
|
+
| `note` | リーフ / コンテナ | – | ラベルまたは `title`, `type`/`variant` | コールアウト |
|
|
71
|
+
| `callout` | リーフ / コンテナ | – | ラベルまたは `title`, `type`/`variant` | クラス違いの `note` エイリアス |
|
|
72
|
+
| `link-card` | リーフ | 可 | `url`/`href`, `title`, `description`, `image`/`icon` | リンクプレビューカード |
|
|
73
|
+
| `file` | リーフ | 可 | `url`/`src`/`path`, `name`/`label`, `size` | ダウンロードリンク |
|
|
67
74
|
|
|
68
75
|
## オプション
|
|
69
76
|
|
|
@@ -73,6 +80,7 @@ export default defineConfig({
|
|
|
73
80
|
| `language` | `string` | – | ラッパーの `lang` に付与する BCP-47 タグ |
|
|
74
81
|
| `builtins` | `boolean` | `true` | 組み込みレンダラーを登録する |
|
|
75
82
|
| `shortcodes` | `Record<string, ShortcodeRenderer>` | `{}` | 組み込みに重ねる独自レンダラー |
|
|
83
|
+
| `inlineShortcodes` | `readonly string[]` | `[]` | インラインの `:` 形式で使える名前に追加する |
|
|
76
84
|
|
|
77
85
|
## 独自レンダラー
|
|
78
86
|
|
|
@@ -83,12 +91,14 @@ shortcodes({
|
|
|
83
91
|
shortcodes: {
|
|
84
92
|
mark: ({ label, attributes }) => `<mark>${label}</mark>`,
|
|
85
93
|
},
|
|
94
|
+
inlineShortcodes: ["mark"],
|
|
86
95
|
});
|
|
87
96
|
```
|
|
88
97
|
|
|
89
98
|
`ShortcodeRenderer` は `{ name, label, attributes, childrenHtml, context,
|
|
90
|
-
container }`
|
|
91
|
-
|
|
99
|
+
container }` を受け取り、文字列を返します。独自レンダラーをインラインの `:`
|
|
100
|
+
形式で使うには、その名前を `inlineShortcodes` に追加します。コンテナ型では
|
|
101
|
+
結果が `<div class="rb-shortcode rb-shortcode--<name>">` でラップされ、
|
|
92
102
|
`childrenHtml` の位置に本文が差し込まれます。コンテナ用レンダラーは本文を
|
|
93
103
|
置きたい位置で `input.childrenHtml` をそのまま出力してください。レンダラーは
|
|
94
104
|
同期関数で、ユーザー入力のエスケープは各自で行う必要があります
|
|
@@ -102,11 +112,12 @@ container }` を受け取り、文字列を返します。コンテナ型では
|
|
|
102
112
|
- `renderShortcode(request, options)` — 単一ショートコードの描画
|
|
103
113
|
- `resolveShortcodeOptions(options?)` — オプションの正規化
|
|
104
114
|
- `builtinShortcodes`, `builtinShortcodeNames` — 組み込みレジストリ
|
|
115
|
+
- `builtinInlineShortcodes` — インラインの `:` 形式で使える組み込み名
|
|
105
116
|
- 型: `ShortcodeRenderer`, `ShortcodeOptions`, `ResolvedShortcodeOptions`,
|
|
106
117
|
`ShortcodeRenderInput`, `ShortcodeRenderRequest`, `ShortcodeAttributes`,
|
|
107
118
|
`RemarkShortcodesOptions`
|
|
108
119
|
|
|
109
120
|
## 関連
|
|
110
121
|
|
|
111
|
-
- [プラグインガイド](../../../docs/docs/reference/plugin-api.md)
|
|
122
|
+
- [プラグインガイド](../../../docs/docs/reference/plugin-api.ja.md)
|
|
112
123
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { builtinShortcodeNames, builtinShortcodes } from "./src/builtins.js";
|
|
2
|
-
import { DIAGNOSTIC_INVALID, DIAGNOSTIC_UNKNOWN, remarkShortcodes, SHORTCODES_SOURCE } from "./src/remark.js";
|
|
3
|
-
import { createShortcodeRenderContext, DEFAULT_SHORTCODE_CLASS_NAME, renderShortcode, resolveShortcodeOptions, SHORTCODE_CHILDREN_MARKER } from "./src/render.js";
|
|
1
|
+
import { builtinInlineShortcodes, builtinShortcodeNames, builtinShortcodes } from "./src/builtins.js";
|
|
2
|
+
import { DIAGNOSTIC_INLINE_UNSUPPORTED, DIAGNOSTIC_INVALID, DIAGNOSTIC_UNKNOWN, remarkShortcodes, SHORTCODES_SOURCE } from "./src/remark.js";
|
|
3
|
+
import { createShortcodeRenderContext, DEFAULT_SHORTCODE_CLASS_NAME, isInlineShortcode, renderShortcode, resolveShortcodeOptions, SHORTCODE_CHILDREN_MARKER } from "./src/render.js";
|
|
4
4
|
import type { ShortcodeOptions } from "./src/types.js";
|
|
5
5
|
export type { DirectiveNode, RemarkShortcodesOptions, ResolvedShortcodeOptions, ShortcodeAttributes, ShortcodeOptions, ShortcodeRenderer, ShortcodeRenderInput, ShortcodeRenderRequest, } from "./src/types.js";
|
|
6
|
-
export { builtinShortcodeNames, builtinShortcodes, createShortcodeRenderContext, DEFAULT_SHORTCODE_CLASS_NAME, DIAGNOSTIC_INVALID, DIAGNOSTIC_UNKNOWN, remarkShortcodes, renderShortcode, resolveShortcodeOptions, SHORTCODE_CHILDREN_MARKER, SHORTCODES_SOURCE, };
|
|
6
|
+
export { builtinInlineShortcodes, builtinShortcodeNames, builtinShortcodes, createShortcodeRenderContext, DEFAULT_SHORTCODE_CLASS_NAME, DIAGNOSTIC_INLINE_UNSUPPORTED, DIAGNOSTIC_INVALID, DIAGNOSTIC_UNKNOWN, isInlineShortcode, remarkShortcodes, renderShortcode, resolveShortcodeOptions, SHORTCODE_CHILDREN_MARKER, SHORTCODES_SOURCE, };
|
|
7
7
|
export declare function shortcodes(options?: ShortcodeOptions): import("@riebeckite/core").RiebeckitePlugin<ShortcodeOptions>;
|
|
8
8
|
export declare const shortcodesPlugin: typeof shortcodes;
|
package/dist/index.js
CHANGED
|
@@ -206,6 +206,12 @@ var builtinShortcodes = {
|
|
|
206
206
|
"link-card": renderLinkCard,
|
|
207
207
|
file: renderFile
|
|
208
208
|
};
|
|
209
|
+
var builtinInlineShortcodes = [
|
|
210
|
+
"badge",
|
|
211
|
+
"kbd",
|
|
212
|
+
"link-card",
|
|
213
|
+
"file"
|
|
214
|
+
];
|
|
209
215
|
var builtinShortcodeNames = Object.keys(builtinShortcodes);
|
|
210
216
|
|
|
211
217
|
// src/remark.ts
|
|
@@ -236,14 +242,24 @@ function resolveShortcodeOptions(options = {}) {
|
|
|
236
242
|
const builtins = options.builtins !== false;
|
|
237
243
|
const custom = options.shortcodes ?? {};
|
|
238
244
|
const shortcodes2 = builtins ? { ...builtinShortcodes, ...custom } : { ...custom };
|
|
245
|
+
const inlineShortcodes = new Set(
|
|
246
|
+
builtins ? builtinInlineShortcodes : []
|
|
247
|
+
);
|
|
248
|
+
for (const name of options.inlineShortcodes ?? []) {
|
|
249
|
+
inlineShortcodes.add(name);
|
|
250
|
+
}
|
|
239
251
|
const resolved = {
|
|
240
252
|
className: options.className ?? DEFAULT_SHORTCODE_CLASS_NAME,
|
|
241
253
|
builtins,
|
|
242
|
-
shortcodes: shortcodes2
|
|
254
|
+
shortcodes: shortcodes2,
|
|
255
|
+
inlineShortcodes
|
|
243
256
|
};
|
|
244
257
|
if (options.language !== void 0) resolved.language = options.language;
|
|
245
258
|
return resolved;
|
|
246
259
|
}
|
|
260
|
+
function isInlineShortcode(name, options) {
|
|
261
|
+
return options.inlineShortcodes.has(name);
|
|
262
|
+
}
|
|
247
263
|
function createShortcodeRenderContext(input) {
|
|
248
264
|
return {
|
|
249
265
|
contentIndex: input.contentIndex ?? /* @__PURE__ */ new Map(),
|
|
@@ -272,6 +288,7 @@ function renderShortcode(request, options) {
|
|
|
272
288
|
url: firstUrl(attributes)
|
|
273
289
|
});
|
|
274
290
|
const container = request.container ?? false;
|
|
291
|
+
const block = request.block ?? container;
|
|
275
292
|
const input = {
|
|
276
293
|
name: request.name,
|
|
277
294
|
label: request.label ?? "",
|
|
@@ -283,10 +300,10 @@ function renderShortcode(request, options) {
|
|
|
283
300
|
input.childrenHtml = request.childrenHtml;
|
|
284
301
|
}
|
|
285
302
|
const body = renderer(input);
|
|
286
|
-
return wrapShortcode(body, request.name,
|
|
303
|
+
return wrapShortcode(body, request.name, block, options);
|
|
287
304
|
}
|
|
288
|
-
function wrapShortcode(body, name,
|
|
289
|
-
const tag =
|
|
305
|
+
function wrapShortcode(body, name, block, options) {
|
|
306
|
+
const tag = block ? "div" : "span";
|
|
290
307
|
const classes = `${options.className} ${options.className}--${name}`;
|
|
291
308
|
const languageAttribute = options.language === void 0 ? "" : ` lang="${escapeHtmlAttribute2(options.language)}"`;
|
|
292
309
|
return `<${tag} class="${escapeHtmlAttribute2(
|
|
@@ -305,6 +322,7 @@ function firstUrl(attributes) {
|
|
|
305
322
|
var SHORTCODES_SOURCE = "@riebeckite/plugin-shortcodes";
|
|
306
323
|
var DIAGNOSTIC_UNKNOWN = "shortcodes-unknown";
|
|
307
324
|
var DIAGNOSTIC_INVALID = "shortcodes-invalid";
|
|
325
|
+
var DIAGNOSTIC_INLINE_UNSUPPORTED = "shortcodes-inline-unsupported";
|
|
308
326
|
var ATTRIBUTE_NAME_PATTERN = /^[A-Za-z_][\w-]*$/;
|
|
309
327
|
function remarkShortcodes(options = {}) {
|
|
310
328
|
const resolved = resolveShortcodeOptions(options);
|
|
@@ -312,7 +330,7 @@ function remarkShortcodes(options = {}) {
|
|
|
312
330
|
const targets = [];
|
|
313
331
|
visit(
|
|
314
332
|
tree,
|
|
315
|
-
["containerDirective", "leafDirective"],
|
|
333
|
+
["containerDirective", "leafDirective", "textDirective"],
|
|
316
334
|
(node, index, parent) => {
|
|
317
335
|
if (parent === void 0 || index === void 0) return;
|
|
318
336
|
targets.push({ node, index, parent });
|
|
@@ -326,10 +344,37 @@ function remarkShortcodes(options = {}) {
|
|
|
326
344
|
function transformDirective(target, resolved, options, file) {
|
|
327
345
|
const { node, index, parent } = target;
|
|
328
346
|
const name = node.name;
|
|
347
|
+
const inline = node.type === "textDirective";
|
|
329
348
|
const container = node.type === "containerDirective";
|
|
330
349
|
const { label, children } = extractLabel(node);
|
|
331
350
|
const attributes = normalizeAttributes(node, file);
|
|
332
351
|
const childrenHtml = container ? SHORTCODE_CHILDREN_MARKER : void 0;
|
|
352
|
+
if (inline && !isInlineShortcode(name, resolved)) {
|
|
353
|
+
const known = Object.hasOwn(resolved.shortcodes, name);
|
|
354
|
+
report(
|
|
355
|
+
file,
|
|
356
|
+
known ? DIAGNOSTIC_INLINE_UNSUPPORTED : DIAGNOSTIC_UNKNOWN,
|
|
357
|
+
known ? `Shortcode ":${name}" is block-only and cannot be used inline.` : `Unknown shortcode ":${name}" was left as escaped text.`,
|
|
358
|
+
node
|
|
359
|
+
);
|
|
360
|
+
parent.children.splice(
|
|
361
|
+
index,
|
|
362
|
+
1,
|
|
363
|
+
...createFallback(
|
|
364
|
+
resolved.className,
|
|
365
|
+
name,
|
|
366
|
+
label,
|
|
367
|
+
attributes,
|
|
368
|
+
{
|
|
369
|
+
container: false,
|
|
370
|
+
block: false,
|
|
371
|
+
modifier: known ? "inline-unsupported" : "unknown"
|
|
372
|
+
},
|
|
373
|
+
children
|
|
374
|
+
)
|
|
375
|
+
);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
333
378
|
const html = renderShortcode(
|
|
334
379
|
{
|
|
335
380
|
name,
|
|
@@ -337,6 +382,7 @@ function transformDirective(target, resolved, options, file) {
|
|
|
337
382
|
attributes,
|
|
338
383
|
childrenHtml,
|
|
339
384
|
container,
|
|
385
|
+
block: !inline,
|
|
340
386
|
context: createShortcodeRenderContext({
|
|
341
387
|
name,
|
|
342
388
|
label,
|
|
@@ -363,7 +409,7 @@ function transformDirective(target, resolved, options, file) {
|
|
|
363
409
|
name,
|
|
364
410
|
label,
|
|
365
411
|
attributes,
|
|
366
|
-
container,
|
|
412
|
+
{ container, block: !inline, modifier: "unknown" },
|
|
367
413
|
children
|
|
368
414
|
)
|
|
369
415
|
);
|
|
@@ -431,11 +477,14 @@ function normalizeAttributes(node, file) {
|
|
|
431
477
|
}
|
|
432
478
|
return attributes;
|
|
433
479
|
}
|
|
434
|
-
function createFallback(className, name, label, attributes,
|
|
435
|
-
const classes = `${className} ${className}
|
|
480
|
+
function createFallback(className, name, label, attributes, shape, children) {
|
|
481
|
+
const classes = `${className} ${className}--${shape.modifier}`;
|
|
436
482
|
const dataName = ` data-shortcode-name="${escapeHtmlAttribute3(name)}"`;
|
|
437
|
-
const
|
|
438
|
-
|
|
483
|
+
const inline = !shape.container && !shape.block;
|
|
484
|
+
const directive = escapeHtml2(
|
|
485
|
+
sourceText(name, label, attributes, shape.container, inline)
|
|
486
|
+
);
|
|
487
|
+
if (shape.container) {
|
|
439
488
|
return [
|
|
440
489
|
createHtml(
|
|
441
490
|
`<div class="${escapeHtmlAttribute3(classes)}"${dataName}>${directive}`
|
|
@@ -444,14 +493,15 @@ function createFallback(className, name, label, attributes, container, children)
|
|
|
444
493
|
createHtml("</div>")
|
|
445
494
|
];
|
|
446
495
|
}
|
|
496
|
+
const tag = shape.block ? "div" : "span";
|
|
447
497
|
return [
|
|
448
498
|
createHtml(
|
|
449
|
-
|
|
499
|
+
`<${tag} class="${escapeHtmlAttribute3(classes)}"${dataName}>${directive}</${tag}>`
|
|
450
500
|
)
|
|
451
501
|
];
|
|
452
502
|
}
|
|
453
|
-
function sourceText(name, label, attributes, container) {
|
|
454
|
-
const fence = container ? ":::" : "::";
|
|
503
|
+
function sourceText(name, label, attributes, container, inline) {
|
|
504
|
+
const fence = container ? ":::" : inline ? ":" : "::";
|
|
455
505
|
const labelPart = label ? `[${label}]` : "";
|
|
456
506
|
return `${fence}${name}${labelPart}${attributesText(attributes)}`;
|
|
457
507
|
}
|
|
@@ -503,13 +553,16 @@ function shortcodes(options = {}) {
|
|
|
503
553
|
var shortcodesPlugin = shortcodes;
|
|
504
554
|
export {
|
|
505
555
|
DEFAULT_SHORTCODE_CLASS_NAME,
|
|
556
|
+
DIAGNOSTIC_INLINE_UNSUPPORTED,
|
|
506
557
|
DIAGNOSTIC_INVALID,
|
|
507
558
|
DIAGNOSTIC_UNKNOWN,
|
|
508
559
|
SHORTCODES_SOURCE,
|
|
509
560
|
SHORTCODE_CHILDREN_MARKER,
|
|
561
|
+
builtinInlineShortcodes,
|
|
510
562
|
builtinShortcodeNames,
|
|
511
563
|
builtinShortcodes,
|
|
512
564
|
createShortcodeRenderContext,
|
|
565
|
+
isInlineShortcode,
|
|
513
566
|
remarkShortcodes,
|
|
514
567
|
renderShortcode,
|
|
515
568
|
resolveShortcodeOptions,
|
package/dist/src/builtins.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ShortcodeRenderInput } from "./types.js";
|
|
2
2
|
/** Built-in renderers keyed by directive name. */
|
|
3
3
|
export declare const builtinShortcodes: Record<string, (input: ShortcodeRenderInput) => string>;
|
|
4
|
+
export declare const builtinInlineShortcodes: readonly string[];
|
|
4
5
|
export declare const builtinShortcodeNames: readonly string[];
|
package/dist/src/remark.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ import type { RemarkShortcodesOptions } from "./types.js";
|
|
|
3
3
|
export declare const SHORTCODES_SOURCE = "@riebeckite/plugin-shortcodes";
|
|
4
4
|
export declare const DIAGNOSTIC_UNKNOWN = "shortcodes-unknown";
|
|
5
5
|
export declare const DIAGNOSTIC_INVALID = "shortcodes-invalid";
|
|
6
|
+
export declare const DIAGNOSTIC_INLINE_UNSUPPORTED = "shortcodes-inline-unsupported";
|
|
6
7
|
export declare function remarkShortcodes(options?: RemarkShortcodesOptions): (tree: Root, file: unknown) => void;
|
package/dist/src/render.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const DEFAULT_SHORTCODE_CLASS_NAME = "rb-shortcode";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const SHORTCODE_CHILDREN_MARKER = "\0rb-shortcodes:children\0";
|
|
10
10
|
export declare function resolveShortcodeOptions(options?: ShortcodeOptions): ResolvedShortcodeOptions;
|
|
11
|
+
export declare function isInlineShortcode(name: string, options: ResolvedShortcodeOptions): boolean;
|
|
11
12
|
export declare function createShortcodeRenderContext(input: {
|
|
12
13
|
name: string;
|
|
13
14
|
label?: string;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -31,12 +31,14 @@ export type ShortcodeOptions = {
|
|
|
31
31
|
builtins?: boolean;
|
|
32
32
|
/** Custom renderers, merged on top of the built-ins by name. */
|
|
33
33
|
shortcodes?: Record<string, ShortcodeRenderer>;
|
|
34
|
+
inlineShortcodes?: readonly string[];
|
|
34
35
|
};
|
|
35
36
|
export type ResolvedShortcodeOptions = {
|
|
36
37
|
className: string;
|
|
37
38
|
language?: string;
|
|
38
39
|
builtins: boolean;
|
|
39
40
|
shortcodes: Record<string, ShortcodeRenderer>;
|
|
41
|
+
inlineShortcodes: ReadonlySet<string>;
|
|
40
42
|
};
|
|
41
43
|
/** Input accepted by {@link renderShortcode}. */
|
|
42
44
|
export type ShortcodeRenderRequest = {
|
|
@@ -45,6 +47,7 @@ export type ShortcodeRenderRequest = {
|
|
|
45
47
|
attributes?: ShortcodeAttributes;
|
|
46
48
|
childrenHtml?: string;
|
|
47
49
|
container?: boolean;
|
|
50
|
+
block?: boolean;
|
|
48
51
|
context?: PluginRenderContext;
|
|
49
52
|
};
|
|
50
53
|
/**
|
|
@@ -56,7 +59,7 @@ export type RemarkShortcodesOptions = ShortcodeOptions & {
|
|
|
56
59
|
contentIndex?: Map<string, string>;
|
|
57
60
|
contentSource?: ContentSource;
|
|
58
61
|
};
|
|
59
|
-
export type DirectiveName = "leafDirective" | "containerDirective";
|
|
62
|
+
export type DirectiveName = "textDirective" | "leafDirective" | "containerDirective";
|
|
60
63
|
export type DirectiveNode = Parent & {
|
|
61
64
|
type: DirectiveName;
|
|
62
65
|
name: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-shortcodes",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@types/mdast": "^4.0.4",
|
|
19
19
|
"unist-util-visit": "^5.1.0",
|
|
20
|
-
"@riebeckite/core": "0.0.
|
|
20
|
+
"@riebeckite/core": "0.0.20"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"tsx": "^4.22.4",
|
|
24
|
-
"@riebeckite/test": "0.0.
|
|
24
|
+
"@riebeckite/test": "0.0.20"
|
|
25
25
|
},
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
package/style.css
CHANGED
|
@@ -245,7 +245,8 @@ div.rb-shortcode {
|
|
|
245
245
|
|
|
246
246
|
/* fallback ---------------------------------------------------------------- */
|
|
247
247
|
|
|
248
|
-
.rb-shortcode--unknown
|
|
248
|
+
.rb-shortcode--unknown,
|
|
249
|
+
.rb-shortcode--inline-unsupported {
|
|
249
250
|
color: var(--rb-shortcode-accent);
|
|
250
251
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
251
252
|
font-size: 0.875em;
|