@panda-lingo/goldendict 0.1.1 → 0.1.2
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 +23 -4
- package/dist/element/goldendict-view.d.ts +3 -1
- package/dist/element/goldendict-view.d.ts.map +1 -1
- package/dist/index.js +45 -37
- package/dist/index.js.map +1 -1
- package/dist/renderer/article-document.d.ts +2 -1
- package/dist/renderer/article-document.d.ts.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,24 @@ scrollable, unwraps common floated wiki panels on narrow screens, and keeps
|
|
|
28
28
|
article headers usable with coarse pointers. The pinned GoldenDict-ng CSS stays
|
|
29
29
|
unchanged so upstream updates remain straightforward.
|
|
30
30
|
|
|
31
|
+
For GoldenDict-compatible article geometry, select the fidelity layout. This
|
|
32
|
+
omits the browser override layer so the upstream body margin, content-box model,
|
|
33
|
+
dictionary header flow, and dictionary-authored CSS cascade remain intact.
|
|
34
|
+
Script permission is independent: a dictionary may require both fidelity layout
|
|
35
|
+
and sandboxed sidecar JavaScript.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
view.layoutMode = "fidelity";
|
|
39
|
+
view.scriptPolicy = "sandboxed";
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The default `layoutMode` is `"responsive"`; the bundled demo deliberately uses
|
|
43
|
+
`"fidelity"` so it can be compared directly with GoldenDict-ng. Consumers can
|
|
44
|
+
also set `layout-mode="fidelity"` on the custom element.
|
|
45
|
+
|
|
46
|
+
Compare at the same CSS viewport, device scale, and GoldenDict zoom: those host
|
|
47
|
+
browser settings still affect physical pixel size and line wrapping.
|
|
48
|
+
|
|
31
49
|
```css
|
|
32
50
|
.dictionary-column {
|
|
33
51
|
min-width: 0;
|
|
@@ -59,10 +77,11 @@ explicit `"sandboxed"` policy retains them inside the iframe, which never gets
|
|
|
59
77
|
`allow-same-origin`. Lookup, media, and external-link events are cancelable so a
|
|
60
78
|
host application can replace the default navigation behavior.
|
|
61
79
|
|
|
62
|
-
The bundled demo deliberately selects `"sandboxed"`
|
|
63
|
-
dictionaries so script-dependent formats such as
|
|
64
|
-
GoldenDict typography and interactions.
|
|
65
|
-
component
|
|
80
|
+
The bundled demo deliberately selects `"sandboxed"` scripts and `"fidelity"`
|
|
81
|
+
layout for locally mounted dictionaries so script-dependent formats such as
|
|
82
|
+
OALDPE render with their GoldenDict typography, geometry, and interactions.
|
|
83
|
+
These demo choices do not change the component defaults (`"none"` scripts and
|
|
84
|
+
`"responsive"` layout) for consumers.
|
|
66
85
|
|
|
67
86
|
In sandboxed mode, external sidecars such as `bres://.../Dictionary-UI.js` are
|
|
68
87
|
routed through the article's `resourceBaseUrl` without changing filename case.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DictionaryClient } from "../client/dictionary-client";
|
|
2
|
-
import type { DictionaryClientOptions, GoldenDictTheme, LookupResponse, ScriptPolicy, ViewState } from "../types";
|
|
2
|
+
import type { ArticleLayoutMode, DictionaryClientOptions, GoldenDictTheme, LookupResponse, ScriptPolicy, ViewState } from "../types";
|
|
3
3
|
export declare class GoldenDictView extends HTMLElement {
|
|
4
4
|
static readonly observedAttributes: string[];
|
|
5
5
|
readonly instanceId: string;
|
|
@@ -30,6 +30,8 @@ export declare class GoldenDictView extends HTMLElement {
|
|
|
30
30
|
set theme(value: GoldenDictTheme);
|
|
31
31
|
get scriptPolicy(): ScriptPolicy;
|
|
32
32
|
set scriptPolicy(value: ScriptPolicy);
|
|
33
|
+
get layoutMode(): ArticleLayoutMode;
|
|
34
|
+
set layoutMode(value: ArticleLayoutMode);
|
|
33
35
|
get dictionaryIds(): readonly string[];
|
|
34
36
|
set dictionaryIds(value: readonly string[]);
|
|
35
37
|
get state(): ViewState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goldendict-view.d.ts","sourceRoot":"","sources":["../../src/element/goldendict-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"goldendict-view.d.ts","sourceRoot":"","sources":["../../src/element/goldendict-view.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -8076,8 +8076,8 @@ function p(i, e) {
|
|
|
8076
8076
|
try {
|
|
8077
8077
|
t = new URL(i);
|
|
8078
8078
|
} catch {
|
|
8079
|
-
const
|
|
8080
|
-
return
|
|
8079
|
+
const d = S(e);
|
|
8080
|
+
return d ? pe(i, d) : i;
|
|
8081
8081
|
}
|
|
8082
8082
|
const n = t.protocol.slice(0, -1).toLowerCase();
|
|
8083
8083
|
if (!T.has(n))
|
|
@@ -8088,7 +8088,7 @@ function p(i, e) {
|
|
|
8088
8088
|
...e,
|
|
8089
8089
|
iconUrl: void 0
|
|
8090
8090
|
}) : A("qrc:///icons/document.png") ?? "";
|
|
8091
|
-
const r = me(t),
|
|
8091
|
+
const r = me(t), l = `${e.apiBaseUrl.replace(/\/+$/, "")}/dictionaries/${encodeURIComponent(a)}/resources`, m = I(S(e) ?? l, r);
|
|
8092
8092
|
return t.hash ? `${m}${t.hash}` : m;
|
|
8093
8093
|
}
|
|
8094
8094
|
function ge(i) {
|
|
@@ -8103,8 +8103,8 @@ function ge(i) {
|
|
|
8103
8103
|
const r = new URL(i);
|
|
8104
8104
|
t = r.searchParams.get("word") ?? r.pathname.replace(/^\/+/, ""), n = r.searchParams.get("gdanchor") ?? (r.hash.slice(1) || void 0), a = r.searchParams.get("dictionaries")?.split(",").filter(Boolean), !t && (o === "bword" || o === "entry") && (t = r.hostname);
|
|
8105
8105
|
} catch {
|
|
8106
|
-
const r = e[2]?.replace(/^\/{0,2}/, "") ?? "", [
|
|
8107
|
-
t =
|
|
8106
|
+
const r = e[2]?.replace(/^\/{0,2}/, "") ?? "", [l, m] = r.split("#", 2), [d, w] = (l ?? "").split("?", 2);
|
|
8107
|
+
t = d ?? "", n = new URLSearchParams(w ?? "").get("gdanchor") ?? (m || void 0);
|
|
8108
8108
|
}
|
|
8109
8109
|
return t = f(t.replace(/^\/+/, "")), t ? {
|
|
8110
8110
|
kind: "lookup",
|
|
@@ -8154,10 +8154,10 @@ function fe(i, e, o) {
|
|
|
8154
8154
|
];
|
|
8155
8155
|
for (const [a, r] of t)
|
|
8156
8156
|
if (i.hasAttribute(a)) {
|
|
8157
|
-
const
|
|
8157
|
+
const l = i.getAttribute(a)?.trim();
|
|
8158
8158
|
return {
|
|
8159
8159
|
kind: r,
|
|
8160
|
-
url: p(
|
|
8160
|
+
url: p(l || e, o)
|
|
8161
8161
|
};
|
|
8162
8162
|
}
|
|
8163
8163
|
const n = i.getAttribute("data-gd-action")?.trim().toLowerCase();
|
|
@@ -8170,8 +8170,8 @@ function fe(i, e, o) {
|
|
|
8170
8170
|
const r = D(e, o);
|
|
8171
8171
|
if (r.kind === "lookup")
|
|
8172
8172
|
return r;
|
|
8173
|
-
const
|
|
8174
|
-
return
|
|
8173
|
+
const l = i.getAttribute("data-gd-word")?.trim();
|
|
8174
|
+
return l ? { kind: "lookup", word: l } : { kind: "unsafe" };
|
|
8175
8175
|
}
|
|
8176
8176
|
if (n === "unsafe")
|
|
8177
8177
|
return { kind: "unsafe" };
|
|
@@ -8243,25 +8243,25 @@ function ue(i, e, o) {
|
|
|
8243
8243
|
}), o === "none" && a.querySelectorAll("script").forEach((r) => r.remove());
|
|
8244
8244
|
for (const r of a.querySelectorAll("*")) {
|
|
8245
8245
|
if (ke(r), o === "none")
|
|
8246
|
-
for (const
|
|
8247
|
-
(/^on/i.test(
|
|
8246
|
+
for (const d of [...r.attributes])
|
|
8247
|
+
(/^on/i.test(d.name) || d.name.toLowerCase() === "srcdoc") && r.removeAttribute(d.name);
|
|
8248
8248
|
if (r instanceof HTMLAnchorElement || r.tagName === "AREA") {
|
|
8249
|
-
const
|
|
8250
|
-
|
|
8249
|
+
const d = r.getAttribute("href");
|
|
8250
|
+
d !== null && we(
|
|
8251
8251
|
r,
|
|
8252
|
-
fe(r,
|
|
8252
|
+
fe(r, d, t) ?? D(d, t),
|
|
8253
8253
|
i.dictionaryId
|
|
8254
8254
|
);
|
|
8255
8255
|
} else if (r.hasAttribute("href")) {
|
|
8256
|
-
const
|
|
8257
|
-
x(
|
|
8256
|
+
const d = r.getAttribute("href") ?? "";
|
|
8257
|
+
x(d) || r.setAttribute("href", p(d, t));
|
|
8258
8258
|
}
|
|
8259
|
-
for (const
|
|
8260
|
-
const w = r.getAttribute(
|
|
8261
|
-
w === null || x(w) || (/^(?:javascript|vbscript|file):/i.test(w) ? r.removeAttribute(
|
|
8259
|
+
for (const d of he) {
|
|
8260
|
+
const w = r.getAttribute(d);
|
|
8261
|
+
w === null || x(w) || (/^(?:javascript|vbscript|file):/i.test(w) ? r.removeAttribute(d) : r.setAttribute(d, p(w, t)));
|
|
8262
8262
|
}
|
|
8263
|
-
const
|
|
8264
|
-
|
|
8263
|
+
const l = r.getAttribute("srcset");
|
|
8264
|
+
l && r.setAttribute("srcset", be(l, t));
|
|
8265
8265
|
const m = r.getAttribute("style");
|
|
8266
8266
|
m && r.setAttribute(
|
|
8267
8267
|
"style",
|
|
@@ -8362,7 +8362,7 @@ function Ae(i, e) {
|
|
|
8362
8362
|
}) : u["document.png"];
|
|
8363
8363
|
}
|
|
8364
8364
|
function Se(i, e, o) {
|
|
8365
|
-
const t = g(i.dictionaryId), n = _e(i.dictionaryId), a = ue(i, e, o), r = ze(i.sourceLanguage),
|
|
8365
|
+
const t = g(i.dictionaryId), n = _e(i.dictionaryId), a = ue(i, e, o), r = ze(i.sourceLanguage), l = g(i.targetLanguage ?? ""), m = g(Ae(i, e));
|
|
8366
8366
|
return `
|
|
8367
8367
|
<article class="gdarticle" id="gdfrom-${n}" data-gd-id="${t}">
|
|
8368
8368
|
<gd-dict-header class="gddictname" id="gddictname-${n}"
|
|
@@ -8375,9 +8375,9 @@ function Se(i, e, o) {
|
|
|
8375
8375
|
</span>
|
|
8376
8376
|
</gd-dict-header>
|
|
8377
8377
|
<section class="gdarticlebody gdlangfrom-${r}"
|
|
8378
|
-
lang="${
|
|
8378
|
+
lang="${l}" style="display:block" id="gd-${n}">${a}</section>
|
|
8379
8379
|
</article>
|
|
8380
|
-
<div
|
|
8380
|
+
<div style="clear:both;" aria-hidden="true"></div>
|
|
8381
8381
|
<span class="gdarticleseparator"></span>`;
|
|
8382
8382
|
}
|
|
8383
8383
|
function Ce(i) {
|
|
@@ -8565,24 +8565,24 @@ function Ie(i, e) {
|
|
|
8565
8565
|
].join("; ");
|
|
8566
8566
|
}
|
|
8567
8567
|
function De(i, e) {
|
|
8568
|
-
const o = e.theme ?? {}, t = E(o.mode), n = e.instanceId.replace(/[^a-zA-Z0-9_-]/g, ""),
|
|
8569
|
-
(
|
|
8570
|
-
).join(""),
|
|
8568
|
+
const o = e.theme ?? {}, t = E(o.mode), n = e.layoutMode ?? "responsive", a = e.instanceId.replace(/[^a-zA-Z0-9_-]/g, ""), r = i.articles.map(
|
|
8569
|
+
(d) => Se(d, e.apiBaseUrl, e.scriptPolicy)
|
|
8570
|
+
).join(""), l = r ? `${r}<div class="empty-space" aria-hidden="true"></div>` : `<div class="gdnotfound"><p>No translation for <b>${g(i.word)}</b> was found.</p></div>`, m = o.brandName ? `${i.word} — ${o.brandName}` : i.word;
|
|
8571
8571
|
return `<!doctype html>
|
|
8572
|
-
<html data-gd-theme="${t}" data-darkreader-scheme="${t}"><head>
|
|
8572
|
+
<html data-gd-theme="${t}" data-gd-layout="${n}" data-darkreader-scheme="${t}"><head>
|
|
8573
8573
|
<meta charset="utf-8">
|
|
8574
8574
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
8575
|
-
<meta http-equiv="Content-Security-Policy" content="${g(Ie(e.scriptPolicy,
|
|
8576
|
-
<title>${g(
|
|
8575
|
+
<meta http-equiv="Content-Security-Policy" content="${g(Ie(e.scriptPolicy, a))}">
|
|
8576
|
+
<title>${g(m)}</title>
|
|
8577
8577
|
<style>${k(re)}</style>
|
|
8578
8578
|
<style>${k(de(o.preset))}</style>
|
|
8579
|
-
|
|
8579
|
+
${n === "responsive" ? `<style data-gd-style="responsive">${k(le)}</style>` : ""}
|
|
8580
8580
|
<style>${ve(o)}</style>
|
|
8581
8581
|
<style media="print">${k(ae)}</style>
|
|
8582
8582
|
</head><body>
|
|
8583
|
-
${
|
|
8583
|
+
${l}
|
|
8584
8584
|
${Ce(i.suggestions)}
|
|
8585
|
-
<script nonce="${
|
|
8585
|
+
<script nonce="${a}">${Te(e.instanceId, t).replace(/<\/script/gi, "<\\/script")}<\/script>
|
|
8586
8586
|
</body></html>`;
|
|
8587
8587
|
}
|
|
8588
8588
|
const b = {
|
|
@@ -8622,7 +8622,8 @@ class _ extends HTMLElement {
|
|
|
8622
8622
|
"word",
|
|
8623
8623
|
"preset",
|
|
8624
8624
|
"theme-mode",
|
|
8625
|
-
"script-policy"
|
|
8625
|
+
"script-policy",
|
|
8626
|
+
"layout-mode"
|
|
8626
8627
|
];
|
|
8627
8628
|
instanceId = qe();
|
|
8628
8629
|
frame;
|
|
@@ -8668,7 +8669,7 @@ class _ extends HTMLElement {
|
|
|
8668
8669
|
} : e === "theme-mode" ? this.theme = {
|
|
8669
8670
|
...this.themeValue,
|
|
8670
8671
|
mode: t || "light"
|
|
8671
|
-
} : e === "script-policy" && this.responseValue && this.renderResponse(this.responseValue));
|
|
8672
|
+
} : (e === "script-policy" || e === "layout-mode") && this.responseValue && this.renderResponse(this.responseValue));
|
|
8672
8673
|
}
|
|
8673
8674
|
get apiBase() {
|
|
8674
8675
|
return this.getAttribute("api-base")?.trim() || "/api/v1";
|
|
@@ -8694,6 +8695,12 @@ class _ extends HTMLElement {
|
|
|
8694
8695
|
set scriptPolicy(e) {
|
|
8695
8696
|
this.setAttribute("script-policy", e);
|
|
8696
8697
|
}
|
|
8698
|
+
get layoutMode() {
|
|
8699
|
+
return this.getAttribute("layout-mode") === "fidelity" ? "fidelity" : "responsive";
|
|
8700
|
+
}
|
|
8701
|
+
set layoutMode(e) {
|
|
8702
|
+
this.setAttribute("layout-mode", e);
|
|
8703
|
+
}
|
|
8697
8704
|
get dictionaryIds() {
|
|
8698
8705
|
return this.dictionaryIdsValue;
|
|
8699
8706
|
}
|
|
@@ -8729,8 +8736,8 @@ class _ extends HTMLElement {
|
|
|
8729
8736
|
} catch (r) {
|
|
8730
8737
|
if (n !== this.requestSequence || Le(r))
|
|
8731
8738
|
return;
|
|
8732
|
-
const
|
|
8733
|
-
this.responseValue = void 0, this.resetFrame(), this.setState("error", { word: t, error:
|
|
8739
|
+
const l = r instanceof Error ? r : new Error(String(r));
|
|
8740
|
+
this.responseValue = void 0, this.resetFrame(), this.setState("error", { word: t, error: l });
|
|
8734
8741
|
} finally {
|
|
8735
8742
|
n === this.requestSequence && (this.requestController = void 0);
|
|
8736
8743
|
}
|
|
@@ -8756,6 +8763,7 @@ class _ extends HTMLElement {
|
|
|
8756
8763
|
apiBaseUrl: this.clientValue.baseUrl,
|
|
8757
8764
|
instanceId: t,
|
|
8758
8765
|
scriptPolicy: this.scriptPolicy,
|
|
8766
|
+
layoutMode: this.layoutMode,
|
|
8759
8767
|
theme: this.themeValue
|
|
8760
8768
|
});
|
|
8761
8769
|
requestAnimationFrame(() => {
|