@paroicms/quill-editor-plugin 1.44.0 → 1.45.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/admin-ui-plugin/dist/admin-ui-plugin.css +2 -2
- package/admin-ui-plugin/dist/admin-ui-plugin.mjs +1 -1
- package/backend/dist/index.js +3 -61
- package/backend/dist/quill-delta.js +19 -12
- package/package.json +15 -13
- package/public-assets/dist/text.css +1 -0
- package/types/html-editor-public-types.d.ts +9 -4
- package/frontend/dist/cross.svg +0 -1
- package/frontend/dist/quill-editor-plugin.css +0 -1
- package/frontend/dist/quill-editor-plugin.mjs +0 -1
package/backend/dist/index.js
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import { isJsonFieldValue, isObj } from "@paroicms/public-anywhere-lib";
|
|
2
|
-
import {
|
|
2
|
+
import { makeStylesheetLinkAsyncTag } from "@paroicms/public-server-lib";
|
|
3
3
|
import { esmDirName, extractPackageNameAndVersionSync } from "@paroicms/script-lib";
|
|
4
|
-
import { type } from "arktype";
|
|
5
4
|
import { dirname, join } from "node:path";
|
|
6
5
|
import { normalizeTypographyInQuillDelta } from "./normalize-typography-in-delta.js";
|
|
7
6
|
import { convertQuillDeltaToHtml, convertQuillDeltaToPlainText } from "./quill-delta.js";
|
|
8
|
-
const MediaIdQueryAT = type({
|
|
9
|
-
"mediaId?": "string|undefined",
|
|
10
|
-
"+": "reject",
|
|
11
|
-
});
|
|
12
7
|
const projectDir = dirname(esmDirName(import.meta.url));
|
|
13
8
|
const packageDir = dirname(projectDir);
|
|
14
9
|
const { name: pluginName, version } = extractPackageNameAndVersionSync(packageDir);
|
|
15
10
|
const plugin = {
|
|
16
11
|
version,
|
|
17
12
|
siteInit(service) {
|
|
18
|
-
service.setPublicAssetsDirectory(join(packageDir, "
|
|
13
|
+
service.setPublicAssetsDirectory(join(packageDir, "public-assets", "dist"));
|
|
19
14
|
service.setAdminUiAssetsDirectory(join(packageDir, "admin-ui-plugin", "dist"));
|
|
20
15
|
service.registerSiteSchemaLibrary(join(packageDir, "site-schema-lib"));
|
|
21
16
|
service.registerRenderingHook("fieldPreprocessor", ({ service, value, options }) => {
|
|
@@ -48,13 +43,7 @@ const plugin = {
|
|
|
48
43
|
service.registerHeadTags(({ state }) => {
|
|
49
44
|
if (!state.get("paQuillEditor:html"))
|
|
50
45
|
return;
|
|
51
|
-
|
|
52
|
-
makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/quill-editor-plugin.css`),
|
|
53
|
-
];
|
|
54
|
-
if (state.get("paQuillEditor:zoomable")) {
|
|
55
|
-
tags.push(`<script type="module" src="${escapeHtml(`${service.pluginAssetsUrl}/quill-editor-plugin.mjs`)}" async></script>`);
|
|
56
|
-
}
|
|
57
|
-
return tags;
|
|
46
|
+
return [makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/text.css`)];
|
|
58
47
|
});
|
|
59
48
|
if (service.configuration.adminUi?.code) {
|
|
60
49
|
service.registerHeadTags(({ state }) => {
|
|
@@ -80,53 +69,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
80
69
|
];
|
|
81
70
|
});
|
|
82
71
|
}
|
|
83
|
-
service.registerLiquidFilter("imageZoomUrl", (service) => {
|
|
84
|
-
service.pluginService.logger.warn(`"imageZoomUrl" filter is deprecated, use instead: <img ... {{ media | zoomable }}>`);
|
|
85
|
-
return "";
|
|
86
|
-
});
|
|
87
|
-
service.registerLiquidFilter("zoomable", async (service, val) => {
|
|
88
|
-
if (!val)
|
|
89
|
-
return "";
|
|
90
|
-
service.setRenderState("paQuillEditor:zoomable", true);
|
|
91
|
-
const mediaId = typeof val === "string"
|
|
92
|
-
? val
|
|
93
|
-
: val && typeof val === "object" && "mediaId" in val && typeof val.mediaId === "string"
|
|
94
|
-
? val.mediaId
|
|
95
|
-
: undefined;
|
|
96
|
-
if (!mediaId)
|
|
97
|
-
return "";
|
|
98
|
-
return `data-zoomable="${encodeURIComponent(mediaId)}"`;
|
|
99
|
-
}, { raw: true });
|
|
100
|
-
service.setPublicApiHandler(async (service, httpContext, relativePath) => {
|
|
101
|
-
const { req, res } = httpContext;
|
|
102
|
-
if (relativePath === "/zoom-image") {
|
|
103
|
-
const { mediaId } = MediaIdQueryAT.assert(req.query);
|
|
104
|
-
if (!mediaId) {
|
|
105
|
-
res.append("Content-Type", "application/json; charset=utf-8");
|
|
106
|
-
res.status(400).send({ error: "mediaId parameter is required" });
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const renderService = await service.openRenderingService({
|
|
110
|
-
language: service.siteSchema.defaultLanguage,
|
|
111
|
-
urlLike: relativePath,
|
|
112
|
-
});
|
|
113
|
-
try {
|
|
114
|
-
const image = await renderService.useImage(mediaId, "x1900x", { pixelRatio: 1 });
|
|
115
|
-
res.append("Content-Type", "application/json; charset=utf-8");
|
|
116
|
-
res.status(200).send(image);
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
service.logger.warn(`Failed to get zoom image for mediaId '${mediaId}':`, error);
|
|
120
|
-
res.append("Content-Type", "application/json; charset=utf-8");
|
|
121
|
-
res.status(404).send({ error: "Image not found" });
|
|
122
|
-
}
|
|
123
|
-
await renderService.close();
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
res.append("Content-Type", "application/json; charset=utf-8");
|
|
127
|
-
res.status(404).send({ status: 404 });
|
|
128
|
-
return;
|
|
129
|
-
});
|
|
130
72
|
},
|
|
131
73
|
};
|
|
132
74
|
export default plugin;
|
|
@@ -24,9 +24,9 @@ export async function convertQuillDeltaToHtml(service, delta, options) {
|
|
|
24
24
|
return obfuscateBlotProcessing(value, customOp.attributes);
|
|
25
25
|
if (type === "media")
|
|
26
26
|
return await mediaBlotProcessing(service, value, options);
|
|
27
|
-
if (type === "video
|
|
28
|
-
return
|
|
29
|
-
if (type === "internal-link
|
|
27
|
+
if (type === "platform-video")
|
|
28
|
+
return platformVideoBlotProcessing(service, value, options);
|
|
29
|
+
if (type === "internal-link") {
|
|
30
30
|
return await internalLinkPluginBlotProcessing(service, value, options);
|
|
31
31
|
}
|
|
32
32
|
pluginService.logger.warn(`Invalid blot '${type}'`);
|
|
@@ -44,9 +44,9 @@ export function convertQuillDeltaToPlainText(service, delta) {
|
|
|
44
44
|
return "";
|
|
45
45
|
if (type === "media")
|
|
46
46
|
return "";
|
|
47
|
-
if (type === "video
|
|
47
|
+
if (type === "platform-video")
|
|
48
48
|
return "";
|
|
49
|
-
if (type === "internal-link
|
|
49
|
+
if (type === "internal-link")
|
|
50
50
|
return "";
|
|
51
51
|
service.pluginService.logger.warn(`Invalid blot '${type}'`);
|
|
52
52
|
return "";
|
|
@@ -71,7 +71,7 @@ async function mediaBlotProcessing(service, obj, options) {
|
|
|
71
71
|
const figureAttributes = [`class="Fig${value.align ? ` ${escapeHtml(value.align)}` : ""}"`];
|
|
72
72
|
if (value.zoomable) {
|
|
73
73
|
figureAttributes.push(`data-zoomable="${escapeHtml(media.mediaId)}"`);
|
|
74
|
-
service.setRenderState("
|
|
74
|
+
service.setRenderState("paZoom:enabled", true); // State of @paroicms/plugin-zoom
|
|
75
75
|
}
|
|
76
76
|
const imgTagAttributes = [
|
|
77
77
|
`class="Fig-media"`,
|
|
@@ -99,9 +99,9 @@ export function preprocessDelta(ops) {
|
|
|
99
99
|
obfuscate: op.insert,
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
-
else if (op.attributes?.["internal-link
|
|
102
|
+
else if (op.attributes?.["internal-link"]) {
|
|
103
103
|
op.insert = {
|
|
104
|
-
"internal-link
|
|
104
|
+
"internal-link": op.attributes?.["internal-link"],
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -140,15 +140,22 @@ function formatObfuscateAsALink(val) {
|
|
|
140
140
|
return "tel";
|
|
141
141
|
throw new Error(`invalid link-type '${val}'`);
|
|
142
142
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
const PlatformVideoValueAT = type({
|
|
144
|
+
videoId: "string",
|
|
145
|
+
platform: "string",
|
|
146
|
+
"+": "reject",
|
|
147
|
+
});
|
|
148
|
+
function platformVideoBlotProcessing(service, value, _options) {
|
|
149
|
+
const videoValue = PlatformVideoValueAT.assert(value);
|
|
150
|
+
if (videoValue.platform !== "youtube") {
|
|
151
|
+
service.pluginService.logger.warn(`Unsupported video platform "${videoValue.platform}"`);
|
|
146
152
|
return "";
|
|
153
|
+
}
|
|
147
154
|
return `
|
|
148
155
|
<iframe
|
|
149
156
|
width="420"
|
|
150
157
|
height="315"
|
|
151
|
-
src="https://www.youtube.com/embed/${encodeURIComponent(videoId)}"
|
|
158
|
+
src="https://www.youtube-nocookie.com/embed/${encodeURIComponent(videoValue.videoId)}"
|
|
152
159
|
></iframe>
|
|
153
160
|
`;
|
|
154
161
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paroicms/quill-editor-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.45.1",
|
|
4
4
|
"description": "Quill Editor plugin for ParoiCMS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"paroicms",
|
|
@@ -17,39 +17,41 @@
|
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"scripts": {
|
|
19
19
|
"dev:admin-ui": "(cd admin-ui-plugin && vite)",
|
|
20
|
-
"build": "npm run build:backend && npm run build:admin-ui && npm run build:
|
|
20
|
+
"build": "npm run build:backend && npm run build:admin-ui && npm run build:public-assets",
|
|
21
21
|
"build:backend": "(cd backend && tsc)",
|
|
22
22
|
"build:admin-ui": "(cd admin-ui-plugin && npm run build)",
|
|
23
|
+
"build:public-assets": "npm run _scss -- --no-source-map --style=compressed",
|
|
23
24
|
"build:backend:watch": "(cd backend && tsc --watch --preserveWatchOutput)",
|
|
24
|
-
"build:frontend": "(cd frontend && npm run build)",
|
|
25
|
-
"build:frontend:watch": "(cd frontend && npm run build:watch)",
|
|
26
25
|
"build:admin-ui:watch": "(cd admin-ui-plugin && npm run build:watch)",
|
|
27
|
-
"
|
|
26
|
+
"build:public-assets:watch": "npm run _scss && npm run _scss -- --watch",
|
|
27
|
+
"_scss": "sass public-assets/src/text.scss public-assets/dist/text.css",
|
|
28
|
+
"clear": "rimraf backend/dist/* admin-ui-plugin/dist/* public-assets/dist/*"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
31
|
"@paroi/quill-delta-to-html": "~0.12.3",
|
|
31
|
-
"@paroicms/script-lib": "0.3.
|
|
32
|
-
"arktype": "~2.1.
|
|
32
|
+
"@paroicms/script-lib": "0.3.3",
|
|
33
|
+
"arktype": "~2.1.23"
|
|
33
34
|
},
|
|
34
35
|
"peerDependencies": {
|
|
35
36
|
"@paroicms/public-anywhere-lib": "0",
|
|
36
37
|
"@paroicms/public-server-lib": "0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@paroicms/public-anywhere-lib": "0.37.
|
|
40
|
-
"@paroicms/public-server-lib": "0.47.
|
|
41
|
-
"@types/node": "~24.
|
|
40
|
+
"@paroicms/public-anywhere-lib": "0.37.1",
|
|
41
|
+
"@paroicms/public-server-lib": "0.47.1",
|
|
42
|
+
"@types/node": "~24.8.1",
|
|
42
43
|
"rimraf": "~6.0.1",
|
|
43
|
-
"
|
|
44
|
+
"sass": "~1.93.2",
|
|
45
|
+
"typescript": "~5.9.3"
|
|
44
46
|
},
|
|
45
47
|
"type": "module",
|
|
46
48
|
"main": "backend/dist/index.js",
|
|
47
49
|
"types": "types/html-editor-public-types.d.ts",
|
|
48
50
|
"files": [
|
|
49
51
|
"backend/dist",
|
|
50
|
-
"frontend/dist",
|
|
51
52
|
"admin-ui-plugin/dist",
|
|
53
|
+
"public-assets/dist",
|
|
52
54
|
"site-schema-lib",
|
|
53
|
-
"types"
|
|
55
|
+
"types/html-editor-public-types.d.ts"
|
|
54
56
|
]
|
|
55
57
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.Text .Fig{display:table;margin:0}.Text .Fig.left{float:left;margin:5px 20px 10px 0}.Text .Fig.right{float:right;margin:5px 0 10px 20px}.Text .Fig.center{clear:both;margin:20px auto}.Text .Fig-media{display:block;height:auto;max-width:100%}.Text .Fig-caption{caption-side:bottom;display:table-caption;font-size:.875em;margin-top:8px;opacity:.6;text-align:center}.Text .ql-align-center{text-align:center}.Text .ql-align-right{text-align:right}.Text .ql-size-small{font-size:.5625em}.Text .ql-size-large{font-size:2em}.Text .ql-size-huge{font-size:4em}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
export interface PlatformVideoValue {
|
|
2
|
+
videoId: string;
|
|
3
|
+
platform: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
export interface HtmlEditorInitService {
|
|
2
7
|
registerVideoPlugin(plugin: HtmlEditorVideoPlugin): void;
|
|
3
8
|
registerInternalLinkPlugin(plugin: HtmlEditorInternalLinkPlugin): void;
|
|
4
9
|
}
|
|
5
10
|
|
|
6
11
|
export interface HtmlEditorVideoPlugin {
|
|
7
|
-
recognizeUrl(url: string):
|
|
8
|
-
getThumbnailUrl(
|
|
12
|
+
recognizeUrl(url: string): PlatformVideoValue | undefined;
|
|
13
|
+
getThumbnailUrl(value: PlatformVideoValue): string;
|
|
9
14
|
createComponent(
|
|
10
|
-
|
|
15
|
+
value: PlatformVideoValue,
|
|
11
16
|
options: {
|
|
12
17
|
getLanguage: () => string;
|
|
13
|
-
onChange: (newVal:
|
|
18
|
+
onChange: (newVal: PlatformVideoValue | null) => void;
|
|
14
19
|
},
|
|
15
20
|
): {
|
|
16
21
|
element: HTMLElement;
|
package/frontend/dist/cross.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="p-icon" aria-hidden="true"><path d="M8.01186 7.00933L12.27 2.75116C12.341 2.68501 12.398 2.60524 12.4375 2.51661C12.4769 2.42798 12.4982 2.3323 12.4999 2.23529C12.5016 2.13827 12.4838 2.0419 12.4474 1.95194C12.4111 1.86197 12.357 1.78024 12.2884 1.71163C12.2198 1.64302 12.138 1.58893 12.0481 1.55259C11.9581 1.51625 11.8617 1.4984 11.7647 1.50011C11.6677 1.50182 11.572 1.52306 11.4834 1.56255C11.3948 1.60204 11.315 1.65898 11.2488 1.72997L6.99067 5.98814L2.7325 1.72997C2.59553 1.60234 2.41437 1.53286 2.22718 1.53616C2.03999 1.53946 1.8614 1.61529 1.72901 1.74767C1.59663 1.88006 1.5208 2.05865 1.5175 2.24584C1.5142 2.43303 1.58368 2.61419 1.71131 2.75116L5.96948 7.00933L1.71131 11.2675C1.576 11.403 1.5 11.5866 1.5 11.7781C1.5 11.9696 1.576 12.1532 1.71131 12.2887C1.84679 12.424 2.03043 12.5 2.2219 12.5C2.41338 12.5 2.59702 12.424 2.7325 12.2887L6.99067 8.03052L11.2488 12.2887C11.3843 12.424 11.568 12.5 11.7594 12.5C11.9509 12.5 12.1346 12.424 12.27 12.2887C12.4053 12.1532 12.4813 11.9696 12.4813 11.7781C12.4813 11.5866 12.4053 11.403 12.27 11.2675L8.01186 7.00933Z" fill="#fff"></path></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.Text .Fig{display:table;margin:0}.Text .Fig.left{float:left;margin:5px 20px 10px 0}.Text .Fig.right{float:right;margin:5px 0 10px 20px}.Text .Fig.center{clear:both;margin:20px auto}.Text .Fig-media{display:block;height:auto;max-width:100%}.Text .Fig-caption{caption-side:bottom;display:table-caption;font-size:.875em;margin-top:8px;opacity:.6;text-align:center}.Text .ql-align-center{text-align:center}.Text .ql-align-right{text-align:right}.Text .ql-size-small{font-size:.5625em}.Text .ql-size-large{font-size:1.125em}.Text .ql-size-huge{font-size:2em}.PaZoomable{cursor:pointer}.PaZoomable:hover,.PaZoomable:focus{outline:1px solid var(--paInteractiveColor)}.PaZoomableViewer{align-items:center;background:#00000080;display:flex;height:100%;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:999}.PaZoomableViewer-img{height:100%;object-fit:contain;width:100%}.PaZoomableViewer-closeButton.PaButton{position:absolute;right:8px;top:5px}.PaZoomableViewer-spinner{animation:spin 1s linear infinite;border:4px solid rgba(255,255,255,.3);border-radius:50%;border-top:4px solid white;height:40px;width:40px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{delegateEvents as $,template as w,setAttribute as c,effect as Z}from"https://esm.sh/solid-js@1.9.7/web";function k(o){let e=o;const t=e.indexOf("?");t!==-1&&(e=e.substring(0,t));const r=e.indexOf("#");r!==-1&&(e=e.substring(0,r));const n=e.lastIndexOf("/");return n===-1?void 0:e.slice(0,n)}const b=k(import.meta.url),E="/api/plugin/quill-editor-plugin",P=E;var V=w('<div class=PaZoomableViewer><button type=button class="PaZoomableViewer-closeButton PaButton"><img alt=⨯ width=30 height=30></button><div class=PaZoomableViewer-spinner>'),x=w('<div class=PaZoomableViewer><button type=button class="PaZoomableViewer-closeButton PaButton"><img alt=⨯ width=30 height=30></button><img class=PaZoomableViewer-img alt>');function L(){const o=document.querySelectorAll("[data-zoomable]");for(const e of o){if(!(e instanceof HTMLElement))continue;const t=e.dataset.zoomable?.trim();t&&C(e,{mediaId:t})}}function C(o,{mediaId:e}){o.classList.add("PaZoomable"),o.setAttribute("tabindex","0"),o.addEventListener("click",async t=>{t.preventDefault(),await _(e)})}async function _(o){const e=document.body,t=(()=>{var i=V(),s=i.firstChild,l=s.firstChild;return s.$$click=n,c(l,"src",`${b}/cross.svg`),i})();function r(i){i.key==="Escape"&&n()}function n(){t.remove(),e.removeEventListener("keyup",r)}e.addEventListener("keyup",r),e.appendChild(t);try{let i=function(d){d.key==="Escape"&&s()},s=function(){p.remove(),e.removeEventListener("keyup",i)};const l=await fetch(`${P}/zoom-image?mediaId=${encodeURIComponent(o)}`);if(!l.ok){console.error("Failed to fetch zoom image:",l.statusText),n();return}const m=await l.json();n();const p=(()=>{var d=x(),u=d.firstChild,y=u.firstChild,f=u.nextSibling;return u.$$click=s,c(y,"src",`${b}/cross.svg`),Z(a=>{var h=m.url,v=m.width,g=m.height;return h!==a.e&&c(f,"src",a.e=h),v!==a.t&&c(f,"width",a.t=v),g!==a.a&&c(f,"height",a.a=g),a},{e:void 0,t:void 0,a:void 0}),d})();e.addEventListener("keyup",i),e.appendChild(p)}catch(i){console.error("Error fetching zoom image:",i),n()}}$(["click"]);L();
|