@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
319 lines • 7.94 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MENUS_BEFORE = exports.MENUS_AFTER = exports.Menus = exports.Menu = exports.MenuEntry = void 0;
exports.newEmptyMenus = newEmptyMenus;
const log_1 = require("../../../../pkg/log");
// Create domain-specific logger for menu operations
const log = (0, log_1.getDomainLogger)('site', { component: 'menu' });
/**
* MenuEntry - A single menu item with hierarchical support
* TypeScript equivalent based on menu.md requirements
*/
class MenuEntry {
constructor(options) {
this._title = options.title;
this._url = options.url;
this._isDir = options.isDir;
this._hasIndex = options.hasIndex;
this._children = options.children || [];
this._weight = options.weight || 0;
this._identifier = options.identifier || this._url;
}
/**
* Get menu entry title
*/
title() {
return this._title;
}
/**
* Get menu entry URL
*/
url() {
return this._url;
}
/**
* Check if this is a directory (branch)
*/
isDirectory() {
return this._isDir;
}
/**
* Check if this directory has an index page (leaf)
*/
hasIndex() {
return this._hasIndex;
}
/**
* Get child menu entries
*/
children() {
return [...this._children];
}
/**
* Get menu entry weight for sorting
*/
weight() {
return this._weight;
}
/**
* Get menu entry identifier
*/
identifier() {
return this._identifier;
}
/**
* Check if this menu entry has children
*/
hasChildren() {
return this._children.length > 0;
}
/**
* Add a child menu entry
*/
addChild(child) {
const newChildren = [...this._children, child];
return new MenuEntry({
title: this._title,
url: this._url,
isDir: this._isDir,
hasIndex: this._hasIndex,
children: newChildren,
weight: this._weight,
identifier: this._identifier,
});
}
/**
* Convert to JSON representation as specified in menu.md
*/
toJSON() {
return {
title: this._title,
url: this._url,
isDir: this._isDir,
hasIndex: this._hasIndex,
children: this._children.map(child => child.toJSON()),
};
}
/**
* Create a new MenuEntry with updated properties
*/
withChildren(children) {
return new MenuEntry({
title: this._title,
url: this._url,
isDir: this._isDir,
hasIndex: this._hasIndex,
children: children,
weight: this._weight,
identifier: this._identifier,
});
}
}
exports.MenuEntry = MenuEntry;
/**
* Menu - A collection of menu entries with sorting and filtering capabilities
*/
class Menu {
constructor(entries = []) {
this._entries = [...entries];
}
/**
* Get all entries
*/
entries() {
return [...this._entries];
}
/**
* Get entry by index
*/
get(index) {
return this._entries[index];
}
/**
* Get length
*/
get length() {
return this._entries.length;
}
/**
* Add a menu entry
*/
add(entry) {
const newEntries = [...this._entries, entry];
return new Menu(newEntries).sortMenu();
}
/**
* Sort menu entries by weight and then by title
*/
sortMenu() {
const sorted = [...this._entries].sort((a, b) => {
// Sort by weight first
if (a.weight() !== b.weight()) {
if (b.weight() === 0)
return -1;
if (a.weight() === 0)
return 1;
return a.weight() - b.weight();
}
// Then sort by title
const titleComparison = a.title().localeCompare(b.title());
if (titleComparison !== 0) {
return titleComparison;
}
// Finally sort by identifier
return a.identifier().localeCompare(b.identifier());
});
return new Menu(sorted);
}
/**
* Filter menu entries by predicate
*/
filterMenu(predicate) {
const filtered = this._entries.filter(predicate);
return new Menu(filtered);
}
/**
* Find menu entry by identifier
*/
findByIdentifier(identifier) {
return this._entries.find(entry => entry.identifier() === identifier);
}
/**
* Find menu entry by URL
*/
findByUrl(url) {
return this._entries.find(entry => entry.url() === url);
}
/**
* Get all leaf entries (entries without children)
*/
getLeaves() {
return this.filterMenu(entry => !entry.hasChildren());
}
/**
* Get all branch entries (entries with children)
*/
getBranches() {
return this.filterMenu(entry => entry.hasChildren());
}
/**
* Convert to JSON array
*/
toJSON() {
return this._entries.map(entry => entry.toJSON());
}
/**
* Iterator support
*/
[Symbol.iterator]() {
return this._entries[Symbol.iterator]();
}
/**
* Map over entries
*/
map(callback) {
return this._entries.map(callback);
}
/**
* ForEach over entries
*/
forEach(callback) {
this._entries.forEach(callback);
}
}
exports.Menu = Menu;
/**
* Menus - A collection of menus by name, supporting multiple languages
* TypeScript equivalent of valueobject.Menus from Go
*/
class Menus {
constructor(menus = new Map()) {
this._menus = new Map(menus);
}
/**
* Get menu by name
*/
get(name) {
return this._menus.get(name);
}
/**
* Set menu by name
*/
set(name, menu) {
const newMenus = new Map(this._menus);
newMenus.set(name, menu);
return new Menus(newMenus);
}
/**
* Get all menu names
*/
names() {
return Array.from(this._menus.keys());
}
/**
* Check if menu exists
*/
has(name) {
return this._menus.has(name);
}
/**
* Check if menu entry has sub-menu
*/
hasSubMenu(entry) {
const menu = this._menus.get(entry.title());
if (!menu)
return false;
if (menu.length === 1 && menu.get(0)?.title() === entry.title()) {
return false;
}
return menu.length > 1;
}
/**
* Get all menus as entries
*/
entries() {
return Array.from(this._menus.entries());
}
/**
* Convert to plain object for serialization
*/
toJSON() {
const result = {};
for (const [name, menu] of this._menus.entries()) {
result[name] = menu.toJSON();
}
return result;
}
/**
* Merge with another Menus instance
*/
merge(other) {
const newMenus = new Map(this._menus);
for (const [name, menu] of other._menus.entries()) {
if (newMenus.has(name)) {
// Merge menu entries
const existingMenu = newMenus.get(name);
const mergedEntries = [...existingMenu.entries(), ...menu.entries()];
const mergedMenu = new Menu(mergedEntries).sortMenu();
newMenus.set(name, mergedMenu);
}
else {
newMenus.set(name, menu);
}
}
return new Menus(newMenus);
}
}
exports.Menus = Menus;
/**
* Create empty menus instance
*/
function newEmptyMenus() {
return new Menus();
}
/**
* Menu constants
*/
exports.MENUS_AFTER = "after";
exports.MENUS_BEFORE = "before";
//# sourceMappingURL=menu.js.map