@railway/inkwell 1.1.1 → 1.3.0
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.cjs +34 -16
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +34 -16
- package/package.json +1 -1
- package/src/styles.css +145 -96
package/dist/index.cjs
CHANGED
|
@@ -1377,6 +1377,7 @@ var InkwellEditorClient = react.forwardRef(
|
|
|
1377
1377
|
);
|
|
1378
1378
|
const overLimit = characterLimit !== void 0 && characterCount > characterLimit;
|
|
1379
1379
|
const hasCharacterLimit = characterLimit !== void 0;
|
|
1380
|
+
const showCharacterCount = characterLimit !== void 0 && characterCount >= characterLimit * 0.8;
|
|
1380
1381
|
const getEditorState = react.useCallback(() => {
|
|
1381
1382
|
const content2 = serializeContent();
|
|
1382
1383
|
return {
|
|
@@ -2026,7 +2027,7 @@ var InkwellEditorClient = react.forwardRef(
|
|
|
2026
2027
|
className: `inkwell-editor-wrapper${hasCharacterLimit ? " inkwell-editor-has-character-limit" : ""}${overLimit ? " inkwell-editor-over-limit" : ""}${className ? ` ${className}` : ""}${classNames?.root ? ` ${classNames.root}` : ""}`,
|
|
2027
2028
|
style: styles?.root,
|
|
2028
2029
|
children: [
|
|
2029
|
-
|
|
2030
|
+
showCharacterCount && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2030
2031
|
CharacterCount,
|
|
2031
2032
|
{
|
|
2032
2033
|
count: characterCount,
|
|
@@ -2185,16 +2186,41 @@ var insertUploadedAttachment = (file, options) => {
|
|
|
2185
2186
|
options.onError?.(err, file);
|
|
2186
2187
|
});
|
|
2187
2188
|
};
|
|
2188
|
-
function
|
|
2189
|
+
function routeFiles(editor, files, options) {
|
|
2189
2190
|
const { accept } = options;
|
|
2191
|
+
const matching = accept ? files.filter((f) => mimeMatches(f.type, accept)) : files;
|
|
2192
|
+
const handled = matching.filter(
|
|
2193
|
+
(f) => isImageFile(f) || options.onAttachmentAdd !== void 0
|
|
2194
|
+
);
|
|
2195
|
+
for (const file of handled) {
|
|
2196
|
+
if (isImageFile(file)) {
|
|
2197
|
+
insertUploadedImage(editor, file, options);
|
|
2198
|
+
} else {
|
|
2199
|
+
insertUploadedAttachment(file, options);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
const skipped = files.filter((f) => !handled.includes(f));
|
|
2203
|
+
return { handled, skipped };
|
|
2204
|
+
}
|
|
2205
|
+
function createAttachmentsPlugin(options) {
|
|
2190
2206
|
return {
|
|
2191
2207
|
name: "attachments",
|
|
2208
|
+
setup(editor) {
|
|
2209
|
+
if (!options.ref) return;
|
|
2210
|
+
const writableRef = options.ref;
|
|
2211
|
+
writableRef.current = {
|
|
2212
|
+
upload: (files) => {
|
|
2213
|
+
if (files.length === 0) return;
|
|
2214
|
+
routeFiles(editor, files, options);
|
|
2215
|
+
}
|
|
2216
|
+
};
|
|
2217
|
+
return () => {
|
|
2218
|
+
writableRef.current = null;
|
|
2219
|
+
};
|
|
2220
|
+
},
|
|
2192
2221
|
onInsertData(data, { editor, insertData }) {
|
|
2193
2222
|
const files = extractFiles(data);
|
|
2194
|
-
const
|
|
2195
|
-
const handled = matching.filter(
|
|
2196
|
-
(f) => isImageFile(f) || options.onAttachmentAdd !== void 0
|
|
2197
|
-
);
|
|
2223
|
+
const { handled, skipped } = routeFiles(editor, files, options);
|
|
2198
2224
|
if (handled.length === 0) {
|
|
2199
2225
|
const htmlImages = extractHtmlImages(data);
|
|
2200
2226
|
if (htmlImages.length === 0) return false;
|
|
@@ -2203,16 +2229,8 @@ function createAttachmentsPlugin(options) {
|
|
|
2203
2229
|
}
|
|
2204
2230
|
return true;
|
|
2205
2231
|
}
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
insertData(filesOnlyDataTransfer(unhandled));
|
|
2209
|
-
}
|
|
2210
|
-
for (const file of handled) {
|
|
2211
|
-
if (isImageFile(file)) {
|
|
2212
|
-
insertUploadedImage(editor, file, options);
|
|
2213
|
-
} else {
|
|
2214
|
-
insertUploadedAttachment(file, options);
|
|
2215
|
-
}
|
|
2232
|
+
if (skipped.length > 0) {
|
|
2233
|
+
insertData(filesOnlyDataTransfer(skipped));
|
|
2216
2234
|
}
|
|
2217
2235
|
return true;
|
|
2218
2236
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -280,6 +280,9 @@ interface Attachment {
|
|
|
280
280
|
*/
|
|
281
281
|
[key: string]: unknown;
|
|
282
282
|
}
|
|
283
|
+
interface AttachmentsHandle {
|
|
284
|
+
upload: (files: File[]) => void;
|
|
285
|
+
}
|
|
283
286
|
interface AttachmentsPluginOptions {
|
|
284
287
|
/**
|
|
285
288
|
* Upload a single file and resolve to the public URL, or an object
|
|
@@ -292,6 +295,8 @@ interface AttachmentsPluginOptions {
|
|
|
292
295
|
* (`image/*`). Files that don't match pass through untouched.
|
|
293
296
|
*/
|
|
294
297
|
accept?: string;
|
|
298
|
+
/** Populated on editor mount, nulled on unmount. */
|
|
299
|
+
ref?: RefObject<AttachmentsHandle | null>;
|
|
295
300
|
/**
|
|
296
301
|
* Placeholder alt text shown on the inserted image element while an
|
|
297
302
|
* image upload is in flight. Defaults to `"Uploading…"`.
|
|
@@ -484,4 +489,4 @@ declare function InkwellRenderer({ content, className, components, rehypePlugins
|
|
|
484
489
|
*/
|
|
485
490
|
declare function parseMarkdown(content: string, options?: ParseMarkdownOptions): ReactNode;
|
|
486
491
|
|
|
487
|
-
export { type Attachment, type AttachmentUploadResult, type AttachmentsPluginOptions, type BubbleMenuItem, type BubbleMenuItemProps, type BubbleMenuOptions, type CompletionsPluginOptions, type EmojiItem, type EmojiPluginOptions, type InkwellComponents, InkwellEditor, type InkwellEditorClassNames, type InkwellEditorFocusOptions, type InkwellEditorHandle, type InkwellEditorProps, type InkwellEditorState, type InkwellEditorStyles, type InkwellFeatures, type InkwellPlugin, type InkwellPluginActivation, type InkwellPluginEditor, type InkwellPluginPlaceholder, InkwellRenderer, type InkwellRendererProps, type MentionItem, type MentionRenderer, type MentionsPluginOptions, type ParseMarkdownOptions, type PluginInsertDataContext, type PluginKeyDownContext, type PluginRenderProps, type RehypePluginConfig, type SlashCommandArg, type SlashCommandChoice, type SlashCommandExecution, type SlashCommandItem, type SlashCommandsPluginOptions, type Snippet, type SnippetsPluginOptions, type SubscribeForwardedKey, createAttachmentsPlugin, createBubbleMenuPlugin, createCompletionsPlugin, createEmojiPlugin, createMentionsPlugin, createSlashCommandsPlugin, createSnippetsPlugin, defaultBubbleMenuItems, defaultEmojis, htmlToMarkdown, parseMarkdown };
|
|
492
|
+
export { type Attachment, type AttachmentUploadResult, type AttachmentsHandle, type AttachmentsPluginOptions, type BubbleMenuItem, type BubbleMenuItemProps, type BubbleMenuOptions, type CompletionsPluginOptions, type EmojiItem, type EmojiPluginOptions, type InkwellComponents, InkwellEditor, type InkwellEditorClassNames, type InkwellEditorFocusOptions, type InkwellEditorHandle, type InkwellEditorProps, type InkwellEditorState, type InkwellEditorStyles, type InkwellFeatures, type InkwellPlugin, type InkwellPluginActivation, type InkwellPluginEditor, type InkwellPluginPlaceholder, InkwellRenderer, type InkwellRendererProps, type MentionItem, type MentionRenderer, type MentionsPluginOptions, type ParseMarkdownOptions, type PluginInsertDataContext, type PluginKeyDownContext, type PluginRenderProps, type RehypePluginConfig, type SlashCommandArg, type SlashCommandChoice, type SlashCommandExecution, type SlashCommandItem, type SlashCommandsPluginOptions, type Snippet, type SnippetsPluginOptions, type SubscribeForwardedKey, createAttachmentsPlugin, createBubbleMenuPlugin, createCompletionsPlugin, createEmojiPlugin, createMentionsPlugin, createSlashCommandsPlugin, createSnippetsPlugin, defaultBubbleMenuItems, defaultEmojis, htmlToMarkdown, parseMarkdown };
|
package/dist/index.d.ts
CHANGED
|
@@ -280,6 +280,9 @@ interface Attachment {
|
|
|
280
280
|
*/
|
|
281
281
|
[key: string]: unknown;
|
|
282
282
|
}
|
|
283
|
+
interface AttachmentsHandle {
|
|
284
|
+
upload: (files: File[]) => void;
|
|
285
|
+
}
|
|
283
286
|
interface AttachmentsPluginOptions {
|
|
284
287
|
/**
|
|
285
288
|
* Upload a single file and resolve to the public URL, or an object
|
|
@@ -292,6 +295,8 @@ interface AttachmentsPluginOptions {
|
|
|
292
295
|
* (`image/*`). Files that don't match pass through untouched.
|
|
293
296
|
*/
|
|
294
297
|
accept?: string;
|
|
298
|
+
/** Populated on editor mount, nulled on unmount. */
|
|
299
|
+
ref?: RefObject<AttachmentsHandle | null>;
|
|
295
300
|
/**
|
|
296
301
|
* Placeholder alt text shown on the inserted image element while an
|
|
297
302
|
* image upload is in flight. Defaults to `"Uploading…"`.
|
|
@@ -484,4 +489,4 @@ declare function InkwellRenderer({ content, className, components, rehypePlugins
|
|
|
484
489
|
*/
|
|
485
490
|
declare function parseMarkdown(content: string, options?: ParseMarkdownOptions): ReactNode;
|
|
486
491
|
|
|
487
|
-
export { type Attachment, type AttachmentUploadResult, type AttachmentsPluginOptions, type BubbleMenuItem, type BubbleMenuItemProps, type BubbleMenuOptions, type CompletionsPluginOptions, type EmojiItem, type EmojiPluginOptions, type InkwellComponents, InkwellEditor, type InkwellEditorClassNames, type InkwellEditorFocusOptions, type InkwellEditorHandle, type InkwellEditorProps, type InkwellEditorState, type InkwellEditorStyles, type InkwellFeatures, type InkwellPlugin, type InkwellPluginActivation, type InkwellPluginEditor, type InkwellPluginPlaceholder, InkwellRenderer, type InkwellRendererProps, type MentionItem, type MentionRenderer, type MentionsPluginOptions, type ParseMarkdownOptions, type PluginInsertDataContext, type PluginKeyDownContext, type PluginRenderProps, type RehypePluginConfig, type SlashCommandArg, type SlashCommandChoice, type SlashCommandExecution, type SlashCommandItem, type SlashCommandsPluginOptions, type Snippet, type SnippetsPluginOptions, type SubscribeForwardedKey, createAttachmentsPlugin, createBubbleMenuPlugin, createCompletionsPlugin, createEmojiPlugin, createMentionsPlugin, createSlashCommandsPlugin, createSnippetsPlugin, defaultBubbleMenuItems, defaultEmojis, htmlToMarkdown, parseMarkdown };
|
|
492
|
+
export { type Attachment, type AttachmentUploadResult, type AttachmentsHandle, type AttachmentsPluginOptions, type BubbleMenuItem, type BubbleMenuItemProps, type BubbleMenuOptions, type CompletionsPluginOptions, type EmojiItem, type EmojiPluginOptions, type InkwellComponents, InkwellEditor, type InkwellEditorClassNames, type InkwellEditorFocusOptions, type InkwellEditorHandle, type InkwellEditorProps, type InkwellEditorState, type InkwellEditorStyles, type InkwellFeatures, type InkwellPlugin, type InkwellPluginActivation, type InkwellPluginEditor, type InkwellPluginPlaceholder, InkwellRenderer, type InkwellRendererProps, type MentionItem, type MentionRenderer, type MentionsPluginOptions, type ParseMarkdownOptions, type PluginInsertDataContext, type PluginKeyDownContext, type PluginRenderProps, type RehypePluginConfig, type SlashCommandArg, type SlashCommandChoice, type SlashCommandExecution, type SlashCommandItem, type SlashCommandsPluginOptions, type Snippet, type SnippetsPluginOptions, type SubscribeForwardedKey, createAttachmentsPlugin, createBubbleMenuPlugin, createCompletionsPlugin, createEmojiPlugin, createMentionsPlugin, createSlashCommandsPlugin, createSnippetsPlugin, defaultBubbleMenuItems, defaultEmojis, htmlToMarkdown, parseMarkdown };
|
package/dist/index.js
CHANGED
|
@@ -1362,6 +1362,7 @@ var InkwellEditorClient = forwardRef(
|
|
|
1362
1362
|
);
|
|
1363
1363
|
const overLimit = characterLimit !== void 0 && characterCount > characterLimit;
|
|
1364
1364
|
const hasCharacterLimit = characterLimit !== void 0;
|
|
1365
|
+
const showCharacterCount = characterLimit !== void 0 && characterCount >= characterLimit * 0.8;
|
|
1365
1366
|
const getEditorState = useCallback(() => {
|
|
1366
1367
|
const content2 = serializeContent();
|
|
1367
1368
|
return {
|
|
@@ -2011,7 +2012,7 @@ var InkwellEditorClient = forwardRef(
|
|
|
2011
2012
|
className: `inkwell-editor-wrapper${hasCharacterLimit ? " inkwell-editor-has-character-limit" : ""}${overLimit ? " inkwell-editor-over-limit" : ""}${className ? ` ${className}` : ""}${classNames?.root ? ` ${classNames.root}` : ""}`,
|
|
2012
2013
|
style: styles?.root,
|
|
2013
2014
|
children: [
|
|
2014
|
-
|
|
2015
|
+
showCharacterCount && /* @__PURE__ */ jsx(
|
|
2015
2016
|
CharacterCount,
|
|
2016
2017
|
{
|
|
2017
2018
|
count: characterCount,
|
|
@@ -2170,16 +2171,41 @@ var insertUploadedAttachment = (file, options) => {
|
|
|
2170
2171
|
options.onError?.(err, file);
|
|
2171
2172
|
});
|
|
2172
2173
|
};
|
|
2173
|
-
function
|
|
2174
|
+
function routeFiles(editor, files, options) {
|
|
2174
2175
|
const { accept } = options;
|
|
2176
|
+
const matching = accept ? files.filter((f) => mimeMatches(f.type, accept)) : files;
|
|
2177
|
+
const handled = matching.filter(
|
|
2178
|
+
(f) => isImageFile(f) || options.onAttachmentAdd !== void 0
|
|
2179
|
+
);
|
|
2180
|
+
for (const file of handled) {
|
|
2181
|
+
if (isImageFile(file)) {
|
|
2182
|
+
insertUploadedImage(editor, file, options);
|
|
2183
|
+
} else {
|
|
2184
|
+
insertUploadedAttachment(file, options);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
const skipped = files.filter((f) => !handled.includes(f));
|
|
2188
|
+
return { handled, skipped };
|
|
2189
|
+
}
|
|
2190
|
+
function createAttachmentsPlugin(options) {
|
|
2175
2191
|
return {
|
|
2176
2192
|
name: "attachments",
|
|
2193
|
+
setup(editor) {
|
|
2194
|
+
if (!options.ref) return;
|
|
2195
|
+
const writableRef = options.ref;
|
|
2196
|
+
writableRef.current = {
|
|
2197
|
+
upload: (files) => {
|
|
2198
|
+
if (files.length === 0) return;
|
|
2199
|
+
routeFiles(editor, files, options);
|
|
2200
|
+
}
|
|
2201
|
+
};
|
|
2202
|
+
return () => {
|
|
2203
|
+
writableRef.current = null;
|
|
2204
|
+
};
|
|
2205
|
+
},
|
|
2177
2206
|
onInsertData(data, { editor, insertData }) {
|
|
2178
2207
|
const files = extractFiles(data);
|
|
2179
|
-
const
|
|
2180
|
-
const handled = matching.filter(
|
|
2181
|
-
(f) => isImageFile(f) || options.onAttachmentAdd !== void 0
|
|
2182
|
-
);
|
|
2208
|
+
const { handled, skipped } = routeFiles(editor, files, options);
|
|
2183
2209
|
if (handled.length === 0) {
|
|
2184
2210
|
const htmlImages = extractHtmlImages(data);
|
|
2185
2211
|
if (htmlImages.length === 0) return false;
|
|
@@ -2188,16 +2214,8 @@ function createAttachmentsPlugin(options) {
|
|
|
2188
2214
|
}
|
|
2189
2215
|
return true;
|
|
2190
2216
|
}
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
insertData(filesOnlyDataTransfer(unhandled));
|
|
2194
|
-
}
|
|
2195
|
-
for (const file of handled) {
|
|
2196
|
-
if (isImageFile(file)) {
|
|
2197
|
-
insertUploadedImage(editor, file, options);
|
|
2198
|
-
} else {
|
|
2199
|
-
insertUploadedAttachment(file, options);
|
|
2200
|
-
}
|
|
2217
|
+
if (skipped.length > 0) {
|
|
2218
|
+
insertData(filesOnlyDataTransfer(skipped));
|
|
2201
2219
|
}
|
|
2202
2220
|
return true;
|
|
2203
2221
|
}
|
package/package.json
CHANGED
package/src/styles.css
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
* consumer can drop in and either keep or override. Light by default,
|
|
5
5
|
* dark via `prefers-color-scheme: dark`. No saturated brand colors.
|
|
6
6
|
*
|
|
7
|
+
* Specificity strategy:
|
|
8
|
+
* Visual-chrome defaults (color, background, border, padding, typography)
|
|
9
|
+
* are wrapped in `:where()` so they carry 0,0,0 specificity. Any single-class
|
|
10
|
+
* consumer rule — Tailwind utilities, `classNames` slot styling, `components`
|
|
11
|
+
* overrides on the renderer — wins automatically by specificity tie-break.
|
|
12
|
+
* No `!important`, no descendant scoping, no inline-style hacks needed.
|
|
13
|
+
*
|
|
14
|
+
* Layout-critical rules (position, z-index, structural width/height/overflow,
|
|
15
|
+
* picker flip math) deliberately stay at normal specificity. Consumers should
|
|
16
|
+
* not silently break editor or picker geometry by adding a class — when they
|
|
17
|
+
* want to override layout, they can with descendant or `!important` rules
|
|
18
|
+
* applied intentionally.
|
|
19
|
+
*
|
|
7
20
|
* Import with: `import "@railway/inkwell/styles.css";`
|
|
8
21
|
*/
|
|
9
22
|
|
|
@@ -31,6 +44,7 @@
|
|
|
31
44
|
--inkwell-accent: hsl(217, 91%, 50%);
|
|
32
45
|
--inkwell-accent-soft: hsla(217, 91%, 50%, 0.12);
|
|
33
46
|
--inkwell-danger: hsl(0, 72%, 51%);
|
|
47
|
+
--inkwell-danger-soft: hsla(0, 72%, 51%, 0.14);
|
|
34
48
|
|
|
35
49
|
/* Inline code */
|
|
36
50
|
--inkwell-code-bg: hsl(220, 14%, 94%);
|
|
@@ -61,6 +75,8 @@
|
|
|
61
75
|
|
|
62
76
|
--inkwell-accent: hsl(217, 91%, 65%);
|
|
63
77
|
--inkwell-accent-soft: hsla(217, 91%, 65%, 0.16);
|
|
78
|
+
--inkwell-danger: hsl(0, 70%, 65%);
|
|
79
|
+
--inkwell-danger-soft: hsla(0, 70%, 65%, 0.18);
|
|
64
80
|
|
|
65
81
|
--inkwell-code-bg: hsl(220, 13%, 18%);
|
|
66
82
|
--inkwell-code-fg: hsl(340, 70%, 75%);
|
|
@@ -69,14 +85,16 @@
|
|
|
69
85
|
|
|
70
86
|
/* ── Editor surface ──────────────────────────────────────────────── */
|
|
71
87
|
|
|
88
|
+
/* Wrapper position is structural — plugin pickers, bubble menus, and the
|
|
89
|
+
character-count overlay all absolutely position against it. Stays at
|
|
90
|
+
normal specificity. */
|
|
72
91
|
.inkwell-editor-wrapper {
|
|
73
92
|
position: relative;
|
|
74
93
|
}
|
|
75
94
|
|
|
76
|
-
/* Visual-chrome defaults
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
automatically — no `!important` or selector gymnastics needed.
|
|
95
|
+
/* Visual-chrome defaults on the editable surface live inside `:where()`
|
|
96
|
+
so a single-class consumer rule (Tailwind utilities, `classNames.editor`,
|
|
97
|
+
etc.) wins automatically.
|
|
80
98
|
|
|
81
99
|
Container size (min-height, max-height, height) is deliberately NOT
|
|
82
100
|
defaulted here. Inkwell sits inside the consumer's layout and the right
|
|
@@ -85,10 +103,12 @@
|
|
|
85
103
|
container. Set it on the editor via `styles.editor`, `classNames.editor`,
|
|
86
104
|
or your own CSS. */
|
|
87
105
|
:where(.inkwell-editor) {
|
|
106
|
+
outline: none;
|
|
88
107
|
padding: 1rem 1.25rem;
|
|
89
108
|
border: 1px solid var(--inkwell-border);
|
|
90
109
|
border-radius: var(--inkwell-radius);
|
|
91
110
|
background: var(--inkwell-bg);
|
|
111
|
+
color: var(--inkwell-text);
|
|
92
112
|
line-height: 1.6;
|
|
93
113
|
font-size: 0.95rem;
|
|
94
114
|
transition: border-color 0.15s ease;
|
|
@@ -96,27 +116,28 @@
|
|
|
96
116
|
:where(.inkwell-editor:focus-within) {
|
|
97
117
|
border-color: var(--inkwell-border-strong);
|
|
98
118
|
}
|
|
99
|
-
.inkwell-editor {
|
|
100
|
-
outline: none;
|
|
101
|
-
color: var(--inkwell-text);
|
|
102
|
-
}
|
|
103
119
|
|
|
120
|
+
/* `position: relative` on paragraphs is structural — Slate decorations and
|
|
121
|
+
inline children position against it. Margin is theming and goes through
|
|
122
|
+
`:where()` so a consumer paragraph-spacing utility wins. */
|
|
104
123
|
.inkwell-editor p {
|
|
105
|
-
margin: 0;
|
|
106
124
|
position: relative;
|
|
107
125
|
}
|
|
108
|
-
.inkwell-editor
|
|
126
|
+
:where(.inkwell-editor p) {
|
|
127
|
+
margin: 0;
|
|
128
|
+
}
|
|
129
|
+
:where(.inkwell-editor strong) {
|
|
109
130
|
font-weight: 600;
|
|
110
131
|
color: var(--inkwell-text);
|
|
111
132
|
}
|
|
112
|
-
.inkwell-editor em {
|
|
133
|
+
:where(.inkwell-editor em) {
|
|
113
134
|
font-style: italic;
|
|
114
135
|
}
|
|
115
|
-
.inkwell-editor del {
|
|
136
|
+
:where(.inkwell-editor del) {
|
|
116
137
|
text-decoration: line-through;
|
|
117
138
|
color: var(--inkwell-text-muted);
|
|
118
139
|
}
|
|
119
|
-
.inkwell-editor code {
|
|
140
|
+
:where(.inkwell-editor code) {
|
|
120
141
|
background: var(--inkwell-code-bg);
|
|
121
142
|
color: var(--inkwell-code-fg);
|
|
122
143
|
padding: 0.1em 0.35em;
|
|
@@ -125,38 +146,38 @@
|
|
|
125
146
|
font-size: 0.85em;
|
|
126
147
|
}
|
|
127
148
|
|
|
128
|
-
.inkwell-editor-blockquote {
|
|
149
|
+
:where(.inkwell-editor-blockquote) {
|
|
129
150
|
border-left: 3px solid var(--inkwell-border-strong);
|
|
130
151
|
padding-left: 0.85em;
|
|
131
152
|
margin: 0.5em 0;
|
|
132
153
|
color: var(--inkwell-text-muted);
|
|
133
154
|
}
|
|
134
155
|
|
|
135
|
-
.inkwell-editor-heading {
|
|
156
|
+
:where(.inkwell-editor-heading) {
|
|
136
157
|
font-weight: 600;
|
|
137
158
|
line-height: 1.3;
|
|
138
159
|
color: var(--inkwell-text);
|
|
139
160
|
}
|
|
140
|
-
.inkwell-editor-heading-1 {
|
|
161
|
+
:where(.inkwell-editor-heading-1) {
|
|
141
162
|
font-size: 1.75em;
|
|
142
163
|
}
|
|
143
|
-
.inkwell-editor-heading-2 {
|
|
164
|
+
:where(.inkwell-editor-heading-2) {
|
|
144
165
|
font-size: 1.4em;
|
|
145
166
|
}
|
|
146
|
-
.inkwell-editor-heading-3 {
|
|
167
|
+
:where(.inkwell-editor-heading-3) {
|
|
147
168
|
font-size: 1.2em;
|
|
148
169
|
}
|
|
149
|
-
.inkwell-editor-heading-4 {
|
|
170
|
+
:where(.inkwell-editor-heading-4) {
|
|
150
171
|
font-size: 1em;
|
|
151
172
|
}
|
|
152
|
-
.inkwell-editor-heading-5 {
|
|
173
|
+
:where(.inkwell-editor-heading-5) {
|
|
153
174
|
font-size: 0.9em;
|
|
154
175
|
}
|
|
155
|
-
.inkwell-editor-heading-6 {
|
|
176
|
+
:where(.inkwell-editor-heading-6) {
|
|
156
177
|
font-size: 0.8em;
|
|
157
178
|
}
|
|
158
179
|
|
|
159
|
-
.inkwell-editor-image {
|
|
180
|
+
:where(.inkwell-editor-image) {
|
|
160
181
|
margin: 0.75em 0;
|
|
161
182
|
border-radius: var(--inkwell-radius);
|
|
162
183
|
overflow: hidden;
|
|
@@ -165,62 +186,74 @@
|
|
|
165
186
|
border-color 0.15s ease,
|
|
166
187
|
box-shadow 0.15s ease;
|
|
167
188
|
}
|
|
168
|
-
.inkwell-editor-image[data-selected] {
|
|
189
|
+
:where(.inkwell-editor-image[data-selected]) {
|
|
169
190
|
border-color: var(--inkwell-accent);
|
|
170
191
|
box-shadow: 0 0 0 3px var(--inkwell-accent-soft);
|
|
171
192
|
}
|
|
193
|
+
/* Image fitting stays structural — `max-width: 100%` and `height: auto`
|
|
194
|
+
are the only sensible defaults for keeping aspect ratio inside a
|
|
195
|
+
variable-width editor. Consumers who want a different sizing model
|
|
196
|
+
should opt in with a descendant or higher-specificity rule. */
|
|
172
197
|
.inkwell-editor-image img {
|
|
173
198
|
display: block;
|
|
174
199
|
max-width: 100%;
|
|
175
200
|
height: auto;
|
|
176
201
|
}
|
|
177
202
|
|
|
178
|
-
/* Built-in character count.
|
|
179
|
-
wrapper
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
203
|
+
/* Built-in character count. Overlays the top-right corner of the editor
|
|
204
|
+
wrapper so it never shifts content, and sits on a solid surface tint
|
|
205
|
+
so it visually layers above any text that wraps underneath. Only
|
|
206
|
+
rendered once typing reaches 80% of `characterLimit`, since the
|
|
207
|
+
limit is a soft hint — typing past it is allowed; the count then
|
|
208
|
+
turns red and the wrapper picks up `.inkwell-editor-over-limit`,
|
|
209
|
+
which paints a soft red halo on the editor surface so it's visually
|
|
210
|
+
obvious the document is over budget.
|
|
211
|
+
|
|
212
|
+
Positioning stays at normal specificity — the overlay only works
|
|
213
|
+
from the top-right corner of the wrapper. Chrome (color, font-weight,
|
|
214
|
+
etc.) lives below in `:where()`. */
|
|
183
215
|
.inkwell-editor-character-count {
|
|
184
216
|
position: absolute;
|
|
185
|
-
|
|
186
|
-
|
|
217
|
+
top: 0.5rem;
|
|
218
|
+
right: 0.5rem;
|
|
187
219
|
z-index: 10;
|
|
188
|
-
|
|
220
|
+
pointer-events: none;
|
|
221
|
+
user-select: none;
|
|
222
|
+
}
|
|
223
|
+
:where(.inkwell-editor-character-count) {
|
|
224
|
+
padding: 0.1rem 0.4rem;
|
|
189
225
|
font-size: 0.72rem;
|
|
190
226
|
font-variant-numeric: tabular-nums;
|
|
191
227
|
color: var(--inkwell-text-dim);
|
|
192
|
-
|
|
193
|
-
|
|
228
|
+
background: var(--inkwell-bg);
|
|
229
|
+
border-radius: calc(var(--inkwell-radius) - 2px);
|
|
194
230
|
}
|
|
195
|
-
.inkwell-editor-character-count-over {
|
|
196
|
-
color:
|
|
231
|
+
:where(.inkwell-editor-character-count-over) {
|
|
232
|
+
color: var(--inkwell-danger);
|
|
197
233
|
font-weight: 500;
|
|
198
234
|
}
|
|
199
|
-
:where(
|
|
200
|
-
|
|
201
|
-
)
|
|
202
|
-
padding-right: 5.25rem;
|
|
203
|
-
padding-bottom: 2.25rem;
|
|
204
|
-
}
|
|
205
|
-
.inkwell-editor-wrapper.inkwell-editor-over-limit .inkwell-editor {
|
|
206
|
-
border-color: hsl(0, 75%, 55%);
|
|
207
|
-
box-shadow: 0 0 0 1px hsl(0, 75%, 55%);
|
|
235
|
+
:where(.inkwell-editor-wrapper.inkwell-editor-over-limit .inkwell-editor) {
|
|
236
|
+
border-color: var(--inkwell-danger-soft);
|
|
237
|
+
box-shadow: 0 0 0 3px var(--inkwell-danger-soft);
|
|
208
238
|
}
|
|
209
239
|
|
|
210
|
-
.inkwell-editor-backtick,
|
|
211
|
-
.inkwell-editor-marker {
|
|
240
|
+
:where(.inkwell-editor-backtick),
|
|
241
|
+
:where(.inkwell-editor-marker) {
|
|
212
242
|
color: var(--inkwell-text-dim);
|
|
213
243
|
}
|
|
214
|
-
.inkwell-editor .inkwell-editor-code-fence {
|
|
244
|
+
:where(.inkwell-editor .inkwell-editor-code-fence) {
|
|
215
245
|
color: var(--inkwell-text-dim);
|
|
216
246
|
}
|
|
217
|
-
.inkwell-editor .inkwell-editor-code-line,
|
|
218
|
-
.inkwell-editor .inkwell-editor-code-fence,
|
|
219
|
-
.inkwell-renderer pre code {
|
|
247
|
+
:where(.inkwell-editor .inkwell-editor-code-line),
|
|
248
|
+
:where(.inkwell-editor .inkwell-editor-code-fence),
|
|
249
|
+
:where(.inkwell-renderer pre code) {
|
|
220
250
|
font-family: var(--inkwell-font-mono);
|
|
221
251
|
font-size: 0.85em;
|
|
222
252
|
line-height: 1.55;
|
|
223
253
|
}
|
|
254
|
+
/* Wrapping behavior for code lines stays structural — Slate emits one
|
|
255
|
+
contenteditable line per node and depends on `white-space: pre-wrap`
|
|
256
|
+
for correct caret placement. */
|
|
224
257
|
.inkwell-editor .inkwell-editor-code-line {
|
|
225
258
|
white-space: pre-wrap;
|
|
226
259
|
word-wrap: break-word;
|
|
@@ -239,11 +272,13 @@
|
|
|
239
272
|
}
|
|
240
273
|
}
|
|
241
274
|
|
|
275
|
+
/* Container positioning is layout-critical — the bubble menu is JS-
|
|
276
|
+
positioned against the selection. Keep at normal specificity. */
|
|
242
277
|
.inkwell-plugin-bubble-menu-container {
|
|
243
278
|
position: absolute;
|
|
244
279
|
z-index: 9999;
|
|
245
280
|
}
|
|
246
|
-
.inkwell-plugin-bubble-menu-inner {
|
|
281
|
+
:where(.inkwell-plugin-bubble-menu-inner) {
|
|
247
282
|
display: flex;
|
|
248
283
|
gap: 2px;
|
|
249
284
|
background: var(--inkwell-bg-elevated);
|
|
@@ -253,7 +288,7 @@
|
|
|
253
288
|
box-shadow: 0 6px 20px hsla(220, 20%, 10%, 0.12);
|
|
254
289
|
animation: inkwell-fade-in 0.12s ease-out;
|
|
255
290
|
}
|
|
256
|
-
.inkwell-plugin-bubble-menu-btn {
|
|
291
|
+
:where(.inkwell-plugin-bubble-menu-btn) {
|
|
257
292
|
display: flex;
|
|
258
293
|
align-items: center;
|
|
259
294
|
justify-content: center;
|
|
@@ -268,35 +303,38 @@
|
|
|
268
303
|
background 0.1s ease,
|
|
269
304
|
color 0.1s ease;
|
|
270
305
|
}
|
|
271
|
-
.inkwell-plugin-bubble-menu-btn:hover {
|
|
306
|
+
:where(.inkwell-plugin-bubble-menu-btn:hover) {
|
|
272
307
|
background: var(--inkwell-bg-subtle);
|
|
273
308
|
color: var(--inkwell-text);
|
|
274
309
|
}
|
|
275
|
-
.inkwell-plugin-bubble-menu-btn-active {
|
|
310
|
+
:where(.inkwell-plugin-bubble-menu-btn-active) {
|
|
276
311
|
background: var(--inkwell-bg-subtle);
|
|
277
312
|
color: var(--inkwell-text);
|
|
278
313
|
}
|
|
279
|
-
.inkwell-plugin-bubble-menu-item-bold {
|
|
314
|
+
:where(.inkwell-plugin-bubble-menu-item-bold) {
|
|
280
315
|
font-weight: 700;
|
|
281
316
|
font-size: 14px;
|
|
282
317
|
}
|
|
283
|
-
.inkwell-plugin-bubble-menu-item-italic {
|
|
318
|
+
:where(.inkwell-plugin-bubble-menu-item-italic) {
|
|
284
319
|
font-style: italic;
|
|
285
320
|
font-size: 14px;
|
|
286
321
|
font-family: Georgia, "Times New Roman", serif;
|
|
287
322
|
}
|
|
288
|
-
.inkwell-plugin-bubble-menu-item-strike {
|
|
323
|
+
:where(.inkwell-plugin-bubble-menu-item-strike) {
|
|
289
324
|
text-decoration: line-through;
|
|
290
325
|
font-size: 14px;
|
|
291
326
|
}
|
|
292
327
|
|
|
293
328
|
/* ── Shared plugin picker (snippets, mentions, etc.) ─────────────── */
|
|
294
329
|
|
|
330
|
+
/* Popup positioning is layout-critical — the picker reads
|
|
331
|
+
`popupEl.offsetParent` for flip math, so it must remain absolutely
|
|
332
|
+
positioned inside the editor wrapper. */
|
|
295
333
|
.inkwell-plugin-picker-popup {
|
|
296
334
|
position: absolute;
|
|
297
335
|
z-index: 1001;
|
|
298
336
|
}
|
|
299
|
-
.inkwell-plugin-picker {
|
|
337
|
+
:where(.inkwell-plugin-picker) {
|
|
300
338
|
background: var(--inkwell-bg-elevated);
|
|
301
339
|
border: 1px solid var(--inkwell-border);
|
|
302
340
|
border-radius: var(--inkwell-radius);
|
|
@@ -305,7 +343,7 @@
|
|
|
305
343
|
max-width: 320px;
|
|
306
344
|
box-shadow: 0 6px 24px hsla(220, 20%, 10%, 0.14);
|
|
307
345
|
}
|
|
308
|
-
.inkwell-plugin-picker-search {
|
|
346
|
+
:where(.inkwell-plugin-picker-search) {
|
|
309
347
|
width: 100%;
|
|
310
348
|
padding: 7px 10px;
|
|
311
349
|
background: var(--inkwell-bg);
|
|
@@ -315,9 +353,12 @@
|
|
|
315
353
|
font-size: 0.85rem;
|
|
316
354
|
outline: none;
|
|
317
355
|
}
|
|
318
|
-
.inkwell-plugin-picker-search::placeholder {
|
|
356
|
+
:where(.inkwell-plugin-picker-search::placeholder) {
|
|
319
357
|
color: var(--inkwell-text-dim);
|
|
320
358
|
}
|
|
359
|
+
/* List `max-height` is structural — prevents the picker from blowing out
|
|
360
|
+
the viewport with long item lists. Scroll behavior and scrollbar
|
|
361
|
+
styling stay alongside it for a single source of truth. */
|
|
321
362
|
.inkwell-plugin-picker-list {
|
|
322
363
|
max-height: 240px;
|
|
323
364
|
overflow-y: auto;
|
|
@@ -340,27 +381,27 @@
|
|
|
340
381
|
.inkwell-plugin-picker-list::-webkit-scrollbar-thumb:hover {
|
|
341
382
|
background-color: var(--inkwell-text-dim);
|
|
342
383
|
}
|
|
343
|
-
.inkwell-plugin-picker-item {
|
|
384
|
+
:where(.inkwell-plugin-picker-item) {
|
|
344
385
|
padding: 7px 10px;
|
|
345
386
|
cursor: pointer;
|
|
346
387
|
transition: background 0.1s ease;
|
|
347
388
|
}
|
|
348
|
-
.inkwell-plugin-picker-item:hover,
|
|
349
|
-
.inkwell-plugin-picker-item-active {
|
|
389
|
+
:where(.inkwell-plugin-picker-item:hover),
|
|
390
|
+
:where(.inkwell-plugin-picker-item-active) {
|
|
350
391
|
background: var(--inkwell-bg-subtle);
|
|
351
392
|
}
|
|
352
|
-
.inkwell-plugin-picker-title {
|
|
393
|
+
:where(.inkwell-plugin-picker-title) {
|
|
353
394
|
font-size: 0.85rem;
|
|
354
395
|
font-weight: 500;
|
|
355
396
|
color: var(--inkwell-text);
|
|
356
397
|
margin-right: 0.5rem;
|
|
357
398
|
}
|
|
358
|
-
.inkwell-plugin-picker-subtitle {
|
|
399
|
+
:where(.inkwell-plugin-picker-subtitle) {
|
|
359
400
|
font-size: 0.75rem;
|
|
360
401
|
color: var(--inkwell-text-muted);
|
|
361
402
|
margin-top: 2px;
|
|
362
403
|
}
|
|
363
|
-
.inkwell-plugin-picker-preview {
|
|
404
|
+
:where(.inkwell-plugin-picker-preview) {
|
|
364
405
|
font-size: 0.75rem;
|
|
365
406
|
color: var(--inkwell-text-muted);
|
|
366
407
|
margin-top: 2px;
|
|
@@ -368,14 +409,14 @@
|
|
|
368
409
|
text-overflow: ellipsis;
|
|
369
410
|
white-space: nowrap;
|
|
370
411
|
}
|
|
371
|
-
.inkwell-plugin-picker-empty {
|
|
412
|
+
:where(.inkwell-plugin-picker-empty) {
|
|
372
413
|
padding: 12px;
|
|
373
414
|
text-align: center;
|
|
374
415
|
color: var(--inkwell-text-dim);
|
|
375
416
|
font-size: 0.85rem;
|
|
376
417
|
}
|
|
377
418
|
|
|
378
|
-
.inkwell-plugin-slash-commands-execute {
|
|
419
|
+
:where(.inkwell-plugin-slash-commands-execute) {
|
|
379
420
|
padding: 8px 10px;
|
|
380
421
|
color: var(--inkwell-text);
|
|
381
422
|
font-size: 0.85rem;
|
|
@@ -385,57 +426,58 @@
|
|
|
385
426
|
|
|
386
427
|
/* ── Renderer ────────────────────────────────────────────────────── */
|
|
387
428
|
|
|
388
|
-
/*
|
|
389
|
-
|
|
429
|
+
/* Every rule below targets a rendered HTML element (`a`, `h1`, `p`, ...)
|
|
430
|
+
that consumers customize through the `components` prop on
|
|
431
|
+
`<InkwellRenderer />` or by adding a class on the rendered element. All
|
|
432
|
+
chrome lives inside `:where()` so those overrides win without
|
|
433
|
+
`!important`. */
|
|
390
434
|
:where(.inkwell-renderer) {
|
|
435
|
+
color: var(--inkwell-text);
|
|
391
436
|
line-height: 1.65;
|
|
392
437
|
font-size: 0.95rem;
|
|
393
438
|
}
|
|
394
|
-
.inkwell-renderer {
|
|
395
|
-
color: var(--inkwell-text);
|
|
396
|
-
}
|
|
397
|
-
.inkwell-renderer :first-child {
|
|
439
|
+
:where(.inkwell-renderer :first-child) {
|
|
398
440
|
margin-top: 0;
|
|
399
441
|
}
|
|
400
|
-
.inkwell-renderer h1 {
|
|
442
|
+
:where(.inkwell-renderer h1) {
|
|
401
443
|
font-size: 1.75em;
|
|
402
444
|
font-weight: 600;
|
|
403
445
|
margin: 0.67em 0;
|
|
404
446
|
}
|
|
405
|
-
.inkwell-renderer h2 {
|
|
447
|
+
:where(.inkwell-renderer h2) {
|
|
406
448
|
font-size: 1.4em;
|
|
407
449
|
font-weight: 600;
|
|
408
450
|
margin: 0.75em 0;
|
|
409
451
|
}
|
|
410
|
-
.inkwell-renderer h3 {
|
|
452
|
+
:where(.inkwell-renderer h3) {
|
|
411
453
|
font-size: 1.2em;
|
|
412
454
|
font-weight: 600;
|
|
413
455
|
margin: 0.8em 0;
|
|
414
456
|
}
|
|
415
|
-
.inkwell-renderer p {
|
|
457
|
+
:where(.inkwell-renderer p) {
|
|
416
458
|
margin: 0.5em 0;
|
|
417
459
|
}
|
|
418
|
-
.inkwell-renderer blockquote {
|
|
460
|
+
:where(.inkwell-renderer blockquote) {
|
|
419
461
|
border-left: 3px solid var(--inkwell-border-strong);
|
|
420
462
|
padding-left: 0.85em;
|
|
421
463
|
margin: 1em 0;
|
|
422
464
|
color: var(--inkwell-text-muted);
|
|
423
465
|
}
|
|
424
|
-
.inkwell-renderer ul,
|
|
425
|
-
.inkwell-renderer ol {
|
|
466
|
+
:where(.inkwell-renderer ul),
|
|
467
|
+
:where(.inkwell-renderer ol) {
|
|
426
468
|
padding-left: 1.5em;
|
|
427
469
|
margin: 1em 0;
|
|
428
470
|
}
|
|
429
|
-
.inkwell-renderer ul {
|
|
471
|
+
:where(.inkwell-renderer ul) {
|
|
430
472
|
list-style: disc;
|
|
431
473
|
}
|
|
432
|
-
.inkwell-renderer ol {
|
|
474
|
+
:where(.inkwell-renderer ol) {
|
|
433
475
|
list-style: decimal;
|
|
434
476
|
}
|
|
435
|
-
.inkwell-renderer li {
|
|
477
|
+
:where(.inkwell-renderer li) {
|
|
436
478
|
margin: 0.25em 0;
|
|
437
479
|
}
|
|
438
|
-
.inkwell-renderer code {
|
|
480
|
+
:where(.inkwell-renderer code) {
|
|
439
481
|
background: var(--inkwell-code-bg);
|
|
440
482
|
color: var(--inkwell-code-fg);
|
|
441
483
|
padding: 0.1em 0.35em;
|
|
@@ -443,13 +485,21 @@
|
|
|
443
485
|
font-family: var(--inkwell-font-mono);
|
|
444
486
|
font-size: 0.85em;
|
|
445
487
|
}
|
|
488
|
+
/* Code-block wrapper position is structural — the copy button absolutely
|
|
489
|
+
positions inside it. */
|
|
446
490
|
.inkwell-renderer-code-block {
|
|
447
491
|
position: relative;
|
|
448
492
|
}
|
|
493
|
+
/* Copy button positioning is layout-critical (top-right inside the code
|
|
494
|
+
block); its chrome lives in `:where()` so consumers can restyle without
|
|
495
|
+
breaking placement. */
|
|
449
496
|
.inkwell-renderer-copy-btn {
|
|
450
497
|
position: absolute;
|
|
451
498
|
top: 0.5rem;
|
|
452
499
|
right: 0.5rem;
|
|
500
|
+
z-index: 1;
|
|
501
|
+
}
|
|
502
|
+
:where(.inkwell-renderer-copy-btn) {
|
|
453
503
|
display: flex;
|
|
454
504
|
align-items: center;
|
|
455
505
|
justify-content: center;
|
|
@@ -465,49 +515,48 @@
|
|
|
465
515
|
opacity 0.15s ease,
|
|
466
516
|
color 0.15s ease,
|
|
467
517
|
background 0.15s ease;
|
|
468
|
-
z-index: 1;
|
|
469
518
|
}
|
|
470
|
-
.inkwell-renderer-code-block:hover .inkwell-renderer-copy-btn {
|
|
519
|
+
:where(.inkwell-renderer-code-block:hover .inkwell-renderer-copy-btn) {
|
|
471
520
|
opacity: 1;
|
|
472
521
|
}
|
|
473
|
-
.inkwell-renderer-copy-btn:hover {
|
|
522
|
+
:where(.inkwell-renderer-copy-btn:hover) {
|
|
474
523
|
background: var(--inkwell-bg-subtle);
|
|
475
524
|
color: var(--inkwell-text);
|
|
476
525
|
}
|
|
477
|
-
.inkwell-renderer pre {
|
|
526
|
+
:where(.inkwell-renderer pre) {
|
|
478
527
|
margin: 1em 0;
|
|
479
528
|
border-radius: var(--inkwell-radius);
|
|
480
529
|
overflow: auto;
|
|
481
530
|
border: 1px solid var(--inkwell-border);
|
|
482
531
|
background: var(--inkwell-bg-subtle);
|
|
483
532
|
}
|
|
484
|
-
.inkwell-renderer pre code {
|
|
533
|
+
:where(.inkwell-renderer pre code) {
|
|
485
534
|
display: block;
|
|
486
535
|
padding: 0.85em 1em;
|
|
487
536
|
background: transparent;
|
|
488
537
|
color: var(--inkwell-text);
|
|
489
538
|
font-size: 0.82em;
|
|
490
539
|
}
|
|
491
|
-
.inkwell-renderer a {
|
|
540
|
+
:where(.inkwell-renderer a) {
|
|
492
541
|
color: var(--inkwell-accent);
|
|
493
542
|
text-decoration: underline;
|
|
494
543
|
text-underline-offset: 2px;
|
|
495
544
|
}
|
|
496
|
-
.inkwell-renderer hr {
|
|
545
|
+
:where(.inkwell-renderer hr) {
|
|
497
546
|
border: none;
|
|
498
547
|
border-top: 1px solid var(--inkwell-border);
|
|
499
548
|
margin: 2em 0;
|
|
500
549
|
}
|
|
501
|
-
.inkwell-renderer strong {
|
|
550
|
+
:where(.inkwell-renderer strong) {
|
|
502
551
|
font-weight: 600;
|
|
503
552
|
}
|
|
504
|
-
.inkwell-renderer em {
|
|
553
|
+
:where(.inkwell-renderer em) {
|
|
505
554
|
font-style: italic;
|
|
506
555
|
}
|
|
507
|
-
.inkwell-renderer del {
|
|
556
|
+
:where(.inkwell-renderer del) {
|
|
508
557
|
text-decoration: line-through;
|
|
509
558
|
}
|
|
510
|
-
.inkwell-renderer img {
|
|
559
|
+
:where(.inkwell-renderer img) {
|
|
511
560
|
max-width: 100%;
|
|
512
561
|
height: auto;
|
|
513
562
|
border-radius: var(--inkwell-radius);
|