@marianmeres/stuic 3.134.0 → 3.136.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/components/CommentInput/CommentInput.svelte +186 -348
- package/dist/components/CommentInput/CommentInput.svelte.d.ts +42 -44
- package/dist/components/CommentInput/README.md +104 -77
- package/dist/components/CommentInput/index.css +29 -259
- package/dist/components/CommentInput/index.d.ts +1 -2
- package/dist/components/CommentInput/index.js +1 -1
- package/dist/components/Input/FieldAssets.svelte +179 -96
- package/dist/components/Input/FieldAssets.svelte.d.ts +9 -0
- package/dist/components/Input/README.md +23 -3
- package/dist/components/MarkdownEditor/MarkdownEditor.svelte +10 -0
- package/dist/components/MarkdownEditor/MarkdownEditor.svelte.d.ts +1 -0
- package/package.json +1 -1
- package/dist/components/CommentInput/_internal/render.d.ts +0 -24
- package/dist/components/CommentInput/_internal/render.js +0 -47
|
@@ -475,9 +475,29 @@ on submit (and round-trips on reopen). Single-select fields ignore the prop.
|
|
|
475
475
|
## FieldAssets
|
|
476
476
|
|
|
477
477
|
Asset/image upload field with an inline thumbnail grid and a built-in lightbox preview
|
|
478
|
-
(`AssetsPreview`). Files are added via the picker button
|
|
479
|
-
|
|
480
|
-
processing).
|
|
478
|
+
(`AssetsPreview`). Files are added via the picker button, by dragging them onto the field,
|
|
479
|
+
or (opt-in) by pasting from the clipboard; each shows as a thumbnail with its filename (and
|
|
480
|
+
an upload progress indicator while processing).
|
|
481
|
+
|
|
482
|
+
### Paste from the clipboard (`pasteable`)
|
|
483
|
+
|
|
484
|
+
Opt in with `pasteable` to let users paste image/file data from the clipboard (Ctrl/Cmd-V) —
|
|
485
|
+
a screenshot, a copied image, etc. It is **focus-scoped**: a paste is consumed only while the
|
|
486
|
+
field (or a control inside it) holds focus. Clicking anywhere in the field focuses it, so no
|
|
487
|
+
Tab is needed, and a `:focus-within` ring on the input box signals the paste-ready state.
|
|
488
|
+
Pasted files go through the same path as the picker and drag-and-drop, so `accept`,
|
|
489
|
+
`cardinality` and `processAssets` all apply. No-op unless `processAssets` is provided.
|
|
490
|
+
|
|
491
|
+
```svelte
|
|
492
|
+
<FieldAssets
|
|
493
|
+
label="Screenshots"
|
|
494
|
+
name="screenshots"
|
|
495
|
+
bind:value
|
|
496
|
+
{processAssets}
|
|
497
|
+
accept="image/*"
|
|
498
|
+
pasteable
|
|
499
|
+
/>
|
|
500
|
+
```
|
|
481
501
|
|
|
482
502
|
### Ordering the assets (`ordered`)
|
|
483
503
|
|
|
@@ -529,6 +529,16 @@
|
|
|
529
529
|
export function toggleMode(): void {
|
|
530
530
|
toggleModeInternal();
|
|
531
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Imperatively run a toolbar command — same effect as clicking the matching
|
|
534
|
+
* toolbar button. Useful for wiring keyboard shortcuts (e.g. ⌘/Ctrl+B) from a
|
|
535
|
+
* host component. No-op while the backend is (re)loading. The `"|"` separator
|
|
536
|
+
* is not a command.
|
|
537
|
+
*/
|
|
538
|
+
export function command(item: Exclude<ToolbarItem, "|">): void {
|
|
539
|
+
const btn = TOOLBAR_REGISTRY[item];
|
|
540
|
+
if (btn && activeHandle) btn.run(activeHandle.commands);
|
|
541
|
+
}
|
|
532
542
|
</script>
|
|
533
543
|
|
|
534
544
|
<InputWrap
|
|
@@ -99,6 +99,7 @@ declare const MarkdownEditor: import("svelte").Component<Props, {
|
|
|
99
99
|
scrollIntoView: (opts?: ScrollIntoViewOptions) => void;
|
|
100
100
|
getMarkdown: () => string;
|
|
101
101
|
toggleMode: () => void;
|
|
102
|
+
command: (item: Exclude<ToolbarItem, "|">) => void;
|
|
102
103
|
}, "value" | "input" | "mode">;
|
|
103
104
|
type MarkdownEditor = ReturnType<typeof MarkdownEditor>;
|
|
104
105
|
export default MarkdownEditor;
|
package/package.json
CHANGED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default Preview renderer for {@link CommentInput}: turns a markdown string into
|
|
3
|
-
* **sanitized** HTML.
|
|
4
|
-
*
|
|
5
|
-
* `marked` and `dompurify` are declared as *optional* peer dependencies and are
|
|
6
|
-
* imported dynamically the first time a Preview tab is opened — consumers who
|
|
7
|
-
* never preview (or who pass their own `renderMarkdown`) don't pay for them, and
|
|
8
|
-
* a consumer who hasn't installed them gets a caught error (handled by the
|
|
9
|
-
* component) rather than a hard build failure. Mirrors the lazy-load convention
|
|
10
|
-
* used by `MarkdownEditor` for its Milkdown/CodeMirror backends.
|
|
11
|
-
*
|
|
12
|
-
* Sanitization is non-negotiable here: comment text is untrusted user content and
|
|
13
|
-
* `marked` emits raw HTML embedded in markdown verbatim (an XSS vector). Every
|
|
14
|
-
* code path that returns HTML runs it through DOMPurify first.
|
|
15
|
-
*/
|
|
16
|
-
/** A markdown-to-HTML renderer. Return value may be sync or async. */
|
|
17
|
-
export type MarkdownRenderer = (markdown: string) => string | Promise<string>;
|
|
18
|
-
/**
|
|
19
|
-
* Render markdown to sanitized HTML using the bundled (lazy) marked + DOMPurify
|
|
20
|
-
* pipeline. Throws if the optional peers aren't installed (the caller catches
|
|
21
|
-
* this and shows a fallback). SSR-safe: returns an empty string off the DOM,
|
|
22
|
-
* since DOMPurify needs a `window` to sanitize against.
|
|
23
|
-
*/
|
|
24
|
-
export declare function renderMarkdownSafe(markdown: string): Promise<string>;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default Preview renderer for {@link CommentInput}: turns a markdown string into
|
|
3
|
-
* **sanitized** HTML.
|
|
4
|
-
*
|
|
5
|
-
* `marked` and `dompurify` are declared as *optional* peer dependencies and are
|
|
6
|
-
* imported dynamically the first time a Preview tab is opened — consumers who
|
|
7
|
-
* never preview (or who pass their own `renderMarkdown`) don't pay for them, and
|
|
8
|
-
* a consumer who hasn't installed them gets a caught error (handled by the
|
|
9
|
-
* component) rather than a hard build failure. Mirrors the lazy-load convention
|
|
10
|
-
* used by `MarkdownEditor` for its Milkdown/CodeMirror backends.
|
|
11
|
-
*
|
|
12
|
-
* Sanitization is non-negotiable here: comment text is untrusted user content and
|
|
13
|
-
* `marked` emits raw HTML embedded in markdown verbatim (an XSS vector). Every
|
|
14
|
-
* code path that returns HTML runs it through DOMPurify first.
|
|
15
|
-
*/
|
|
16
|
-
// Cache the resolved (marked + DOMPurify) pipeline so the dynamic imports and
|
|
17
|
-
// DOMPurify instance creation happen at most once per page.
|
|
18
|
-
let cached = null;
|
|
19
|
-
async function load() {
|
|
20
|
-
if (cached)
|
|
21
|
-
return cached;
|
|
22
|
-
const [{ marked }, dompurify] = await Promise.all([
|
|
23
|
-
import("marked"),
|
|
24
|
-
import("dompurify"),
|
|
25
|
-
]);
|
|
26
|
-
// DOMPurify's default export is the instance in a browser/DOM context.
|
|
27
|
-
const DOMPurify = dompurify.default ?? dompurify;
|
|
28
|
-
cached = async (markdown) => {
|
|
29
|
-
// GitHub-flavored markdown + soft line breaks → <br>, matching how comment
|
|
30
|
-
// boxes (incl. GitHub's) treat single newlines.
|
|
31
|
-
const html = await marked.parse(markdown ?? "", { gfm: true, breaks: true });
|
|
32
|
-
return DOMPurify.sanitize(html);
|
|
33
|
-
};
|
|
34
|
-
return cached;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Render markdown to sanitized HTML using the bundled (lazy) marked + DOMPurify
|
|
38
|
-
* pipeline. Throws if the optional peers aren't installed (the caller catches
|
|
39
|
-
* this and shows a fallback). SSR-safe: returns an empty string off the DOM,
|
|
40
|
-
* since DOMPurify needs a `window` to sanitize against.
|
|
41
|
-
*/
|
|
42
|
-
export async function renderMarkdownSafe(markdown) {
|
|
43
|
-
if (typeof window === "undefined")
|
|
44
|
-
return "";
|
|
45
|
-
const render = await load();
|
|
46
|
-
return render(markdown);
|
|
47
|
-
}
|