@moxn/kb-migrate 0.4.38 → 0.4.39
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/sources/notion.d.ts
CHANGED
|
@@ -150,7 +150,7 @@ export declare function slugify(title: string): string;
|
|
|
150
150
|
* so a second same-titled sibling was rejected by that assert (audit finding D).
|
|
151
151
|
* Mutates `siblingSlugCounts` (keyed on the BASE slug) the way the builder expects.
|
|
152
152
|
*/
|
|
153
|
-
export declare function disambiguateSibling(title: string, siblingSlugCounts: Map<string, number
|
|
153
|
+
export declare function disambiguateSibling(title: string, siblingSlugCounts: Map<string, number>, slugifyFn?: (s: string) => string): {
|
|
154
154
|
name: string;
|
|
155
155
|
slug: string;
|
|
156
156
|
};
|
package/dist/sources/notion.js
CHANGED
|
@@ -632,12 +632,12 @@ export function slugify(title) {
|
|
|
632
632
|
* so a second same-titled sibling was rejected by that assert (audit finding D).
|
|
633
633
|
* Mutates `siblingSlugCounts` (keyed on the BASE slug) the way the builder expects.
|
|
634
634
|
*/
|
|
635
|
-
export function disambiguateSibling(title, siblingSlugCounts) {
|
|
636
|
-
const baseSlug =
|
|
635
|
+
export function disambiguateSibling(title, siblingSlugCounts, slugifyFn = slugify) {
|
|
636
|
+
const baseSlug = slugifyFn(title);
|
|
637
637
|
const existing = siblingSlugCounts.get(baseSlug) ?? 0;
|
|
638
638
|
siblingSlugCounts.set(baseSlug, existing + 1);
|
|
639
639
|
if (existing === 0)
|
|
640
640
|
return { name: title, slug: baseSlug };
|
|
641
641
|
const name = `${title} ${existing + 1}`;
|
|
642
|
-
return { name, slug:
|
|
642
|
+
return { name, slug: slugifyFn(name) };
|
|
643
643
|
}
|
|
@@ -68,3 +68,16 @@ describe('disambiguateSibling (D — dedup name AND path together)', () => {
|
|
|
68
68
|
expect(disambiguateSibling('Beta', counts).slug).toBe('beta');
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
|
+
describe('disambiguateSibling — custom slugify (OneNote uses slugifyPathSegment)', () => {
|
|
72
|
+
const upperSlug = (s) => s.toUpperCase().replace(/ /g, '_');
|
|
73
|
+
it('derives the slug with the provided function, keeping the bijection', () => {
|
|
74
|
+
const counts = new Map();
|
|
75
|
+
expect(disambiguateSibling('My Page', counts, upperSlug)).toEqual({
|
|
76
|
+
name: 'My Page',
|
|
77
|
+
slug: 'MY_PAGE',
|
|
78
|
+
});
|
|
79
|
+
const second = disambiguateSibling('My Page', counts, upperSlug);
|
|
80
|
+
expect(second).toEqual({ name: 'My Page 2', slug: 'MY_PAGE_2' });
|
|
81
|
+
expect(upperSlug(second.name)).toBe(second.slug);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* own ID or any ancestor's ID is in the set. If the set is empty, every
|
|
12
12
|
* page is included.
|
|
13
13
|
*/
|
|
14
|
+
import { disambiguateSibling } from '../notion.js';
|
|
14
15
|
const MAX_GROUP_DEPTH = 4;
|
|
15
16
|
/**
|
|
16
17
|
* Normalize any human text into a ltree-safe slug segment.
|
|
@@ -96,12 +97,22 @@ async function walkSection(client, section, pathSegs, ctx, ancestorSelected, sel
|
|
|
96
97
|
createdBefore: opts.createdBefore,
|
|
97
98
|
});
|
|
98
99
|
const sectionSeg = slugifyPathSegment(section.displayName);
|
|
100
|
+
// Dedup same-titled sibling pages within a section — suffix the title AND the
|
|
101
|
+
// path segment together so slugify(name) === pathTail (the server's hard
|
|
102
|
+
// bijection assert) and two pages never collide on one path. Without this,
|
|
103
|
+
// two "Untitled" pages produce the same kbPath → the second silently clobbers
|
|
104
|
+
// or skips the first on import. (Notion finding D; OneNote had no dedup at all.)
|
|
105
|
+
const pageSlugCounts = new Map();
|
|
99
106
|
for (const page of pages) {
|
|
100
107
|
const pageSelected = ancestorSelected || (!!sel && sel.has(page.id));
|
|
101
108
|
if (!pageSelected)
|
|
102
109
|
continue;
|
|
103
|
-
const pageSeg =
|
|
104
|
-
out.push(toDiscovered(page,
|
|
110
|
+
const { name: dedupTitle, slug: pageSeg } = disambiguateSibling(page.title ?? 'untitled', pageSlugCounts, slugifyPathSegment);
|
|
111
|
+
out.push(toDiscovered({ ...page, title: dedupTitle }, section, [
|
|
112
|
+
...pathSegs,
|
|
113
|
+
sectionSeg,
|
|
114
|
+
pageSeg,
|
|
115
|
+
], ctx));
|
|
105
116
|
}
|
|
106
117
|
}
|
|
107
118
|
function toDiscovered(page, section, segs, ctx) {
|
package/package.json
CHANGED