@dogsbay/corpus 0.2.0-beta.132 → 0.2.0-beta.134
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/dist/index.d.ts +58 -1
- package/dist/index.js +46 -3
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -11,8 +11,65 @@ export interface Corpus {
|
|
|
11
11
|
contains?(path: string, dir: string): boolean;
|
|
12
12
|
}
|
|
13
13
|
export type CorpusFiles = Map<string, string | Uint8Array>;
|
|
14
|
+
export interface MapCorpusOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Every path of the repo (relative to the same root as `files`), when the host knows more
|
|
17
|
+
* files than it has fetched — the playground lists a GitHub tree and fetches as it goes.
|
|
18
|
+
* The corpus lists them all, so the import sees the repo as it is; reading one that `files`
|
|
19
|
+
* does not hold returns undefined and is recorded (`missing`).
|
|
20
|
+
*/
|
|
21
|
+
paths?: Iterable<string>;
|
|
22
|
+
}
|
|
23
|
+
export interface MapCorpus extends Corpus {
|
|
24
|
+
/** Listed paths the import read but `files` did not hold, sorted: fetch them and run it again. */
|
|
25
|
+
missing(): string[];
|
|
26
|
+
}
|
|
14
27
|
/**
|
|
15
28
|
* A corpus over a map of files; bytes are read as UTF-8. A key that is not a plain path
|
|
16
29
|
* (`../x`, `/etc/x`, `a/./b`, a backslash) is left out: the keys come from someone else's repo.
|
|
17
30
|
*/
|
|
18
|
-
export declare function corpusFromMap(files: CorpusFiles):
|
|
31
|
+
export declare function corpusFromMap(files: CorpusFiles, opts?: MapCorpusOptions): MapCorpus;
|
|
32
|
+
/**
|
|
33
|
+
* What a browser conversion still needs, when the host listed more paths than it fetched:
|
|
34
|
+
* `read` the import read (fetch them and convert again: the result changes), `copy` the
|
|
35
|
+
* output copies as they are (fetch them for the finished files; nothing is converted again).
|
|
36
|
+
* Both empty: the result is complete. Each round can find one more level of an include or
|
|
37
|
+
* `require` chain, so a host caps the rounds; a result with `read` not empty is not a
|
|
38
|
+
* conversion (its `files` may be empty: the import could not go on without them).
|
|
39
|
+
*/
|
|
40
|
+
export interface Unfetched {
|
|
41
|
+
read: string[];
|
|
42
|
+
copy: string[];
|
|
43
|
+
/**
|
|
44
|
+
* `copy` with where each file goes in `files` (its output path), in the same order: the host
|
|
45
|
+
* adds the fetched bytes itself, without converting again.
|
|
46
|
+
*/
|
|
47
|
+
copyTo: {
|
|
48
|
+
from: string;
|
|
49
|
+
to: string;
|
|
50
|
+
}[];
|
|
51
|
+
}
|
|
52
|
+
/** `copyTo`'s pairs sorted by source path, and `copy` (the sources) in the same order. */
|
|
53
|
+
export declare function pendingCopies(pairs: {
|
|
54
|
+
from: string;
|
|
55
|
+
to: string;
|
|
56
|
+
}[]): Pick<Unfetched, "copy" | "copyTo">;
|
|
57
|
+
/**
|
|
58
|
+
* The ledger message for a conversion that still needs files (undefined when none), with the
|
|
59
|
+
* error the import stopped on, when it stopped.
|
|
60
|
+
*/
|
|
61
|
+
export declare function unfetchedMessage(read: string[], stoppedOn?: unknown): string | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Each written page's source file → its path in the project, from the pages in the order they
|
|
64
|
+
* were written: a later page at the same path replaces an earlier one, whose file then has no
|
|
65
|
+
* page (its notes would otherwise open another file's page).
|
|
66
|
+
*/
|
|
67
|
+
export declare function pageSources(written: Iterable<{
|
|
68
|
+
file: string;
|
|
69
|
+
path: string;
|
|
70
|
+
}>): Map<string, string>;
|
|
71
|
+
/** The ledger, each entry about a written page's source file given its `page`. */
|
|
72
|
+
export declare function withPages<E extends {
|
|
73
|
+
file?: string;
|
|
74
|
+
page?: string;
|
|
75
|
+
}>(ledger: E[], pageOf: ReadonlyMap<string, string>): E[];
|
package/dist/index.js
CHANGED
|
@@ -12,17 +12,60 @@ import { isPlainPath } from "@dogsbay/detect";
|
|
|
12
12
|
* A corpus over a map of files; bytes are read as UTF-8. A key that is not a plain path
|
|
13
13
|
* (`../x`, `/etc/x`, `a/./b`, a backslash) is left out: the keys come from someone else's repo.
|
|
14
14
|
*/
|
|
15
|
-
export function corpusFromMap(files) {
|
|
15
|
+
export function corpusFromMap(files, opts = {}) {
|
|
16
16
|
const decoder = new TextDecoder();
|
|
17
|
-
const paths = [...files.keys()].filter(isPlainPath).sort();
|
|
17
|
+
const paths = [...new Set([...files.keys(), ...(opts.paths ?? [])])].filter(isPlainPath).sort();
|
|
18
18
|
const listed = new Set(paths);
|
|
19
|
+
const missing = new Set();
|
|
19
20
|
return {
|
|
20
21
|
paths,
|
|
21
22
|
text(path) {
|
|
22
23
|
if (!listed.has(path))
|
|
23
24
|
return undefined;
|
|
24
25
|
const v = files.get(path);
|
|
25
|
-
|
|
26
|
+
if (v === undefined) {
|
|
27
|
+
missing.add(path);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return typeof v === "string" ? v : decoder.decode(v);
|
|
26
31
|
},
|
|
32
|
+
missing: () => [...missing].sort(),
|
|
27
33
|
};
|
|
28
34
|
}
|
|
35
|
+
/** `copyTo`'s pairs sorted by source path, and `copy` (the sources) in the same order. */
|
|
36
|
+
export function pendingCopies(pairs) {
|
|
37
|
+
const copyTo = [...pairs].sort((a, b) => (a.from < b.from ? -1 : a.from > b.from ? 1 : 0));
|
|
38
|
+
return { copy: copyTo.map((p) => p.from), copyTo };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The ledger message for a conversion that still needs files (undefined when none), with the
|
|
42
|
+
* error the import stopped on, when it stopped.
|
|
43
|
+
*/
|
|
44
|
+
export function unfetchedMessage(read, stoppedOn) {
|
|
45
|
+
if (!read.length)
|
|
46
|
+
return undefined;
|
|
47
|
+
const names = `${read.slice(0, 3).join(", ")}${read.length > 3 ? ", …" : ""}`;
|
|
48
|
+
const stopped = stoppedOn instanceof Error ? ` It stopped on: ${stoppedOn.message}` : "";
|
|
49
|
+
return `${read.length} file${read.length === 1 ? "" : "s"} the conversion reads ${read.length === 1 ? "was" : "were"} not given (${names}): fetch them and convert again.${stopped}`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Each written page's source file → its path in the project, from the pages in the order they
|
|
53
|
+
* were written: a later page at the same path replaces an earlier one, whose file then has no
|
|
54
|
+
* page (its notes would otherwise open another file's page).
|
|
55
|
+
*/
|
|
56
|
+
export function pageSources(written) {
|
|
57
|
+
const fileAt = new Map();
|
|
58
|
+
for (const { file, path } of written)
|
|
59
|
+
fileAt.set(path, file);
|
|
60
|
+
const pageOf = new Map();
|
|
61
|
+
for (const [path, file] of fileAt)
|
|
62
|
+
pageOf.set(file, path);
|
|
63
|
+
return pageOf;
|
|
64
|
+
}
|
|
65
|
+
/** The ledger, each entry about a written page's source file given its `page`. */
|
|
66
|
+
export function withPages(ledger, pageOf) {
|
|
67
|
+
return ledger.map((e) => {
|
|
68
|
+
const page = e.file === undefined ? undefined : pageOf.get(e.file);
|
|
69
|
+
return page === undefined ? e : { ...e, page };
|
|
70
|
+
});
|
|
71
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dogsbay/corpus",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.134",
|
|
4
4
|
"description": "A documentation repository as its importers read it, in the browser or in Node: plain paths plus text on demand, from a map of files or from a folder whose symlinks are kept inside it",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@dogsbay/detect": "0.2.0-beta.
|
|
23
|
+
"@dogsbay/detect": "0.2.0-beta.134"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^22.20.1",
|