UNPKG

@mdfriday/foundry

Version:

The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.

461 lines 14.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.Site = void 0; const page_1 = require("./page"); const log_1 = require("../../../../pkg/log"); const taxonomies_builder_1 = require("../../../domain/site/entity/taxonomies-builder"); // Create domain-specific logger for site operations const log = (0, log_1.getDomainLogger)('site', { component: 'site' }); /** * Site - TypeScript equivalent of Go's Site entity * Main site management class */ class Site { // Public properties for template access (following Go's pattern) get Title() { return this.title; } // Add Pages property for template access (equivalent to Go's Pages() method) async Pages() { const langIndex = this.languageSvc.getLanguageIndex(this.language.getCurrentLanguage()); const cps = await this.contentSvc.globalPages(langIndex); return this.sitePages(cps); } // Add RegularPages property for template access (equivalent to Go's RegularPages() method) get RegularPages() { const cps = this.contentSvc.globalRegularPages(); return this.sitePages(cps); } constructor(configSvc, contentSvc, translationSvc, languageSvc, sitemap, staticCopySvc, publisher, author, compiler, url, ref, language, navigation, title) { this.template = null; this.home = null; this.configSvc = configSvc; this.contentSvc = contentSvc; this.translationSvc = translationSvc; this.languageSvc = languageSvc; this.sitemap = sitemap; this.staticCopySvc = staticCopySvc; this.publisher = publisher; this.author = author; this.compiler = compiler; this.url = url; this.ref = ref; this.language = language; this.navigation = navigation; this.title = title; } /** * Build site * TypeScript equivalent of Build method from Go */ async build(template) { try { this.template = template; // Setup phase await this.setup(); // Pre-generate menus for all languages (before rendering pages) await this.generateNavigations(); // Copy static files as part of the build process await this.copyStaticFiles(); // Render phase await this.render(); } catch (error) { const message = error instanceof Error ? error.message : String(error); log.error(`❌ Site build failed: ${message}`); throw error; } } /** * Build site with progress callbacks * TypeScript equivalent of Build method from Go with progress tracking */ async buildWithProgress(template, onProgress) { try { this.template = template; // Setup phase await this.setup(); // Pre-generate menus for all languages (before rendering pages) await this.generateNavigations(); // Copy static files as part of the build process await this.copyStaticFiles(); // Render phase with progress tracking await this.renderWithProgress(onProgress); } catch (error) { const message = error instanceof Error ? error.message : String(error); log.error(`❌ Site build failed: ${message}`); throw error; } } /** * Setup site before rendering * TypeScript equivalent of setup method from Go */ async setup() { try { const languageKeys = this.languageSvc.languageKeys(); for (const lang of languageKeys) { this.language.setCurrentLanguage(lang); } } catch (error) { const message = error instanceof Error ? error.message : String(error); log.error(`❌ Setup failed: ${message}`); throw error; } } /** * Render all pages * TypeScript equivalent of render method from Go */ async render() { try { await this.renderPages(); } catch (error) { throw error; } } /** * Render all pages with progress tracking * TypeScript equivalent of render method from Go with progress callbacks */ async renderWithProgress(onProgress) { try { await this.renderPagesWithProgress(onProgress); } catch (error) { throw error; } } /** * Render pages for current language * TypeScript equivalent of renderPages method from Go * 支持增量构建:根据环境变量判断是否只渲染 stale 页面 */ async renderPages() { const langIndex = this.languageSvc.getLanguageIndex(this.language.getCurrentLanguage()); const pages = []; let pageCount = 0; await this.contentSvc.walkPages(langIndex, async (page) => { const sitePage = await this.sitePage(page); pages.push(sitePage); pageCount++; const sources = await this.contentSvc.getPageSources(page); await sitePage.processResources(sources); // Check if this is the home page if (page.isHome()) { this.home = sitePage; } }); for (let i = 0; i < pages.length; i++) { const page = pages[i]; if (page.isStale()) { await page.render(); page.clearStale(); } } } /** * Render pages for current language with progress tracking * TypeScript equivalent of renderPages method from Go with progress callbacks */ async renderPagesWithProgress(onProgress) { const langIndex = this.languageSvc.getLanguageIndex(this.language.getCurrentLanguage()); const pages = []; let pageCount = 0; // First pass: collect all pages await this.contentSvc.walkPages(langIndex, async (page) => { const sitePage = await this.sitePage(page); pages.push(sitePage); pageCount++; const sources = await this.contentSvc.getPageSources(page); await sitePage.processResources(sources); // Check if this is the home page if (page.isHome()) { this.home = sitePage; } }); // Second pass: render pages with progress tracking const totalPages = pages.length; for (let i = 0; i < pages.length; i++) { const page = pages[i]; await page.render(); // Report progress onProgress?.({ currentPage: i + 1, totalPages: totalPages }); } } /** * Get page output (simplified implementation) * TypeScript equivalent of pageOutput method from Go */ async pageOutput(page) { // Simplified implementation - return the page's output return page.output(); } /** * Clear site cache (simplified implementation) */ clearSiteCache() { // Placeholder for cache clearing logic } get Home() { return this.home; } get Params() { return this.configSvc.configParams(); } get Taxonomies() { return this.navigation.getTaxonomies(this.language.getCurrentLanguage()) || new taxonomies_builder_1.TaxonomyList(); } get Menus() { return this.navigation.getMenus(this.language.getCurrentLanguage()); } getTitle() { return this.title; } setTitle(title) { this.title = title; } /** * Get configuration service */ getConfigService() { return this.configSvc; } /** * Get content service */ getContentService() { return this.contentSvc; } /** * Get language service */ getLanguageService() { return this.languageSvc; } /** * Get base URL * Provides the base URL service without exposing internal URL object */ baseURL() { return this.url.base; } /** * Get URL handler */ getURL() { return this.url; } /** * Get reference handler */ getRef() { return this.ref; } /** * Get language handler */ getLanguage() { return this.language; } get Language() { return this.getLanguage(); } /** * Get navigation handler */ getNavigation() { return this.navigation; } /** * Get publisher */ getPublisher() { return this.publisher; } /** * Get template */ getTemplate() { return this.template; } /** * Get author info */ getAuthor() { return this.author; } /** * Get compiler info */ getCompiler() { return this.compiler; } /** * Get sitemap service */ getSitemap() { return this.sitemap; } /** * Check if site is multi-language */ isMultipleLanguage() { return this.language.isMultipleLanguage(); } /** * Get current language */ getCurrentLanguage() { return this.language.lang(); } /** * Get language prefix for URLs */ languagePrefix() { return this.language.languagePrefix(); } /** * Site page factory method - convert content page to site page */ async sitePage(target) { return new page_1.Page(this.template, this.languageSvc, this.publisher, target, this); } /** * Convert array of content pages to array of site pages * TypeScript equivalent of Go's sitePages method */ sitePages(contentPages) { const pages = []; for (let i = 0; i < contentPages.length; i++) { const cp = contentPages[i]; try { // Use synchronous version to match property getter pattern const sitePage = this.sitePageSync(cp); pages.push(sitePage); } catch (error) { log.error(`❌ [Site.sitePages] Failed to convert page ${i}:`, error); // Skip pages that can't be converted, following Go's pattern } } return pages; } /** * Create site page from content page (synchronous version) * TypeScript equivalent of Go's site page creation */ sitePageSync(contentPage) { return new page_1.Page(this.template, this.languageSvc, this.publisher, contentPage, this); } /** * Pre-generate menus for all languages * This ensures menus are cached before page rendering begins */ async generateNavigations() { const languageKeys = this.languageSvc.languageKeys(); for (const lang of languageKeys) { const langIndex = this.languageSvc.getLanguageIndex(lang); await this.navigation.generateMenusForLanguage(lang, langIndex); await this.navigation.generateTaxonomiesForLanguage(lang, langIndex, this); } } /** * Get page by path * TypeScript equivalent of Go's GetPage method * Made synchronous to match template function requirements */ GetPage(...ref) { if (ref.length > 1) { throw new Error(`too many arguments to .Site.GetPage: ${ref}. Use lookups on the form {{ .Site.GetPage "/posts/mypage-md" }}`); } let key = ref[0]; // Normalize path separators (equivalent to filepath.ToSlash) key = key.replace(/\\/g, '/'); // Ensure path starts with "/" if (!key.startsWith('/')) { key = '/' + key; } try { const langIndex = this.languageSvc.getLanguageIndex(this.language.getCurrentLanguage()); // Make synchronous call to content service const contentPage = this.contentSvc.getPageFromPathSync(langIndex, key); if (!contentPage) { log.warn(`⚠️ GetPage: No page found for key "${key}"`); return null; } // Create site page synchronously return this.sitePageSync(contentPage); } catch (error) { log.error(`❌ Error getting page "${key}": ${error}`); return null; } } /** * Copy static files to publish directory * This is a core business capability of the Site entity */ async copyStaticFiles() { try { await this.staticCopySvc.copyStaticFiles(this.staticCopySvc.staticFs(), this.staticCopySvc.publishFs()); } catch (error) { log.error('❌ Static file copy failed:', error); throw error; } } /** * Create site weighted page from ordinal weight page * TypeScript equivalent of Go's siteWeightedPage method */ async siteWeightedPage(ordinalWeightPage) { // First create the site page from the content page const sitePage = await this.sitePage(ordinalWeightPage.page()); // Import WeightedPage here to avoid circular dependency const { WeightedPage } = await Promise.resolve().then(() => __importStar(require('./taxonomies-builder'))); // Return wrapped site page with ordinal weight page return new WeightedPage(sitePage, ordinalWeightPage); } } exports.Site = Site; //# sourceMappingURL=site.js.map