@ugfoundation/swaralipi-js 0.7.0 → 0.7.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/README.md +22 -3
- package/dist/{batch-UG26T3IE.js → batch-6AINAZJS.js} +4 -4
- package/dist/{batch-UG26T3IE.js.map → batch-6AINAZJS.js.map} +1 -1
- package/dist/{chunk-KMIW7ZBA.js → chunk-7QBLGKJC.js} +3 -3
- package/dist/{chunk-KMIW7ZBA.js.map → chunk-7QBLGKJC.js.map} +1 -1
- package/dist/{chunk-NFKKXN7S.js → chunk-ZOCFJL5A.js} +3 -3
- package/dist/{chunk-NFKKXN7S.js.map → chunk-ZOCFJL5A.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 +46 -11
- package/dist/viewer/index.cjs.map +1 -1
- package/dist/viewer/index.d.cts +32 -11
- package/dist/viewer/index.d.ts +32 -11
- package/dist/viewer/index.js +45 -10
- package/dist/viewer/index.js.map +1 -1
- package/package.json +1 -1
package/dist/viewer/index.d.cts
CHANGED
|
@@ -184,22 +184,31 @@ 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.
|
|
191
201
|
*
|
|
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
202
|
* `zoom` (default 1) multiplies the fit scale so callers can zoom in past
|
|
196
|
-
* fit-to-width
|
|
197
|
-
* photo viewer.
|
|
203
|
+
* fit-to-width, or below the readability floor deliberately; past that point
|
|
204
|
+
* `.sw-scroll` panning is expected, same as a photo viewer. `minScale` is a
|
|
205
|
+
* second, relative floor used by print, where paper cannot scroll.
|
|
198
206
|
*
|
|
199
207
|
* Self-contained on purpose — print.ts serialises this function into the
|
|
200
|
-
* print page, so it must not close over anything or import anything
|
|
208
|
+
* print page, so it must not close over anything or import anything (the
|
|
209
|
+
* defaults below are literals for the same reason).
|
|
201
210
|
*/
|
|
202
|
-
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number): void;
|
|
211
|
+
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number, minSpacing?: number, minSize?: number): void;
|
|
203
212
|
/** Zoom bounds/step for zoomIn()/zoomOut()/the `zoom` property — exported so
|
|
204
213
|
* a consumer's own zoom UI (e.g. a slider) can match the element's clamp. */
|
|
205
214
|
declare const MIN_ZOOM = 0.5;
|
|
@@ -215,6 +224,11 @@ declare const ZOOM_STEP = 1.2;
|
|
|
215
224
|
* --sw-font font stack (default: Noto Sans Bengali + system Bengali)
|
|
216
225
|
* --sw-size base font size
|
|
217
226
|
* --sw-cell-gap horizontal gap between source cells
|
|
227
|
+
* --sw-tight 0–1 multiplier on the column spacing (gap + matra floor);
|
|
228
|
+
* set by fitSwaralipi to compress before shrinking type
|
|
229
|
+
* --sw-matra minimum width of one matra column
|
|
230
|
+
* --sw-header-min floor for the নাম/তাল/আবর্তন header (it must stay legible
|
|
231
|
+
* when the notation is scaled down to fit a phone)
|
|
218
232
|
* --sw-hl player-highlight background (P2.3)
|
|
219
233
|
* --sw-rule header rule / muted line color
|
|
220
234
|
*
|
|
@@ -492,6 +506,13 @@ interface SwaralipiSheetElement extends HTMLElement {
|
|
|
492
506
|
staffOptions: StaffOptions;
|
|
493
507
|
/** Re-fit the notation to the element's current width. */
|
|
494
508
|
fit(): void;
|
|
509
|
+
/** How far the column spacing may be compressed to fit a narrow container
|
|
510
|
+
* before the type is scaled down at all, 0–1 (attribute `min-spacing`;
|
|
511
|
+
* undefined = the library default). Lower = tighter columns, bigger glyphs. */
|
|
512
|
+
minSpacing: number | undefined;
|
|
513
|
+
/** Smallest notation size in px the fit may produce (attribute `min-size`);
|
|
514
|
+
* past it the sheet scrolls horizontally instead of shrinking further. */
|
|
515
|
+
minSize: number | undefined;
|
|
495
516
|
/** Zoom factor on top of fit-to-width (1 = fit; clamped to
|
|
496
517
|
* [MIN_ZOOM, MAX_ZOOM]). Assigning re-fits immediately. Resets to 1 on the
|
|
497
518
|
* next doc/lang re-render — a resize alone (fit()) does not reset it. */
|
package/dist/viewer/index.d.ts
CHANGED
|
@@ -184,22 +184,31 @@ 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.
|
|
191
201
|
*
|
|
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
202
|
* `zoom` (default 1) multiplies the fit scale so callers can zoom in past
|
|
196
|
-
* fit-to-width
|
|
197
|
-
* photo viewer.
|
|
203
|
+
* fit-to-width, or below the readability floor deliberately; past that point
|
|
204
|
+
* `.sw-scroll` panning is expected, same as a photo viewer. `minScale` is a
|
|
205
|
+
* second, relative floor used by print, where paper cannot scroll.
|
|
198
206
|
*
|
|
199
207
|
* Self-contained on purpose — print.ts serialises this function into the
|
|
200
|
-
* print page, so it must not close over anything or import anything
|
|
208
|
+
* print page, so it must not close over anything or import anything (the
|
|
209
|
+
* defaults below are literals for the same reason).
|
|
201
210
|
*/
|
|
202
|
-
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number): void;
|
|
211
|
+
declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number, minSpacing?: number, minSize?: number): void;
|
|
203
212
|
/** Zoom bounds/step for zoomIn()/zoomOut()/the `zoom` property — exported so
|
|
204
213
|
* a consumer's own zoom UI (e.g. a slider) can match the element's clamp. */
|
|
205
214
|
declare const MIN_ZOOM = 0.5;
|
|
@@ -215,6 +224,11 @@ declare const ZOOM_STEP = 1.2;
|
|
|
215
224
|
* --sw-font font stack (default: Noto Sans Bengali + system Bengali)
|
|
216
225
|
* --sw-size base font size
|
|
217
226
|
* --sw-cell-gap horizontal gap between source cells
|
|
227
|
+
* --sw-tight 0–1 multiplier on the column spacing (gap + matra floor);
|
|
228
|
+
* set by fitSwaralipi to compress before shrinking type
|
|
229
|
+
* --sw-matra minimum width of one matra column
|
|
230
|
+
* --sw-header-min floor for the নাম/তাল/আবর্তন header (it must stay legible
|
|
231
|
+
* when the notation is scaled down to fit a phone)
|
|
218
232
|
* --sw-hl player-highlight background (P2.3)
|
|
219
233
|
* --sw-rule header rule / muted line color
|
|
220
234
|
*
|
|
@@ -492,6 +506,13 @@ interface SwaralipiSheetElement extends HTMLElement {
|
|
|
492
506
|
staffOptions: StaffOptions;
|
|
493
507
|
/** Re-fit the notation to the element's current width. */
|
|
494
508
|
fit(): void;
|
|
509
|
+
/** How far the column spacing may be compressed to fit a narrow container
|
|
510
|
+
* before the type is scaled down at all, 0–1 (attribute `min-spacing`;
|
|
511
|
+
* undefined = the library default). Lower = tighter columns, bigger glyphs. */
|
|
512
|
+
minSpacing: number | undefined;
|
|
513
|
+
/** Smallest notation size in px the fit may produce (attribute `min-size`);
|
|
514
|
+
* past it the sheet scrolls horizontally instead of shrinking further. */
|
|
515
|
+
minSize: number | undefined;
|
|
495
516
|
/** Zoom factor on top of fit-to-width (1 = fit; clamped to
|
|
496
517
|
* [MIN_ZOOM, MAX_ZOOM]). Assigning re-fits immediately. Resets to 1 on the
|
|
497
518
|
* 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,27 @@ 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
|
-
const
|
|
495
|
+
for (const step of [0.75, 0.5, 0.25, 0]) {
|
|
496
|
+
if (natural <= available || minSpacing >= 1) break;
|
|
497
|
+
sheet.style.setProperty("--sw-tight", String(minSpacing + (1 - minSpacing) * step));
|
|
498
|
+
natural = block.scrollWidth;
|
|
499
|
+
}
|
|
500
|
+
const base = parseFloat(getComputedStyle(sheet).fontSize);
|
|
501
|
+
let fit = natural > available ? Math.max(minScale, available / natural) : 1;
|
|
502
|
+
if (base > 0 && minSize > 0) fit = Math.max(fit, Math.min(1, minSize / base));
|
|
495
503
|
const scale = fit * zoom;
|
|
496
504
|
if (scale === 1) continue;
|
|
497
|
-
const base = parseFloat(getComputedStyle(sheet).fontSize);
|
|
498
505
|
sheet.style.setProperty("--sw-size", `${(base * scale).toFixed(3)}px`);
|
|
499
506
|
}
|
|
500
507
|
}
|
|
@@ -531,7 +538,10 @@ ${FONT_FACES}
|
|
|
531
538
|
margin: 0 0 0.75em;
|
|
532
539
|
padding: 0 0 0.5em;
|
|
533
540
|
border-bottom: 1px solid var(--sw-rule, rgba(128, 128, 128, 0.35));
|
|
534
|
-
|
|
541
|
+
/* Scales with the sheet, but never below the floor: fitSwaralipi shrinks
|
|
542
|
+
.sw-sheet's font-size to fit the notation, and the metadata is prose \u2014
|
|
543
|
+
it has no columns to align and must stay readable on a phone. */
|
|
544
|
+
font-size: max(0.95em, var(--sw-header-min, 0.95rem));
|
|
535
545
|
}
|
|
536
546
|
.sw-meta-row { display: flex; gap: 0.3em; }
|
|
537
547
|
.sw-meta-label { font-weight: 600; min-width: 4.5em; }
|
|
@@ -547,7 +557,7 @@ ${FONT_FACES}
|
|
|
547
557
|
.sw-scroll { overflow-x: auto; }
|
|
548
558
|
.sw-block {
|
|
549
559
|
display: grid;
|
|
550
|
-
column-gap: var(--sw-cell-gap, 0.4em);
|
|
560
|
+
column-gap: calc(var(--sw-cell-gap, 0.4em) * var(--sw-tight, 1));
|
|
551
561
|
align-items: end;
|
|
552
562
|
width: max-content;
|
|
553
563
|
}
|
|
@@ -1030,7 +1040,7 @@ body { width: 178mm; color: #111; background: #fff; -webkit-print-color-adjust:
|
|
|
1030
1040
|
</style>
|
|
1031
1041
|
</head>
|
|
1032
1042
|
<body>${top}${bodyHtml}${bottom}
|
|
1033
|
-
<script>window.__swFit=function(){(${fitSwaralipi.toString()})(document,0.45)};window.__swFit()</script>
|
|
1043
|
+
<script>window.__swFit=function(){(${fitSwaralipi.toString()})(document,0.45,1,undefined,0)};window.__swFit()</script>
|
|
1034
1044
|
</body>
|
|
1035
1045
|
</html>`;
|
|
1036
1046
|
}
|
|
@@ -1121,7 +1131,7 @@ function ensureNotationFonts() {
|
|
|
1121
1131
|
var sharedSheet;
|
|
1122
1132
|
function createElementClass() {
|
|
1123
1133
|
return class SwaralipiSheet extends HTMLElement {
|
|
1124
|
-
static observedAttributes = ["src", "lang", "hide-header"];
|
|
1134
|
+
static observedAttributes = ["src", "lang", "hide-header", "min-spacing", "min-size"];
|
|
1125
1135
|
#doc;
|
|
1126
1136
|
#root;
|
|
1127
1137
|
#adopted = false;
|
|
@@ -1176,6 +1186,10 @@ function createElementClass() {
|
|
|
1176
1186
|
if (newValue !== null) void this.#load(newValue);
|
|
1177
1187
|
return;
|
|
1178
1188
|
}
|
|
1189
|
+
if (name === "min-spacing" || name === "min-size") {
|
|
1190
|
+
this.fit();
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1179
1193
|
if (name === "lang") this.#ensureTransliterator();
|
|
1180
1194
|
this.#render();
|
|
1181
1195
|
}
|
|
@@ -1199,7 +1213,28 @@ function createElementClass() {
|
|
|
1199
1213
|
}
|
|
1200
1214
|
/** Scale the notation to fit the available width, times the zoom factor. */
|
|
1201
1215
|
#fit() {
|
|
1202
|
-
fitSwaralipi(this.#root, 0, this.#zoom);
|
|
1216
|
+
fitSwaralipi(this.#root, 0, this.#zoom, this.minSpacing, this.minSize);
|
|
1217
|
+
}
|
|
1218
|
+
/** Numeric attribute, or undefined for fitSwaralipi's own default. */
|
|
1219
|
+
#attrNum(name) {
|
|
1220
|
+
const value = parseFloat(this.getAttribute(name) ?? "");
|
|
1221
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1222
|
+
}
|
|
1223
|
+
#setAttrNum(name, value) {
|
|
1224
|
+
if (value === void 0) this.removeAttribute(name);
|
|
1225
|
+
else this.setAttribute(name, String(value));
|
|
1226
|
+
}
|
|
1227
|
+
get minSpacing() {
|
|
1228
|
+
return this.#attrNum("min-spacing");
|
|
1229
|
+
}
|
|
1230
|
+
set minSpacing(value) {
|
|
1231
|
+
this.#setAttrNum("min-spacing", value);
|
|
1232
|
+
}
|
|
1233
|
+
get minSize() {
|
|
1234
|
+
return this.#attrNum("min-size");
|
|
1235
|
+
}
|
|
1236
|
+
set minSize(value) {
|
|
1237
|
+
this.#setAttrNum("min-size", value);
|
|
1203
1238
|
}
|
|
1204
1239
|
/** Re-fit the current render (public for hosts that resize the sheet
|
|
1205
1240
|
* themselves, e.g. a tab that was hidden while the document loaded). */
|