@hanology/cham-browser 0.2.0 → 0.2.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 +81 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/template/src/components/AnnotationTooltip.vue +10 -9
- package/template/src/components/VerticalScroll.vue +4 -0
- package/template/src/composables/useAnnotationRenderer.ts +14 -2
- package/template/src/views/PieceView.vue +51 -41
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @hanology/cham-browser
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@hanology/cham-browser)
|
|
4
|
+
|
|
5
|
+
Site generator for [CHAM (Classical Han with Annotations Markup)](https://github.com/hanologyorg/cham-format) — generates a complete static website from CHAM content.
|
|
6
|
+
|
|
7
|
+
Includes parser, serializer, transformation pipeline, Vue 3 frontend template, and CLI.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @hanology/cham-browser
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## CLI
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Generate a static site from CHAM content
|
|
19
|
+
npx cham-browser --config config.yaml
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### config.yaml
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
# Branding
|
|
26
|
+
name: 漢流
|
|
27
|
+
nameEn: Hanology
|
|
28
|
+
subtitle: 古典詩文圖書館
|
|
29
|
+
|
|
30
|
+
# Content paths (relative to config.yaml)
|
|
31
|
+
libraryDir: library/content
|
|
32
|
+
authorsFile: library/data/authors.yaml
|
|
33
|
+
|
|
34
|
+
# Build options
|
|
35
|
+
outputDir: dist
|
|
36
|
+
pretty: true
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
### Parser & Serializer (browser-compatible)
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { parse, serialize } from '@hanology/cham-browser'
|
|
45
|
+
|
|
46
|
+
const doc = parse(chamSource)
|
|
47
|
+
const output = serialize(doc)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Pipeline (pure functions, no Node.js fs)
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import {
|
|
54
|
+
buildPieceFromCham,
|
|
55
|
+
buildBookData,
|
|
56
|
+
buildLibraryIndex,
|
|
57
|
+
buildAuthorsJson,
|
|
58
|
+
buildDynastiesJson,
|
|
59
|
+
} from '@hanology/cham-browser'
|
|
60
|
+
|
|
61
|
+
const piece = buildPieceFromCham(
|
|
62
|
+
chamSource, bookConfig, authors, bookId,
|
|
63
|
+
proseFiles, layerFiles,
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Architecture
|
|
68
|
+
|
|
69
|
+
| Layer | Description |
|
|
70
|
+
|-------|-------------|
|
|
71
|
+
| `pipeline.ts` | Pure transformation functions (CHAM → JSON) |
|
|
72
|
+
| `cli.ts` | I/O adapter: reads files, calls pipeline, runs vite-ssg |
|
|
73
|
+
| `template/` | Vue 3 + vite-ssg frontend (components, views, styles) |
|
|
74
|
+
|
|
75
|
+
## Requirements
|
|
76
|
+
|
|
77
|
+
Node.js 20+
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAA;AAC9F,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -27,17 +27,22 @@ function layerLabel(ann: Annotation): string {
|
|
|
27
27
|
}
|
|
28
28
|
return ''
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
function onBackdropTouchMove() {
|
|
32
|
+
emit('close')
|
|
33
|
+
}
|
|
30
34
|
</script>
|
|
31
35
|
|
|
32
36
|
<template>
|
|
33
37
|
<Teleport to="body">
|
|
34
38
|
<Transition name="ann-fade">
|
|
35
|
-
<div v-if="visible && annotations.length" class="ann-backdrop" @click="emit('close')">
|
|
39
|
+
<div v-if="visible && annotations.length" class="ann-backdrop" @click="emit('close')" @touchmove="onBackdropTouchMove">
|
|
36
40
|
<div
|
|
37
41
|
class="ann-tooltip"
|
|
38
42
|
:class="{ 'ann-vertical': layout === 'vertical', 'ann-mobile-bottom': isMobile }"
|
|
39
43
|
:style="style"
|
|
40
44
|
@click.stop
|
|
45
|
+
@touchmove.stop
|
|
41
46
|
>
|
|
42
47
|
<button v-if="isMobile" class="ann-handle" @click="emit('close')">
|
|
43
48
|
<span class="ann-handle-bar" />
|
|
@@ -48,12 +53,10 @@ function layerLabel(ann: Annotation): string {
|
|
|
48
53
|
class="ann-entry"
|
|
49
54
|
:class="ann.kind"
|
|
50
55
|
>
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
<span v-if="layerLabel(ann)" class="ann-layer">{{ layerLabel(ann) }}</span>
|
|
54
|
-
</div>
|
|
56
|
+
<span class="ann-kind">{{ ann.kind === 'pronunciation' ? '音' : '義' }}</span>
|
|
57
|
+
<span v-if="layerLabel(ann)" class="ann-layer">{{ layerLabel(ann) }}</span>
|
|
55
58
|
<PronunciationGroup v-if="getSegment(ann)" :segment="getSegment(ann)!" />
|
|
56
|
-
<
|
|
59
|
+
<span v-else class="ann-body">{{ ann.text }}</span>
|
|
57
60
|
</div>
|
|
58
61
|
</div>
|
|
59
62
|
</div>
|
|
@@ -135,7 +138,6 @@ function layerLabel(ann: Annotation): string {
|
|
|
135
138
|
display: inline-flex;
|
|
136
139
|
align-items: center;
|
|
137
140
|
gap: 6px;
|
|
138
|
-
margin-bottom: 2px;
|
|
139
141
|
}
|
|
140
142
|
.ann-layer {
|
|
141
143
|
font-size: 11px;
|
|
@@ -153,7 +155,6 @@ function layerLabel(ann: Annotation): string {
|
|
|
153
155
|
}
|
|
154
156
|
|
|
155
157
|
.ann-body {
|
|
156
|
-
margin-top: 4px;
|
|
157
158
|
line-height: 1.8;
|
|
158
159
|
}
|
|
159
160
|
|
|
@@ -168,6 +169,7 @@ function layerLabel(ann: Annotation): string {
|
|
|
168
169
|
.ann-vertical .ann-entry {
|
|
169
170
|
margin-bottom: 0;
|
|
170
171
|
margin-left: 12px;
|
|
172
|
+
display: inline;
|
|
171
173
|
}
|
|
172
174
|
.ann-vertical .ann-kind {
|
|
173
175
|
margin-right: 0;
|
|
@@ -175,7 +177,6 @@ function layerLabel(ann: Annotation): string {
|
|
|
175
177
|
vertical-align: baseline;
|
|
176
178
|
}
|
|
177
179
|
.ann-vertical .ann-body {
|
|
178
|
-
margin-top: 0;
|
|
179
180
|
margin-left: 6px;
|
|
180
181
|
}
|
|
181
182
|
|
|
@@ -56,7 +56,8 @@ export function renderAnnotatedText(text: string, spans: AnnSpan[], useRuby = fa
|
|
|
56
56
|
const numText = toChineseNumber(annCounter)
|
|
57
57
|
const body = esc(text.slice(span.start, span.end))
|
|
58
58
|
if (useRuby) {
|
|
59
|
-
|
|
59
|
+
const rtCls = numText.length > 1 ? 'ann-num ann-num-long' : 'ann-num'
|
|
60
|
+
html += `<ruby class="ann-target ${kinds}" data-ann-ids="${ids}">${body}<rp></rp><rt class="${rtCls}">${numText}</rt><rp></rp></ruby>`
|
|
60
61
|
} else {
|
|
61
62
|
html += `<span class="ann-target ${kinds}" data-ann-ids="${ids}">${body}<sup class="ann-num">${numText}</sup></span>`
|
|
62
63
|
}
|
|
@@ -151,7 +152,18 @@ export function useAnnotationTooltip() {
|
|
|
151
152
|
|
|
152
153
|
function hide() { visible.value = false }
|
|
153
154
|
function toggle(event: MouseEvent, annotations: Annotation[]) {
|
|
154
|
-
if (visible.value) {
|
|
155
|
+
if (visible.value) {
|
|
156
|
+
const currentIds = items.value.map(a => a.id).sort().join(',')
|
|
157
|
+
const newIds = annotations.map(a => a.id).sort().join(',')
|
|
158
|
+
if (currentIds === newIds) {
|
|
159
|
+
// Same annotation: dismiss on mobile only (desktop uses hover to manage)
|
|
160
|
+
if (window.innerWidth < 768) hide()
|
|
161
|
+
} else {
|
|
162
|
+
show(event, annotations)
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
show(event, annotations)
|
|
166
|
+
}
|
|
155
167
|
}
|
|
156
168
|
|
|
157
169
|
return { visible, items, style, show, hide, toggle }
|
|
@@ -259,32 +259,33 @@ function tcy(n: number): string {
|
|
|
259
259
|
/>
|
|
260
260
|
</section>
|
|
261
261
|
|
|
262
|
-
<
|
|
263
|
-
num=""
|
|
264
|
-
label="注釋"
|
|
265
|
-
:special="false"
|
|
266
|
-
:text="piece.sections.annotations || ''"
|
|
267
|
-
:is-annotations="true"
|
|
268
|
-
:vertical="true"
|
|
269
|
-
class="v-section"
|
|
270
|
-
/>
|
|
271
|
-
|
|
272
|
-
<div v-if="hasLayers" class="v-layers-section">
|
|
273
|
-
<AnnotationLayerSelector
|
|
274
|
-
:layers="annotationLayers"
|
|
275
|
-
v-model:activeIds="activeLayerIds"
|
|
276
|
-
/>
|
|
262
|
+
<div class="v-section">
|
|
277
263
|
<SectionBlock
|
|
278
|
-
v-for="block in layerAnnotationBlocks"
|
|
279
|
-
:key="block.label"
|
|
280
264
|
num=""
|
|
281
|
-
|
|
265
|
+
label="注釋"
|
|
282
266
|
:special="false"
|
|
283
|
-
:text="
|
|
267
|
+
:text="piece.sections.annotations || ''"
|
|
284
268
|
:is-annotations="true"
|
|
285
269
|
:vertical="true"
|
|
286
|
-
class="v-section"
|
|
287
270
|
/>
|
|
271
|
+
<template v-if="hasLayers">
|
|
272
|
+
<div class="v-layers-inline">
|
|
273
|
+
<AnnotationLayerSelector
|
|
274
|
+
:layers="annotationLayers"
|
|
275
|
+
v-model:activeIds="activeLayerIds"
|
|
276
|
+
/>
|
|
277
|
+
</div>
|
|
278
|
+
<SectionBlock
|
|
279
|
+
v-for="block in layerAnnotationBlocks"
|
|
280
|
+
:key="block.label"
|
|
281
|
+
num=""
|
|
282
|
+
:label="block.label"
|
|
283
|
+
:special="false"
|
|
284
|
+
:text="block.text"
|
|
285
|
+
:is-annotations="true"
|
|
286
|
+
:vertical="true"
|
|
287
|
+
/>
|
|
288
|
+
</template>
|
|
288
289
|
</div>
|
|
289
290
|
|
|
290
291
|
<SectionBlock
|
|
@@ -382,20 +383,32 @@ function tcy(n: number): string {
|
|
|
382
383
|
</div>
|
|
383
384
|
|
|
384
385
|
<div class="h-sections">
|
|
385
|
-
<div v-if="hasLayers" class="h-
|
|
386
|
-
<AnnotationLayerSelector
|
|
387
|
-
:layers="annotationLayers"
|
|
388
|
-
v-model:activeIds="activeLayerIds"
|
|
389
|
-
/>
|
|
386
|
+
<div v-if="piece.sections.annotations || hasLayers" class="h-ann-section">
|
|
390
387
|
<SectionBlock
|
|
391
|
-
v-
|
|
392
|
-
:key="block.label"
|
|
388
|
+
v-if="piece.sections.annotations"
|
|
393
389
|
num=""
|
|
394
|
-
|
|
390
|
+
label="注釋"
|
|
395
391
|
:special="false"
|
|
396
|
-
:text="
|
|
392
|
+
:text="piece.sections.annotations"
|
|
397
393
|
:is-annotations="true"
|
|
398
394
|
/>
|
|
395
|
+
<template v-if="hasLayers">
|
|
396
|
+
<div class="h-layers-inline">
|
|
397
|
+
<AnnotationLayerSelector
|
|
398
|
+
:layers="annotationLayers"
|
|
399
|
+
v-model:activeIds="activeLayerIds"
|
|
400
|
+
/>
|
|
401
|
+
</div>
|
|
402
|
+
<SectionBlock
|
|
403
|
+
v-for="block in layerAnnotationBlocks"
|
|
404
|
+
:key="block.label"
|
|
405
|
+
num=""
|
|
406
|
+
:label="block.label"
|
|
407
|
+
:special="false"
|
|
408
|
+
:text="block.text"
|
|
409
|
+
:is-annotations="true"
|
|
410
|
+
/>
|
|
411
|
+
</template>
|
|
399
412
|
</div>
|
|
400
413
|
|
|
401
414
|
<SectionBlock
|
|
@@ -532,15 +545,11 @@ function tcy(n: number): string {
|
|
|
532
545
|
flex-shrink: 0;
|
|
533
546
|
}
|
|
534
547
|
|
|
535
|
-
.v-layers-
|
|
536
|
-
flex-shrink: 0;
|
|
548
|
+
.v-layers-inline {
|
|
537
549
|
writing-mode: vertical-rl;
|
|
538
550
|
text-orientation: mixed;
|
|
539
|
-
padding: 0
|
|
540
|
-
|
|
541
|
-
flex-direction: column;
|
|
542
|
-
gap: 8px;
|
|
543
|
-
align-items: flex-start;
|
|
551
|
+
padding: 12px 0 4px;
|
|
552
|
+
border-top: 1px solid var(--border-light);
|
|
544
553
|
}
|
|
545
554
|
|
|
546
555
|
.v-source-link {
|
|
@@ -649,12 +658,13 @@ function tcy(n: number): string {
|
|
|
649
658
|
margin: 0 auto; padding-bottom: 80px;
|
|
650
659
|
}
|
|
651
660
|
|
|
652
|
-
.h-
|
|
661
|
+
.h-ann-section {
|
|
653
662
|
margin-bottom: 16px;
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.h-layers-inline {
|
|
666
|
+
padding: 12px 0;
|
|
667
|
+
margin-bottom: 8px;
|
|
658
668
|
}
|
|
659
669
|
|
|
660
670
|
.h-source-link {
|