orz-markdown 1.4.0 → 1.5.0
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 +31 -0
- package/dist/doc-meta.d.ts +3 -3
- package/dist/doc-meta.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/prepare-sources.d.ts +34 -5
- package/dist/prepare-sources.d.ts.map +1 -1
- package/dist/prepare-sources.js +80 -22
- package/dist/prepare-sources.js.map +1 -1
- package/orz-markdown-skills/SKILL.md +22 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -71,6 +71,37 @@ You can also convert a node programmatically:
|
|
|
71
71
|
const markdown = window.OrzMarkdownRuntime.elementToMarkdown(someElement);
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
## Portable Document Metadata
|
|
75
|
+
|
|
76
|
+
The editable document builders share one metadata model from
|
|
77
|
+
`orz-markdown/doc-meta`. An mdhtml or paged source can declare metadata in a
|
|
78
|
+
leading block that is consumed during generation:
|
|
79
|
+
|
|
80
|
+
```markdown
|
|
81
|
+
{{nyml
|
|
82
|
+
kind: meta
|
|
83
|
+
title: Field Notes
|
|
84
|
+
author: Your Name
|
|
85
|
+
description: Notes from the field course
|
|
86
|
+
license: CC-BY-4.0
|
|
87
|
+
license_name: Creative Commons Attribution 4.0
|
|
88
|
+
license_url: https://creativecommons.org/licenses/by/4.0/
|
|
89
|
+
source: https://example.org/field-notes
|
|
90
|
+
date: 2026-07-10
|
|
91
|
+
keywords: notes, fieldwork, markdown
|
|
92
|
+
}}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The generated file stores normalized metadata in standard `<head>` tags and an
|
|
96
|
+
`#orz-meta` JSON island. Those records survive in-browser edits and framework
|
|
97
|
+
updates. Host applications can instead pass a `DocMeta` object to the family
|
|
98
|
+
builders; host values win field by field. Slides seed `title` and `author` from
|
|
99
|
+
their native deck config and accept the same programmatic override.
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
import { extractDocMeta, parseDocMetaIsland } from 'orz-markdown/doc-meta';
|
|
103
|
+
```
|
|
104
|
+
|
|
74
105
|
## Themes
|
|
75
106
|
|
|
76
107
|
We provide multiple ready-to-use CSS themes for rendering the output! You do not need to style the custom plugins from scratch.
|
package/dist/doc-meta.d.ts
CHANGED
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Two channels, one precedence rule:
|
|
15
15
|
*
|
|
16
|
-
* 1. **In the source** — a `{{nyml kind: meta … }}` block
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* 1. **In the source** — a `{{nyml kind: meta … }}` block that a lone author
|
|
17
|
+
* can type. The builder consumes and removes it, then emits the normalized
|
|
18
|
+
* metadata into the generated document's `<head>`.
|
|
19
19
|
* 2. **Injected by a host** — the `metadata` build option.
|
|
20
20
|
*
|
|
21
21
|
* The **host wins, field by field**: a platform that knows the license
|
package/dist/doc-meta.js
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Two channels, one precedence rule:
|
|
16
16
|
*
|
|
17
|
-
* 1. **In the source** — a `{{nyml kind: meta … }}` block
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* 1. **In the source** — a `{{nyml kind: meta … }}` block that a lone author
|
|
18
|
+
* can type. The builder consumes and removes it, then emits the normalized
|
|
19
|
+
* metadata into the generated document's `<head>`.
|
|
20
20
|
* 2. **Injected by a host** — the `metadata` build option.
|
|
21
21
|
*
|
|
22
22
|
* The **host wins, field by field**: a platform that knows the license
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import './plugins/nyml.js';
|
|
|
13
13
|
export { register } from './registry.js';
|
|
14
14
|
export type { PluginDefinition } from './registry.js';
|
|
15
15
|
export { prepareSources } from './prepare-sources.js';
|
|
16
|
+
export type { PrepareSourcesOptions } from './prepare-sources.js';
|
|
16
17
|
declare const md: MarkdownIt;
|
|
17
18
|
export default md;
|
|
18
19
|
export { md };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,UAAU,MAAM,aAAa,CAAC;AAkBrC,OAAO,mBAAmB,CAAC;AAC3B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,sBAAsB,CAAC;AAC9B,OAAO,sBAAsB,CAAC;AAC9B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,mBAAmB,CAAC;AAC3B,OAAO,mBAAmB,CAAC;AAE3B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,UAAU,MAAM,aAAa,CAAC;AAkBrC,OAAO,mBAAmB,CAAC;AAC3B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,sBAAsB,CAAC;AAC9B,OAAO,sBAAsB,CAAC;AAC9B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,mBAAmB,CAAC;AAC3B,OAAO,mBAAmB,CAAC;AAE3B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,QAAA,MAAM,EAAE,YAMN,CAAC;AAsIH,eAAe,EAAE,CAAC;AAClB,OAAO,EAAE,EAAE,EAAE,CAAC;AAId,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,gCAA8B;AAC9B,8DAAqC;AACrC,4EAAwC;AACxC,kFAA8C;AAC9C,gFAA4C;AAC5C,4EAAwC;AACxC,wEAAoC;AACpC,sEAAkC;AAClC,sEAAkC;AAClC,sEAAkC;AAClC,oFAA+C;AAC/C,sFAAwD;AACxD,qEAA8D;AAC9D,uEAAgE;AAChE,+CAA8C;AAC9C,+CAAiD;AACjD,6CAA+C;AAC/C,iDAAmD;AACnD,uEAAwE;AACxE,6BAA2B;AAC3B,8BAA4B;AAC5B,8BAA4B;AAC5B,gCAA8B;AAC9B,gCAA8B;AAC9B,+BAA6B;AAC7B,8BAA4B;AAC5B,+BAA6B;AAC7B,6BAA2B;AAC3B,6BAA2B;AAE3B,6CAAyC;AAAhC,uGAAA,QAAQ,OAAA;AAEjB,2DAAsD;AAA7C,oHAAA,cAAc,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pre-processes a markdown source string by
|
|
2
|
+
* Pre-processes a markdown source string by resolving URL-based markdown
|
|
3
|
+
* includes BEFORE rendering. markdown-it rendering is synchronous, so a URL
|
|
4
|
+
* fetch cannot happen inside a render rule; this async pre-pass inlines the
|
|
5
|
+
* referenced markdown up front, and the result renders normally.
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
* fetches each URL, and replaces the directive with the fetched markdown content.
|
|
7
|
+
* Directive syntax (anywhere in the source):
|
|
6
8
|
*
|
|
7
|
-
*
|
|
9
|
+
* {{markdown https://host/path.md}}
|
|
10
|
+
* {{md-include https://host/path.md}}
|
|
11
|
+
*
|
|
12
|
+
* Each directive is replaced by the fetched markdown (which may itself contain
|
|
13
|
+
* includes — resolved recursively up to `maxDepth`, with an ancestor-chain
|
|
14
|
+
* cycle guard). A directive whose fetch fails or whose host is not allowed is
|
|
15
|
+
* LEFT IN PLACE (unresolved, never a hard error).
|
|
16
|
+
*
|
|
17
|
+
* The network transport is INJECTABLE (`opts.fetcher`) and can be restricted to
|
|
18
|
+
* an allowlist of hosts (`opts.allowedHosts`) — important when resolving
|
|
19
|
+
* host-authored content server-side, where an unrestricted fetch is an SSRF
|
|
20
|
+
* vector. With no options it behaves as before: the global `fetch`, any host.
|
|
8
21
|
*/
|
|
9
|
-
export
|
|
22
|
+
export interface PrepareSourcesOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Fetch a URL's markdown text. Injectable so a host controls transport and
|
|
25
|
+
* auth; defaults to the global `fetch`. Return `null` to leave the directive
|
|
26
|
+
* unresolved (e.g. a non-200, or a URL the host declines).
|
|
27
|
+
*/
|
|
28
|
+
fetcher?: (url: string) => Promise<string | null>;
|
|
29
|
+
/**
|
|
30
|
+
* If non-empty, ONLY URLs whose host is in this list are fetched; any other
|
|
31
|
+
* directive is left in place. Case-insensitive exact host match (host =
|
|
32
|
+
* `example.com` or `example.com:8443`). The SSRF guard for server-side use.
|
|
33
|
+
*/
|
|
34
|
+
allowedHosts?: string[];
|
|
35
|
+
/** Max recursion depth for includes that themselves include (default 3). */
|
|
36
|
+
maxDepth?: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function prepareSources(src: string, opts?: PrepareSourcesOptions): Promise<string>;
|
|
10
39
|
//# sourceMappingURL=prepare-sources.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-sources.d.ts","sourceRoot":"","sources":["../src/prepare-sources.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prepare-sources.d.ts","sourceRoot":"","sources":["../src/prepare-sources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAClD;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAyBD,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC,MAAM,CAAC,CA0CjB"}
|
package/dist/prepare-sources.js
CHANGED
|
@@ -1,31 +1,89 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.prepareSources = prepareSources;
|
|
4
2
|
/**
|
|
5
|
-
* Pre-processes a markdown source string by
|
|
3
|
+
* Pre-processes a markdown source string by resolving URL-based markdown
|
|
4
|
+
* includes BEFORE rendering. markdown-it rendering is synchronous, so a URL
|
|
5
|
+
* fetch cannot happen inside a render rule; this async pre-pass inlines the
|
|
6
|
+
* referenced markdown up front, and the result renders normally.
|
|
7
|
+
*
|
|
8
|
+
* Directive syntax (anywhere in the source):
|
|
9
|
+
*
|
|
10
|
+
* {{markdown https://host/path.md}}
|
|
11
|
+
* {{md-include https://host/path.md}}
|
|
6
12
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
13
|
+
* Each directive is replaced by the fetched markdown (which may itself contain
|
|
14
|
+
* includes — resolved recursively up to `maxDepth`, with an ancestor-chain
|
|
15
|
+
* cycle guard). A directive whose fetch fails or whose host is not allowed is
|
|
16
|
+
* LEFT IN PLACE (unresolved, never a hard error).
|
|
9
17
|
*
|
|
10
|
-
*
|
|
18
|
+
* The network transport is INJECTABLE (`opts.fetcher`) and can be restricted to
|
|
19
|
+
* an allowlist of hosts (`opts.allowedHosts`) — important when resolving
|
|
20
|
+
* host-authored content server-side, where an unrestricted fetch is an SSRF
|
|
21
|
+
* vector. With no options it behaves as before: the global `fetch`, any host.
|
|
11
22
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.prepareSources = prepareSources;
|
|
25
|
+
const DIRECTIVE = /\{\{(?:markdown|md-include)\s+(https?:\/\/[^\s}]+)\}\}/g;
|
|
26
|
+
async function defaultFetcher(url) {
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(url);
|
|
29
|
+
if (!res.ok)
|
|
30
|
+
return null;
|
|
31
|
+
return await res.text();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function hostAllowed(url, allowed) {
|
|
38
|
+
if (!allowed || allowed.length === 0)
|
|
39
|
+
return true;
|
|
40
|
+
let host;
|
|
41
|
+
try {
|
|
42
|
+
host = new URL(url).host.toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return allowed.some((a) => a.toLowerCase() === host);
|
|
48
|
+
}
|
|
49
|
+
async function prepareSources(src, opts = {}) {
|
|
50
|
+
const fetcher = opts.fetcher ?? defaultFetcher;
|
|
51
|
+
const maxDepth = opts.maxDepth ?? 3;
|
|
52
|
+
// Splice by match index (never String.replace, whose replacement string
|
|
53
|
+
// treats `$` specially — fetched markdown containing `$&`/`$1` would corrupt).
|
|
54
|
+
async function resolve(text, depth, ancestors) {
|
|
55
|
+
const matches = [...text.matchAll(DIRECTIVE)];
|
|
56
|
+
if (matches.length === 0)
|
|
57
|
+
return text;
|
|
58
|
+
let out = "";
|
|
59
|
+
let last = 0;
|
|
60
|
+
for (const m of matches) {
|
|
61
|
+
const full = m[0];
|
|
62
|
+
const url = m[1];
|
|
63
|
+
const idx = m.index ?? 0;
|
|
64
|
+
out += text.slice(last, idx);
|
|
65
|
+
last = idx + full.length;
|
|
66
|
+
if (!hostAllowed(url, opts.allowedHosts)) {
|
|
67
|
+
out += full; // not allowed → leave the directive untouched
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (ancestors.has(url)) {
|
|
71
|
+
// Cycle (this URL is already being included up the chain) → drop it.
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const fetched = await fetcher(url);
|
|
75
|
+
if (fetched == null) {
|
|
76
|
+
out += full; // fetch failed → leave in place, never throw
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
out +=
|
|
80
|
+
depth < maxDepth
|
|
81
|
+
? await resolve(fetched, depth + 1, new Set(ancestors).add(url))
|
|
82
|
+
: fetched;
|
|
27
83
|
}
|
|
84
|
+
out += text.slice(last);
|
|
85
|
+
return out;
|
|
28
86
|
}
|
|
29
|
-
return
|
|
87
|
+
return resolve(src, 0, new Set());
|
|
30
88
|
}
|
|
31
89
|
//# sourceMappingURL=prepare-sources.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-sources.js","sourceRoot":"","sources":["../src/prepare-sources.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"prepare-sources.js","sourceRoot":"","sources":["../src/prepare-sources.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,6 +32,13 @@ const resolved = await prepareSources(markdownSource);
|
|
|
32
32
|
const html = md.render(resolved, { markdownBasePath: '/local/base/path' });
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
`prepareSources(src, opts?)` (≥ 1.5.0) accepts options for safe server-side use:
|
|
36
|
+
`allowedHosts` (only resolve includes from these hosts — an SSRF guard when the
|
|
37
|
+
source is host-authored), `fetcher` (inject the transport; defaults to global
|
|
38
|
+
`fetch`), and `maxDepth` (recursion for nested includes, default 3). Nested
|
|
39
|
+
includes resolve with an ancestor-chain cycle guard. No options preserves the
|
|
40
|
+
prior behavior.
|
|
41
|
+
|
|
35
42
|
---
|
|
36
43
|
|
|
37
44
|
## HTML Page Requirements
|
|
@@ -74,6 +81,21 @@ The runtime also provides **copy-as-Markdown**: with it loaded, copying a select
|
|
|
74
81
|
|
|
75
82
|
> **Do not strip `data-md` attributes.** `mermaid`, `smiles`, `qrcode`, `youtube`, and `chart` output carry a `data-md` breadcrumb so copy recovers their source after client-side rendering (e.g. a copied QR yields `{{qr ...}}`, not its SVG). Preserve these attributes if you post-process the HTML.
|
|
76
83
|
|
|
84
|
+
### Portable document metadata
|
|
85
|
+
|
|
86
|
+
The self-contained family shares `DocMeta` from `orz-markdown/doc-meta`:
|
|
87
|
+
`title`, `author`, `description`, `license` (`spdx`, `name`, `url`), `source`,
|
|
88
|
+
`date`, and `keywords`. In mdhtml and paged source, authors may provide a
|
|
89
|
+
`{{nyml kind: meta ...}}` block. The builder consumes that block and emits
|
|
90
|
+
standard `<head>` metadata plus a machine-readable `#orz-meta` JSON island;
|
|
91
|
+
those emitted records survive later in-browser saves and framework updates.
|
|
92
|
+
Host-injected metadata wins field by field. Slides use deck `title:` and
|
|
93
|
+
`author:` as their source metadata and accept the same host override.
|
|
94
|
+
|
|
95
|
+
Use `extractDocMeta`, `mergeDocMeta`, `renderDocMetaHead`,
|
|
96
|
+
`renderDocMetaIsland`, and `parseDocMetaIsland` from
|
|
97
|
+
`orz-markdown/doc-meta`; do not create a second metadata grammar in a host app.
|
|
98
|
+
|
|
77
99
|
---
|
|
78
100
|
|
|
79
101
|
## Themes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orz-markdown",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Customized markdown-it parser with official and custom plugins",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
|
-
"url": "https://github.com/wangyu16/orz-markdown"
|
|
42
|
+
"url": "git+https://github.com/wangyu16/orz-markdown.git"
|
|
43
43
|
},
|
|
44
44
|
"homepage": "https://github.com/wangyu16/orz-markdown#readme",
|
|
45
45
|
"bugs": "https://github.com/wangyu16/orz-markdown/issues",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@traptitech/markdown-it-katex": "^3.6.0",
|
|
48
48
|
"katex": "^0.16.35",
|
|
49
|
-
"markdown-it": "^14.
|
|
49
|
+
"markdown-it": "^14.3.0",
|
|
50
50
|
"markdown-it-anchor": "^9.2.0",
|
|
51
51
|
"markdown-it-container": "^4.0.0",
|
|
52
52
|
"markdown-it-footnote": "^4.0.0",
|
|
@@ -66,11 +66,11 @@
|
|
|
66
66
|
"@types/markdown-it-footnote": "^3.0.4",
|
|
67
67
|
"@types/node": "^25.3.5",
|
|
68
68
|
"@types/qrcode-svg": "^1.1.5",
|
|
69
|
-
"esbuild": "^0.
|
|
70
|
-
"happy-dom": "^
|
|
69
|
+
"esbuild": "^0.28.1",
|
|
70
|
+
"happy-dom": "^20.10.6",
|
|
71
71
|
"path-browserify": "^1.0.1",
|
|
72
|
-
"tsx": "^4.
|
|
72
|
+
"tsx": "^4.22.4",
|
|
73
73
|
"typescript": "^5.9.3",
|
|
74
|
-
"vitest": "^4.
|
|
74
|
+
"vitest": "^4.1.10"
|
|
75
75
|
}
|
|
76
76
|
}
|