roam-export
Version:
A set of tools to Filter/transform/render RoamResearch JSON export. Used in Roam Garden
123 lines • 6.63 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RoamJsonQuery = void 0;
const _ = __importStar(require("lodash"));
const common_1 = require("./common");
const roam_utils_1 = require("./roam-utils");
class RoamJsonQuery {
constructor(allPages, filter, createOrphansForBacklinks = true) {
this.allPages = allPages;
this.filter = filter;
this.createOrphansForBacklinks = createOrphansForBacklinks;
this.blockToPage = new Map();
this.orphanId = 0;
this.createOrphanPage = (name, blocks = []) => {
var _a;
return ({
title: name,
uid: ((_a = this.pageByName.get(name)) === null || _a === void 0 ? void 0 : _a.uid) || `orphan-${this.orphanId++}`,
children: [{
string: `## This is an "Orphan" page. Its core content has not been shared: what you see below is a ` +
`loose collection of pages and page snippets that mention this page, as well as snippets of this ` +
`page that were quoted elsewhere.`,
uid: `orphan-${this.orphanId++}`,
}, ...roam_utils_1.removeHierarchicalDuplicates(blocks),],
});
};
this.removePrivateBlocks = (pages) => pages.map(page => roam_utils_1.removeChildMatching(page, this.filter.makeBlocksWithTheseTagsPrivate));
this.findPublicPages = (pages) => {
if (this.filter.makeAllPagesPublic)
return pages;
return pages.filter(it => this.isPublic(it));
};
this.isPublic = (page) => {
var _a;
return ((_a = this.filter.pagesToMakePublic) === null || _a === void 0 ? void 0 : _a.includes(page.title)) ||
roam_utils_1.isPublic(page, this.filter.makePagesWithTheseTagsPublic);
};
this.buildBlockToPageMap();
this.pageByName = new Map(allPages.map(it => [it.title, it]));
this.pageByUid = new Map(allPages.map(it => [it.uid, it]));
}
getPagesToRender() {
console.log("Starting filtering process with the following settings", this.filter);
const pagesWithoutPrivateBlocks = this.removePrivateBlocks(this.allPages);
const publicPages = this.findPublicPages(pagesWithoutPrivateBlocks);
const referencedBlocks = roam_utils_1.getReferencedBlocks(publicPages, pagesWithoutPrivateBlocks);
console.log(`${referencedBlocks.length} blocks referenced by other blocks`);
const pagesWithBlocks = [...publicPages, ...this.createOrphanPagesWithBlocks(publicPages, referencedBlocks)];
console.log(`There is ${pagesWithBlocks.length} pages with blocks`);
const { blocksReferencingPages, referencedPages } = this.buildBlocksReferencingPages(pagesWithBlocks);
const pagesToRender = this.createOrphansForBacklinks ?
[...pagesWithBlocks, ...this.createOrphansWithReferences(pagesWithBlocks, referencedPages)] :
pagesWithBlocks;
const blockUidsToRender = new Set([...referencedBlocks, ...blocksReferencingPages].map(it => it.uid));
console.log(`${blockUidsToRender.size} blocks to separately render`);
return {
pages: pagesToRender,
blockUids: blockUidsToRender,
};
}
createOrphanPagesWithBlocks(publicPages, referencedBlocks) {
const allPublicBlocks = new Set(roam_utils_1.getFlatBlockList(publicPages));
const orphanBlocks = referencedBlocks.filter(it => !allPublicBlocks.has(it));
console.log(`${orphanBlocks.length + allPublicBlocks.size} total blocks to make public`);
return this.buildOrphanPages(orphanBlocks);
}
createOrphansWithReferences(pagesWithBlocks, referencedPages) {
const existingTitles = new Set(pagesWithBlocks.map(it => it.title));
const orphans = [...referencedPages].filter(it => !existingTitles.has(it.title));
return orphans.map(it => this.createOrphanPage(it.title));
}
buildOrphanPages(orphanBlocks) {
const byPage = _.groupBy(orphanBlocks, (it) => this.blockToPage.get(it === null || it === void 0 ? void 0 : it.uid));
return _.keys(byPage).map(key => this.createOrphanPage(key, byPage[key]));
}
buildBlockToPageMap() {
this.allPages.forEach(it => roam_utils_1.visitChildren(it, block => {
this.blockToPage.set(block["uid"], it.title);
}));
}
/**
* This is required to display content of the block in Backlinks/References section
* Hence including the blocks that have references to any public pages
* TODO: currently these are not rendered and only text is used, so can consider
* not creating MDX nodes for these. Though would probably actually move to
* using rendered version in the future
*/
buildBlocksReferencingPages(pages) {
const blocksReferencingPages = new Set();
const referencedPages = new Set();
pages.forEach(it => roam_utils_1.visitChildren(it, block => {
var _a;
if ("refs" in block) {
const pagesInBlock = (_a = block.refs) === null || _a === void 0 ? void 0 : _a.map(ref => this.pageByUid.get(ref.uid)).filter(common_1.truthy);
if (pagesInBlock === null || pagesInBlock === void 0 ? void 0 : pagesInBlock.length)
blocksReferencingPages.add(block);
pagesInBlock === null || pagesInBlock === void 0 ? void 0 : pagesInBlock.forEach(page => referencedPages.add(page));
}
}));
return { blocksReferencingPages, referencedPages };
}
}
exports.RoamJsonQuery = RoamJsonQuery;
//# sourceMappingURL=filtering.js.map