| import { isScalar, isCollection } from '../nodes/identity.js'; | |
| import { visit } from '../visit.js'; | |
| /** | |
| * Verify that the input string is a valid anchor. | |
| * | |
| * Will throw on errors. | |
| */ | |
| function anchorIsValid(anchor) { | |
| if (/[\x00-\x19\s,[\]{}]/.test(anchor)) { | |
| const sa = JSON.stringify(anchor); | |
| const msg = `Anchor must not contain whitespace or control characters: ${sa}`; | |
| throw new Error(msg); | |
| } | |
| return true; | |
| } | |
| function anchorNames(root) { | |
| const anchors = new Set(); | |
| visit(root, { | |
| Value(_key, node) { | |
| if (node.anchor) | |
| anchors.add(node.anchor); | |
| } | |
| }); | |
| return anchors; | |
| } | |
| /** Find a new anchor name with the given `prefix` and a one-indexed suffix. */ | |
| function findNewAnchor(prefix, exclude) { | |
| for (let i = 1; true; ++i) { | |
| const name = `${prefix}${i}`; | |
| if (!exclude.has(name)) | |
| return name; | |
| } | |
| } | |
| function createNodeAnchors(doc, prefix) { | |
| const aliasObjects = []; | |
| const sourceObjects = new Map(); | |
| let prevAnchors = null; | |
| return { | |
| onAnchor: (source) => { | |
| aliasObjects.push(source); | |
| prevAnchors ?? (prevAnchors = anchorNames(doc)); | |
| const anchor = findNewAnchor(prefix, prevAnchors); | |
| prevAnchors.add(anchor); | |
| return anchor; | |
| }, | |
| /** | |
| * With circular references, the source node is only resolved after all | |
| * of its child nodes are. This is why anchors are set only after all of | |
| * the nodes have been created. | |
| */ | |
| setAnchors: () => { | |
| for (const source of aliasObjects) { | |
| const ref = sourceObjects.get(source); | |
| if (typeof ref === 'object' && | |
| ref.anchor && | |
| (isScalar(ref.node) || isCollection(ref.node))) { | |
| ref.node.anchor = ref.anchor; | |
| } | |
| else { | |
| const error = new Error('Failed to resolve repeated object (this should not happen)'); | |
| error.source = source; | |
| throw error; | |
| } | |
| } | |
| }, | |
| sourceObjects | |
| }; | |
| } | |
| export { anchorIsValid, anchorNames, createNodeAnchors, findNewAnchor }; | |
Xet Storage Details
- Size:
- 2.28 kB
- Xet hash:
- a0c5bd218af2e155daf1d509badfb2039868722b37ed03c2f62a6619053aa1cf
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.