@ugfoundation/swaralipi-js 0.7.0 → 0.7.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 +22 -3
- package/dist/{batch-UG26T3IE.js → batch-W56YUPJC.js} +4 -4
- package/dist/{batch-UG26T3IE.js.map → batch-W56YUPJC.js.map} +1 -1
- package/dist/{chunk-KMIW7ZBA.js → chunk-AAQIY4VS.js} +3 -3
- package/dist/{chunk-KMIW7ZBA.js.map → chunk-AAQIY4VS.js.map} +1 -1
- package/dist/{chunk-NFKKXN7S.js → chunk-RLJQ5UIN.js} +3 -3
- package/dist/{chunk-NFKKXN7S.js.map → chunk-RLJQ5UIN.js.map} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/convert/index.cjs +1 -1
- package/dist/convert/index.cjs.map +1 -1
- package/dist/convert/index.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/spec/index.cjs +1 -1
- package/dist/spec/index.cjs.map +1 -1
- package/dist/spec/index.d.cts +1 -1
- package/dist/spec/index.d.ts +1 -1
- package/dist/spec/index.js +1 -1
- package/dist/viewer/index.cjs +57 -11
- package/dist/viewer/index.cjs.map +1 -1
- package/dist/viewer/index.d.cts +34 -11
- package/dist/viewer/index.d.ts +34 -11
- package/dist/viewer/index.js +56 -10
- package/dist/viewer/index.js.map +1 -1
- package/package.json +1 -1
package/dist/viewer/index.d.cts
CHANGED
|
@@ -184,22 +184,33 @@ declare function renderToHtml(doc: Swaralipi, opts?: RenderOptions): string;
|
|
|
184
184
|
* top.
|
|
185
185
|
*
|
|
186
186
|
* The whole document is one grid (see render.ts), so a sheet has exactly one
|
|
187
|
-
* natural width — a wide তাল overruns a phone or an A4 page.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
187
|
+
* natural width — a wide তাল overruns a phone or an A4 page. Two levers, in
|
|
188
|
+
* this order, because they cost different things:
|
|
189
|
+
*
|
|
190
|
+
* 1. **Spacing.** `--sw-cell-gap` and the `--sw-matra` column floor are
|
|
191
|
+
* 25–35 % of that natural width (measured over the corpus), and giving
|
|
192
|
+
* them up costs only air between the columns — the alignment is
|
|
193
|
+
* untouched, since every row still borrows the same tracks. Compressed
|
|
194
|
+
* only as far as the container demands, down to `minSpacing`.
|
|
195
|
+
* 2. **Type size.** Everything inside is em-relative, so scaling the sheet's
|
|
196
|
+
* `font-size` scales the notation without disturbing the columns (a
|
|
197
|
+
* `transform` would scale it too, but would also break print
|
|
198
|
+
* pagination). This is what actually makes the glyphs smaller, so it
|
|
199
|
+
* runs second and stops at `minSize` px — past that the block scrolls
|
|
200
|
+
* inside `.sw-scroll` rather than becoming unreadable. It also runs the
|
|
201
|
+
* other way: a sheet narrower than its container grows (to 2x) rather
|
|
202
|
+
* than leaving dead space to the right of every row.
|
|
191
203
|
*
|
|
192
|
-
* Free-scaling by default (no floor): the sheet should always fit on first
|
|
193
|
-
* paint rather than fall back to `.sw-scroll`'s horizontal scrollbar — a
|
|
194
|
-
* `minScale` floor exists only for print, where paper cannot scroll.
|
|
195
204
|
* `zoom` (default 1) multiplies the fit scale so callers can zoom in past
|
|
196
|
-
* fit-to-width
|
|
197
|
-
* photo viewer.
|
|
205
|
+
* fit-to-width, or below the readability floor deliberately; past that point
|
|
206
|
+
* `.sw-scroll` panning is expected, same as a photo viewer. `minScale` is a
|
|
207
|
+
* second, relative floor used by print, where paper cannot scroll.
|
|
198
208
|
*
|
|
199
209
|
* Self-contained on purpose — print.ts serialises this function into the
|
|
200
|
-
* print page, so it must not close over anything or import anything
|
|
210
|
+
* print page, so it must not close over anything or import anything (the
|
|
211
|
+
* defaults below are literals for the same reason).
|
|
201
212
|
*/
|
|
202
|
-
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number): void;
|
|
213
|
+
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number, minSpacing?: number, minSize?: number): void;
|
|
203
214
|
/** Zoom bounds/step for zoomIn()/zoomOut()/the `zoom` property — exported so
|
|
204
215
|
* a consumer's own zoom UI (e.g. a slider) can match the element's clamp. */
|
|
205
216
|
declare const MIN_ZOOM = 0.5;
|
|
@@ -215,6 +226,11 @@ declare const ZOOM_STEP = 1.2;
|
|
|
215
226
|
* --sw-font font stack (default: Noto Sans Bengali + system Bengali)
|
|
216
227
|
* --sw-size base font size
|
|
217
228
|
* --sw-cell-gap horizontal gap between source cells
|
|
229
|
+
* --sw-tight 0–1 multiplier on the column spacing (gap + matra floor);
|
|
230
|
+
* set by fitSwaralipi to compress before shrinking type
|
|
231
|
+
* --sw-matra minimum width of one matra column
|
|
232
|
+
* --sw-header-min floor for the নাম/তাল/আবর্তন header (it must stay legible
|
|
233
|
+
* when the notation is scaled down to fit a phone)
|
|
218
234
|
* --sw-hl player-highlight background (P2.3)
|
|
219
235
|
* --sw-rule header rule / muted line color
|
|
220
236
|
*
|
|
@@ -492,6 +508,13 @@ interface SwaralipiSheetElement extends HTMLElement {
|
|
|
492
508
|
staffOptions: StaffOptions;
|
|
493
509
|
/** Re-fit the notation to the element's current width. */
|
|
494
510
|
fit(): void;
|
|
511
|
+
/** How far the column spacing may be compressed to fit a narrow container
|
|
512
|
+
* before the type is scaled down at all, 0–1 (attribute `min-spacing`;
|
|
513
|
+
* undefined = the library default). Lower = tighter columns, bigger glyphs. */
|
|
514
|
+
minSpacing: number | undefined;
|
|
515
|
+
/** Smallest notation size in px the fit may produce (attribute `min-size`);
|
|
516
|
+
* past it the sheet scrolls horizontally instead of shrinking further. */
|
|
517
|
+
minSize: number | undefined;
|
|
495
518
|
/** Zoom factor on top of fit-to-width (1 = fit; clamped to
|
|
496
519
|
* [MIN_ZOOM, MAX_ZOOM]). Assigning re-fits immediately. Resets to 1 on the
|
|
497
520
|
* next doc/lang re-render — a resize alone (fit()) does not reset it. */
|
package/dist/viewer/index.d.ts
CHANGED
|
@@ -184,22 +184,33 @@ declare function renderToHtml(doc: Swaralipi, opts?: RenderOptions): string;
|
|
|
184
184
|
* top.
|
|
185
185
|
*
|
|
186
186
|
* The whole document is one grid (see render.ts), so a sheet has exactly one
|
|
187
|
-
* natural width — a wide তাল overruns a phone or an A4 page.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
187
|
+
* natural width — a wide তাল overruns a phone or an A4 page. Two levers, in
|
|
188
|
+
* this order, because they cost different things:
|
|
189
|
+
*
|
|
190
|
+
* 1. **Spacing.** `--sw-cell-gap` and the `--sw-matra` column floor are
|
|
191
|
+
* 25–35 % of that natural width (measured over the corpus), and giving
|
|
192
|
+
* them up costs only air between the columns — the alignment is
|
|
193
|
+
* untouched, since every row still borrows the same tracks. Compressed
|
|
194
|
+
* only as far as the container demands, down to `minSpacing`.
|
|
195
|
+
* 2. **Type size.** Everything inside is em-relative, so scaling the sheet's
|
|
196
|
+
* `font-size` scales the notation without disturbing the columns (a
|
|
197
|
+
* `transform` would scale it too, but would also break print
|
|
198
|
+
* pagination). This is what actually makes the glyphs smaller, so it
|
|
199
|
+
* runs second and stops at `minSize` px — past that the block scrolls
|
|
200
|
+
* inside `.sw-scroll` rather than becoming unreadable. It also runs the
|
|
201
|
+
* other way: a sheet narrower than its container grows (to 2x) rather
|
|
202
|
+
* than leaving dead space to the right of every row.
|
|
191
203
|
*
|
|
192
|
-
* Free-scaling by default (no floor): the sheet should always fit on first
|
|
193
|
-
* paint rather than fall back to `.sw-scroll`'s horizontal scrollbar — a
|
|
194
|
-
* `minScale` floor exists only for print, where paper cannot scroll.
|
|
195
204
|
* `zoom` (default 1) multiplies the fit scale so callers can zoom in past
|
|
196
|
-
* fit-to-width
|
|
197
|
-
* photo viewer.
|
|
205
|
+
* fit-to-width, or below the readability floor deliberately; past that point
|
|
206
|
+
* `.sw-scroll` panning is expected, same as a photo viewer. `minScale` is a
|
|
207
|
+
* second, relative floor used by print, where paper cannot scroll.
|
|
198
208
|
*
|
|
199
209
|
* Self-contained on purpose — print.ts serialises this function into the
|
|
200
|
-
* print page, so it must not close over anything or import anything
|
|
210
|
+
* print page, so it must not close over anything or import anything (the
|
|
211
|
+
* defaults below are literals for the same reason).
|
|
201
212
|
*/
|
|
202
|
-
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number): void;
|
|
213
|
+
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number, minSpacing?: number, minSize?: number): void;
|
|
203
214
|
/** Zoom bounds/step for zoomIn()/zoomOut()/the `zoom` property — exported so
|
|
204
215
|
* a consumer's own zoom UI (e.g. a slider) can match the element's clamp. */
|
|
205
216
|
declare const MIN_ZOOM = 0.5;
|
|
@@ -215,6 +226,11 @@ declare const ZOOM_STEP = 1.2;
|
|
|
215
226
|
* --sw-font font stack (default: Noto Sans Bengali + system Bengali)
|
|
216
227
|
* --sw-size base font size
|
|
217
228
|
* --sw-cell-gap horizontal gap between source cells
|
|
229
|
+
* --sw-tight 0–1 multiplier on the column spacing (gap + matra floor);
|
|
230
|
+
* set by fitSwaralipi to compress before shrinking type
|
|
231
|
+
* --sw-matra minimum width of one matra column
|
|
232
|
+
* --sw-header-min floor for the নাম/তাল/আবর্তন header (it must stay legible
|
|
233
|
+
* when the notation is scaled down to fit a phone)
|
|
218
234
|
* --sw-hl player-highlight background (P2.3)
|
|
219
235
|
* --sw-rule header rule / muted line color
|
|
220
236
|
*
|
|
@@ -492,6 +508,13 @@ interface SwaralipiSheetElement extends HTMLElement {
|
|
|
492
508
|
staffOptions: StaffOptions;
|
|
493
509
|
/** Re-fit the notation to the element's current width. */
|
|
494
510
|
fit(): void;
|
|
511
|
+
/** How far the column spacing may be compressed to fit a narrow container
|
|
512
|
+
* before the type is scaled down at all, 0–1 (attribute `min-spacing`;
|
|
513
|
+
* undefined = the library default). Lower = tighter columns, bigger glyphs. */
|
|
514
|
+
minSpacing: number | undefined;
|
|
515
|
+
/** Smallest notation size in px the fit may produce (attribute `min-size`);
|
|
516
|
+
* past it the sheet scrolls horizontally instead of shrinking further. */
|
|
517
|
+
minSize: number | undefined;
|
|
495
518
|
/** Zoom factor on top of fit-to-width (1 = fit; clamped to
|
|
496
519
|
* [MIN_ZOOM, MAX_ZOOM]). Assigning re-fits immediately. Resets to 1 on the
|
|
497
520
|
* next doc/lang re-render — a resize alone (fit()) does not reset it. */
|
package/dist/viewer/index.js
CHANGED
|
@@ -464,7 +464,7 @@ function renderToHtml(doc, opts = {}) {
|
|
|
464
464
|
const tr = lang !== "bn" && opts.transliterate ? opts.transliterate : (s) => s;
|
|
465
465
|
const ctx = { lang, marks: MARKS[lang], tr };
|
|
466
466
|
const layout = alignRows(doc.parts.flatMap((p) => p.rows.map((r) => groupRowIntoCells(r.notes))));
|
|
467
|
-
const tracks = `grid-template-columns:max-content repeat(${layout.width},minmax(var(--sw-matra, 1.4em),max-content))`;
|
|
467
|
+
const tracks = `grid-template-columns:max-content repeat(${layout.width},minmax(calc(var(--sw-matra, 1.4em) * var(--sw-tight, 1)),max-content))`;
|
|
468
468
|
const out = [`<div class="sw-sheet" lang="${lang}">`];
|
|
469
469
|
if (opts.showHeader !== false) out.push(renderHeader(doc.meta, ctx));
|
|
470
470
|
out.push(`<div class="sw-scroll"><div class="sw-block" style="${tracks}">`);
|
|
@@ -481,20 +481,35 @@ function renderToHtml(doc, opts = {}) {
|
|
|
481
481
|
}
|
|
482
482
|
|
|
483
483
|
// src/viewer/fit.ts
|
|
484
|
-
function fitSwaralipi(root, minScale = 0, zoom = 1) {
|
|
484
|
+
function fitSwaralipi(root, minScale = 0, zoom = 1, minSpacing = 0.35, minSize = 12) {
|
|
485
485
|
const sheets = root.querySelectorAll(".sw-sheet");
|
|
486
486
|
for (const sheet of sheets) {
|
|
487
487
|
const scroll = sheet.querySelector(".sw-scroll");
|
|
488
488
|
const block = sheet.querySelector(".sw-block");
|
|
489
489
|
if (scroll === null || block === null) continue;
|
|
490
490
|
sheet.style.removeProperty("--sw-size");
|
|
491
|
+
sheet.style.removeProperty("--sw-tight");
|
|
491
492
|
const available = scroll.clientWidth;
|
|
492
|
-
|
|
493
|
+
let natural = block.scrollWidth;
|
|
493
494
|
if (available === 0 || natural === 0) continue;
|
|
494
|
-
|
|
495
|
+
if (natural > available && minSpacing < 1) {
|
|
496
|
+
let loose = minSpacing;
|
|
497
|
+
let tight = 1;
|
|
498
|
+
for (let i = 0; i < 6; i++) {
|
|
499
|
+
const mid = (loose + tight) / 2;
|
|
500
|
+
sheet.style.setProperty("--sw-tight", String(mid));
|
|
501
|
+
if (block.scrollWidth <= available) loose = mid;
|
|
502
|
+
else tight = mid;
|
|
503
|
+
}
|
|
504
|
+
sheet.style.setProperty("--sw-tight", String(loose));
|
|
505
|
+
natural = block.scrollWidth;
|
|
506
|
+
}
|
|
507
|
+
const base = parseFloat(getComputedStyle(sheet).fontSize);
|
|
508
|
+
if (!(base > 0)) continue;
|
|
509
|
+
let fit = Math.max(minScale, Math.min((available - 1) / natural, 2));
|
|
510
|
+
if (minSize > 0) fit = Math.max(fit, Math.min(1, minSize / base));
|
|
495
511
|
const scale = fit * zoom;
|
|
496
512
|
if (scale === 1) continue;
|
|
497
|
-
const base = parseFloat(getComputedStyle(sheet).fontSize);
|
|
498
513
|
sheet.style.setProperty("--sw-size", `${(base * scale).toFixed(3)}px`);
|
|
499
514
|
}
|
|
500
515
|
}
|
|
@@ -531,7 +546,10 @@ ${FONT_FACES}
|
|
|
531
546
|
margin: 0 0 0.75em;
|
|
532
547
|
padding: 0 0 0.5em;
|
|
533
548
|
border-bottom: 1px solid var(--sw-rule, rgba(128, 128, 128, 0.35));
|
|
534
|
-
|
|
549
|
+
/* Scales with the sheet, but never below the floor: fitSwaralipi shrinks
|
|
550
|
+
.sw-sheet's font-size to fit the notation, and the metadata is prose \u2014
|
|
551
|
+
it has no columns to align and must stay readable on a phone. */
|
|
552
|
+
font-size: max(0.95em, var(--sw-header-min, 0.95rem));
|
|
535
553
|
}
|
|
536
554
|
.sw-meta-row { display: flex; gap: 0.3em; }
|
|
537
555
|
.sw-meta-label { font-weight: 600; min-width: 4.5em; }
|
|
@@ -547,7 +565,7 @@ ${FONT_FACES}
|
|
|
547
565
|
.sw-scroll { overflow-x: auto; }
|
|
548
566
|
.sw-block {
|
|
549
567
|
display: grid;
|
|
550
|
-
column-gap: var(--sw-cell-gap, 0.4em);
|
|
568
|
+
column-gap: calc(var(--sw-cell-gap, 0.4em) * var(--sw-tight, 1));
|
|
551
569
|
align-items: end;
|
|
552
570
|
width: max-content;
|
|
553
571
|
}
|
|
@@ -1030,7 +1048,7 @@ body { width: 178mm; color: #111; background: #fff; -webkit-print-color-adjust:
|
|
|
1030
1048
|
</style>
|
|
1031
1049
|
</head>
|
|
1032
1050
|
<body>${top}${bodyHtml}${bottom}
|
|
1033
|
-
<script>window.__swFit=function(){(${fitSwaralipi.toString()})(document,0.45)};window.__swFit()</script>
|
|
1051
|
+
<script>window.__swFit=function(){(${fitSwaralipi.toString()})(document,0.45,1,undefined,0)};window.__swFit()</script>
|
|
1034
1052
|
</body>
|
|
1035
1053
|
</html>`;
|
|
1036
1054
|
}
|
|
@@ -1121,7 +1139,7 @@ function ensureNotationFonts() {
|
|
|
1121
1139
|
var sharedSheet;
|
|
1122
1140
|
function createElementClass() {
|
|
1123
1141
|
return class SwaralipiSheet extends HTMLElement {
|
|
1124
|
-
static observedAttributes = ["src", "lang", "hide-header"];
|
|
1142
|
+
static observedAttributes = ["src", "lang", "hide-header", "min-spacing", "min-size"];
|
|
1125
1143
|
#doc;
|
|
1126
1144
|
#root;
|
|
1127
1145
|
#adopted = false;
|
|
@@ -1176,6 +1194,10 @@ function createElementClass() {
|
|
|
1176
1194
|
if (newValue !== null) void this.#load(newValue);
|
|
1177
1195
|
return;
|
|
1178
1196
|
}
|
|
1197
|
+
if (name === "min-spacing" || name === "min-size") {
|
|
1198
|
+
this.fit();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1179
1201
|
if (name === "lang") this.#ensureTransliterator();
|
|
1180
1202
|
this.#render();
|
|
1181
1203
|
}
|
|
@@ -1199,7 +1221,28 @@ function createElementClass() {
|
|
|
1199
1221
|
}
|
|
1200
1222
|
/** Scale the notation to fit the available width, times the zoom factor. */
|
|
1201
1223
|
#fit() {
|
|
1202
|
-
fitSwaralipi(this.#root, 0, this.#zoom);
|
|
1224
|
+
fitSwaralipi(this.#root, 0, this.#zoom, this.minSpacing, this.minSize);
|
|
1225
|
+
}
|
|
1226
|
+
/** Numeric attribute, or undefined for fitSwaralipi's own default. */
|
|
1227
|
+
#attrNum(name) {
|
|
1228
|
+
const value = parseFloat(this.getAttribute(name) ?? "");
|
|
1229
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1230
|
+
}
|
|
1231
|
+
#setAttrNum(name, value) {
|
|
1232
|
+
if (value === void 0) this.removeAttribute(name);
|
|
1233
|
+
else this.setAttribute(name, String(value));
|
|
1234
|
+
}
|
|
1235
|
+
get minSpacing() {
|
|
1236
|
+
return this.#attrNum("min-spacing");
|
|
1237
|
+
}
|
|
1238
|
+
set minSpacing(value) {
|
|
1239
|
+
this.#setAttrNum("min-spacing", value);
|
|
1240
|
+
}
|
|
1241
|
+
get minSize() {
|
|
1242
|
+
return this.#attrNum("min-size");
|
|
1243
|
+
}
|
|
1244
|
+
set minSize(value) {
|
|
1245
|
+
this.#setAttrNum("min-size", value);
|
|
1203
1246
|
}
|
|
1204
1247
|
/** Re-fit the current render (public for hosts that resize the sheet
|
|
1205
1248
|
* themselves, e.g. a tab that was hidden while the document loaded). */
|
|
@@ -1273,6 +1316,9 @@ function createElementClass() {
|
|
|
1273
1316
|
});
|
|
1274
1317
|
this.#root.innerHTML = this.#styleFallback() + html;
|
|
1275
1318
|
this.#fit();
|
|
1319
|
+
void document.fonts?.ready.then(() => {
|
|
1320
|
+
if (seq === this.#renderSeq) this.fit();
|
|
1321
|
+
});
|
|
1276
1322
|
}
|
|
1277
1323
|
#renderError(message) {
|
|
1278
1324
|
const div = document.createElement("div");
|