@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
313 lines • 12.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Content = void 0;
const _1 = require("./");
const doctree_1 = require("../../../../pkg/doctree");
const fileinfo_1 = require("../vo/fileinfo");
const log_1 = require("../../../../pkg/log");
const paths_1 = require("../../../domain/paths");
// Create a domain-specific logger for content operations
const log = (0, log_1.getDomainLogger)('content', { component: 'content' });
class Content {
constructor(fs, converter, pageMap) {
this.fs = fs;
this.converter = converter;
this.pageMap = pageMap;
}
setTemplateSvc(templateSvc) {
this.pageMap.pageBuilder.templateSvc = templateSvc;
}
async renderString(ctx, ...args) {
if (args.length < 1 || args.length > 2) {
throw new Error("RenderString want 1 or 2 arguments");
}
let sidx = 1;
if (args.length === 1) {
sidx = 0;
}
else {
const firstArg = args[0];
if (typeof firstArg !== 'object' || firstArg === null) {
throw new Error("first argument must be a map");
}
throw new Error("RenderString not implemented yet");
}
const contentToRender = args[sidx];
const contentStr = String(contentToRender);
const fmi = this.fs.newFileMetaInfoWithContent(contentStr);
const file = (0, fileinfo_1.newFileInfo)(fmi);
// For now, return the content directly without caching
// TODO: Implement proper caching when cache system is available
return contentStr;
}
async collectPages() {
try {
await this.process();
await this.assemble();
}
catch (error) {
throw new Error(`process/assemble: ${error}`);
}
}
async process() {
try {
const c = new _1.PagesCollector(this.pageMap, this.fs);
await c.collect();
}
catch (error) {
throw error;
}
}
async assemble() {
try {
await this.pageMap.assemble();
}
catch (error) {
throw error;
}
}
/**
* GetPageSources - exact replica of Go's GetPageSources method
*/
async getPageSources(page) {
let keyPage = page.paths().base();
if (keyPage === "/") {
keyPage = "";
}
const key = keyPage + "/get-sources-for-page";
return await this.pageMap.getResourcesForPage(page);
}
/**
* GlobalPages - exact replica of Go's GlobalPages method
*/
async globalPages(langIndex) {
return await this.pageMap.getPagesInSection(langIndex, new _1.PageMapQueryPagesInSectionImpl("", "global", true, // recursive
true, // includeSelf
0, // index
_1.pagePredicates.shouldListGlobal));
}
async globalRegularPages() {
return await this.pageMap.getPagesInSection(0, new _1.PageMapQueryPagesInSectionImpl("", "global", true, // recursive
true, // includeSelf
0, // index
(p) => _1.pagePredicates.shouldListGlobal(p) && _1.pagePredicates.kindPage(p)));
}
/**
* WalkPages - exact replica of Go's WalkPages method
* TypeScript equivalent of golang/internal/domain/contenthub/entity/walk.go:WalkPages
*/
async walkPages(langIndex, walker) {
try {
// Get the page tree for the specified language index
// This is equivalent to: tree := ch.PageMap.TreePages.Shape(0, langIndex)
const tree = this.pageMap.treePages.shape(0, langIndex);
// Create a walker equivalent to Go's NodeShiftTreeWalker
const walkHandler = async (key, node) => {
if (!node) {
return false;
}
// Equivalent to: ps, found := n.getPage()
const [page, found] = node.getPage();
if (!found) {
return false;
}
// Equivalent to: if err := walker(ps); err != nil { return false, err }
try {
await walker(page);
}
catch (error) {
throw error;
}
return false; // Continue walking
};
// Walk the tree - this mimics the Go version's tree walking
await this.walkTree(tree, walkHandler);
}
catch (error) {
log.error(`WalkPages failed for langIndex ${langIndex}:`, error);
throw error;
}
}
/**
* WalkTaxonomies - exact replica of Go's WalkTaxonomies method
* TypeScript equivalent of golang/internal/domain/contenthub/entity/walk.go:WalkTaxonomies
*/
async walkTaxonomies(langIndex, walker) {
try {
// Get the page tree for the specified language index
const tree = this.pageMap.treePages.shape(0, langIndex);
// Get taxonomy views from the page builder's taxonomy service
const tc = this.pageMap.pageBuilder.taxonomy;
for (const viewName of tc.views) {
const key = tc.pluralTreeKey(viewName.plural());
// Create a walker handler for each taxonomy
const w = new doctree_1.NodeShiftTreeWalker({
tree: tree,
prefix: (0, _1.addTrailingSlash)(key),
lockType: doctree_1.LockType.LockTypeRead,
handle: async (s, n, match) => {
const [p, found] = n.getPage();
if (!found) {
return [false, null];
}
// Check if this is a term page
if (p.kind() === 'term') {
const t = p; // TermPage
if (!t.term) {
return [true, new Error('term is empty')];
}
const k = t.term.toLowerCase();
// Walk through taxonomy entries
try {
await this.pageMap.treeTaxonomyEntries.walkPrefix(doctree_1.LockType.LockTypeRead, (0, _1.addTrailingSlash)(s), (ss, wn) => {
const [sp, found] = wn.getPage();
if (!found) {
return [false, null];
}
// Call the walker function but don't await it here
// The promise will be handled by the caller
walker(viewName.plural(), k, {
weight: () => wn.term.Weight(),
ordinal: () => wn.term.Ordinal(),
page: () => sp,
owner: () => t
}).catch(err => {
log.error('Error in taxonomy walker:', err);
});
return [false, null];
});
return [false, null];
}
catch (err) {
return [true, err];
}
}
return [false, null];
}
});
await w.walk();
}
}
catch (error) {
throw error;
}
}
/**
* Helper method to walk the tree structure
* This is a simplified version of Go's NodeShiftTreeWalker.Walk
*/
async walkTree(tree, handler) {
// This is a simplified implementation
// In the Go version, this uses a sophisticated tree walker
// For now, we'll iterate through available pages
try {
// Get all available pages using the existing getPagesInSection method
// This gets all pages recursively from root, which is equivalent to walking the entire tree
const allPages = await this.pageMap.getPagesInSection(0, // langIndex - we'll use the same langIndex from the calling method
new _1.PageMapQueryPagesInSectionImpl("", // path - empty string means root
"walk", // keyPart
true, // recursive - get all pages
true, // includeSelf
0, // index
() => true // include all pages
));
for (let i = 0; i < allPages.length; i++) {
const page = allPages[i];
const key = page.paths().path();
// Create a mock node that has getPage method
const mockNode = {
getPage: () => [page, true]
};
await handler(key, mockNode);
}
}
catch (error) {
log.error('Error walking tree:', error);
throw error;
}
}
/**
* GetPageFromPath - TypeScript equivalent of Go's PageFinder.GetPageFromPath
* This is the core content domain business logic for finding pages by path
*/
getPageFromPath(langIndex, path) {
try {
const pathProcessor = paths_1.PathDomain.createProcessor();
const ps = pathProcessor.parse(paths_1.PATH_CONSTANTS.COMPONENT_FOLDER_CONTENT, path);
const tree = this.pageMap.treePages.shape(0, langIndex);
// Parse the path - equivalent to Go's paths.Parse(files.ComponentFolderContent, path)
// Try exact match first - equivalent to: n := tree.Get(p.Base())
let node = tree.get(ps.base());
if (node) {
const [page, found] = node.getPage();
if (found) {
return page;
}
}
return null;
}
catch (error) {
log.error(`❌ Content.getPageFromPath error for path "${path}":`, error);
return null;
}
}
getPageFromFile(langIndex, file) {
try {
const tree = this.pageMap.treePages.shape(0, langIndex);
let node = tree.get(file.paths().base());
if (node) {
const [page, found] = node.getPage();
if (found) {
return page;
}
}
return null;
}
catch (error) {
log.error(`❌ Content.getPageFromPath error for path "${file.path()}":`, error);
return null;
}
}
async handleChangeFiles(fileMetaInfos) {
const affectedPageKeys = [];
for (const [filePath, fileMetaInfo] of fileMetaInfos) {
try {
await this.addOrUpdateFile(fileMetaInfo, affectedPageKeys);
}
catch (error) {
log.error(`Failed to process file change for ${filePath}:`, error);
}
}
return affectedPageKeys;
}
/**
* 添加或更新文件到 PageMap,参考 collectDir 中的实现
*/
async addOrUpdateFile(fileMetaInfo, affectedPageKeys) {
if (fileMetaInfo.isDir()) {
// 目录变更,暂时不处理(在这个阶段我们只关注单个文件)
return;
}
try {
// 参考 collectDir 中的实现:为文件创建 FileInfo 并添加到 PageMap
const file = (0, fileinfo_1.newFileInfo)(fileMetaInfo);
// 获取现有页面的 key(如果存在)
const pageKey = file.paths().base();
if (pageKey) {
affectedPageKeys.push(pageKey);
}
// 添加到 PageMap(如果页面已存在会被更新)
await this.pageMap.addFi(file);
const page = this.getPageFromFile(0, file);
if (page && page.pageIdentity) {
page.pageIdentity().markStale();
}
}
catch (error) {
log.error(`Failed to add/update file in PageMap: ${fileMetaInfo.fileName()}`, error);
throw error;
}
}
}
exports.Content = Content;
//# sourceMappingURL=content.js.map