{"_id":"@quartz-community/bases-page","_rev":"4-a39f09742723cb9185c8a24e118a3a2d","name":"@quartz-community/bases-page","dist-tags":{"latest":"1.0.0"},"versions":{"0.2.0":{"name":"@quartz-community/bases-page","version":"0.2.0","keywords":["quartz","quartz-plugin","obsidian","bases","database","page-type"],"author":{"name":"Quartz Community"},"license":"MIT","_id":"@quartz-community/bases-page@0.2.0","maintainers":[{"name":"aarnphm","email":"aaron.pham.2k21@gmail.com"},{"name":"saberzero1","email":"github@emilebangma.com"}],"homepage":"https://quartz.jzhao.xyz","bugs":{"url":"https://github.com/quartz-community/bases-page/issues"},"dist":{"shasum":"0210c4903b01c3c14440c0e1c5f045a576616d43","tarball":"https://registry.npmjs.org/@quartz-community/bases-page/-/bases-page-0.2.0.tgz","fileCount":28,"integrity":"sha512-nOI3bhHNVJZ9rhSQS6CiFXNU39KmXmWshCFfoMZ1JzOKrqlHCoNqYFHTRz2rC2yGNsAitw0Il4/1b7SZwB16mg==","signatures":[{"sig":"MEYCIQDLZIKjhcietGoqkKWF1hs2ZkQkj1dZ99yHHK/pxXx+TwIhAM+eiEKs+NWx6YEZ85sjov5kMGOeQpA/WGPiHwZf9a6h","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@quartz-community%2fbases-page@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":2586811},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","quartz":{"name":"bases-page","version":"1.0.0","category":["transformer","pageType","component"],"displayName":"Bases Page","defaultOrder":50,"dependencies":[],"optionSchema":{"linkResolution":{"type":"enum","values":["absolute","relative","shortest"]},"defaultViewType":{"type":"string"}},"quartzVersion":">=5.0.0","defaultEnabled":true,"defaultOptions":{"linkResolution":"shortest","defaultViewType":"table"}},"engines":{"npm":">=10.9.2","node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./compiler":{"types":"./dist/compiler/index.d.ts","import":"./dist/compiler/index.js"},"./registry":{"types":"./dist/registry.d.ts","import":"./dist/registry.js"},"./components":{"types":"./dist/components/index.d.ts","import":"./dist/components/index.js"},"./package.json":"./package.json"},"gitHead":"6aeb6973fb75a204f36a399e1c5746f0a9c5759c","scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format && npm run test","format":"prettier . --check","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"saberzero1","email":"github@emilebangma.com"},"repository":{"url":"git+https://github.com/quartz-community/bases-page.git","type":"git"},"_npmVersion":"10.9.8","description":"Obsidian Bases page type plugin for Quartz v5. Renders database-like filtered views of notes from .base files.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"@quartz-community/types":"^0.2.1","@quartz-community/utils":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"sass":"^1.97.3","tsup":"^8.5.0","yaml":"^2.8.1","vfile":"^6.0.3","eslint":"^8.57.0","preact":"^10.28.2","vitest":"^2.1.9","prettier":"^3.6.2","typescript":"^5.9.3","@types/hast":"^3.0.4","@types/node":"^24.10.0","@types/mdast":"^4.0.4","github-slugger":"^2.0.0","unist-util-visit":"^5.1.0","hast-util-from-html":"^2.0.3","eslint-config-prettier":"^9.1.0","preact-render-to-string":"^6.6.6","hast-util-to-jsx-runtime":"^2.3.6","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/eslint-plugin":"^7.18.0"},"peerDependencies":{"vfile":"^6.0.3","preact":"^10.0.0","@jackyzha0/quartz":"^5.0.0"},"peerDependenciesMeta":{"vfile":{"optional":true},"preact":{"optional":false},"@jackyzha0/quartz":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/bases-page_0.2.0_1784761062283_0.4504883516728835","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@quartz-community/bases-page","version":"0.2.1","keywords":["quartz","quartz-plugin","obsidian","bases","database","page-type"],"author":{"name":"Quartz Community"},"license":"MIT","_id":"@quartz-community/bases-page@0.2.1","maintainers":[{"name":"aarnphm","email":"aaron.pham.2k21@gmail.com"},{"name":"saberzero1","email":"github@emilebangma.com"}],"homepage":"https://quartz.jzhao.xyz","bugs":{"url":"https://github.com/quartz-community/bases-page/issues"},"dist":{"shasum":"72c5476eeb27fe5edfff9d2f4ac982a7b1167f77","tarball":"https://registry.npmjs.org/@quartz-community/bases-page/-/bases-page-0.2.1.tgz","fileCount":28,"integrity":"sha512-FyCLoRvj4vIOwzksptYnFxPmaHVqZ78utIQ9QDq8GP7W4cfnLRNCpKPoPMBvspKplpoEhn5Zajnu4ymAP08HJQ==","signatures":[{"sig":"MEUCIEXJtOoT38kCgXEH/uZpUivM5v7hHNtgOFep035rpyjFAiEAlsUBEXEOKPgvm3HdVpNKQqbgUmKyXT9JfXs7nzUWbAs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2590090},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","quartz":{"name":"bases-page","version":"1.0.0","category":["transformer","pageType","component"],"displayName":"Bases Page","defaultOrder":50,"dependencies":[],"optionSchema":{"linkResolution":{"type":"enum","values":["absolute","relative","shortest"]},"defaultViewType":{"type":"string"}},"quartzVersion":">=5.0.0","defaultEnabled":true,"defaultOptions":{"linkResolution":"shortest","defaultViewType":"table"}},"engines":{"npm":">=10.9.2","node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./compiler":{"types":"./dist/compiler/index.d.ts","import":"./dist/compiler/index.js"},"./registry":{"types":"./dist/registry.d.ts","import":"./dist/registry.js"},"./components":{"types":"./dist/components/index.d.ts","import":"./dist/components/index.js"},"./package.json":"./package.json"},"gitHead":"3b11fb8a2632c7e501fa398fdc243bd65700da3f","scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format && npm run test","format":"prettier . --check","release":"npm run build && changeset publish","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"saberzero1","email":"github@emilebangma.com"},"repository":{"url":"git+https://github.com/quartz-community/bases-page.git","type":"git"},"_npmVersion":"10.9.8","description":"Obsidian Bases page type plugin for Quartz v5. Renders database-like filtered views of notes from .base files.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"@quartz-community/types":"^0.2.1","@quartz-community/utils":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"sass":"^1.97.3","tsup":"^8.5.0","yaml":"^2.8.1","vfile":"^6.0.3","eslint":"^8.57.0","preact":"^10.28.2","vitest":"^2.1.9","prettier":"^3.6.2","typescript":"^5.9.3","@types/hast":"^3.0.4","@types/node":"^24.10.0","@types/mdast":"^4.0.4","github-slugger":"^2.0.0","@changesets/cli":"^2.29.2","unist-util-visit":"^5.1.0","hast-util-from-html":"^2.0.3","eslint-config-prettier":"^9.1.0","preact-render-to-string":"^6.6.6","hast-util-to-jsx-runtime":"^2.3.6","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/eslint-plugin":"^7.18.0"},"peerDependencies":{"vfile":"^6.0.3","preact":"^10.0.0","@jackyzha0/quartz":"^5.0.0"},"peerDependenciesMeta":{"vfile":{"optional":true},"preact":{"optional":false},"@jackyzha0/quartz":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/bases-page_0.2.1_1784848382474_0.49888042338785277","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@quartz-community/bases-page","version":"0.2.2","keywords":["quartz","quartz-plugin","obsidian","bases","database","page-type"],"author":{"name":"Quartz Community"},"license":"MIT","_id":"@quartz-community/bases-page@0.2.2","maintainers":[{"name":"aarnphm","email":"aaron.pham.2k21@gmail.com"},{"name":"saberzero1","email":"github@emilebangma.com"}],"homepage":"https://quartz.jzhao.xyz","bugs":{"url":"https://github.com/quartz-community/bases-page/issues"},"dist":{"shasum":"fcb2ff52831b857d01cf22720e1c558736f8c3d1","tarball":"https://registry.npmjs.org/@quartz-community/bases-page/-/bases-page-0.2.2.tgz","fileCount":28,"integrity":"sha512-04KlZ8GMws1h7QQ9HVdVPA22oetpQbg19zc6l6/1PrQgL0+5tqic6VjqPywYVNR8S/1iGAE46ZquBe6tpMhr7A==","signatures":[{"sig":"MEUCIQC2fdqSE04zVKeMzSW5WGtqd1X4g7/tdNIoQEp/2b8CiQIgWWjWT0ByGAHaDwMusfc+yvUMBig3i//lPc4Czgq7HDk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2590756},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","quartz":{"name":"bases-page","version":"1.0.0","category":["transformer","pageType","component"],"displayName":"Bases Page","defaultOrder":50,"dependencies":[],"optionSchema":{"linkResolution":{"type":"enum","values":["absolute","relative","shortest"]},"defaultViewType":{"type":"string"}},"quartzVersion":">=5.0.0","defaultEnabled":true,"defaultOptions":{"linkResolution":"shortest","defaultViewType":"table"}},"engines":{"npm":">=10.9.2","node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./compiler":{"types":"./dist/compiler/index.d.ts","import":"./dist/compiler/index.js"},"./registry":{"types":"./dist/registry.d.ts","import":"./dist/registry.js"},"./components":{"types":"./dist/components/index.d.ts","import":"./dist/components/index.js"},"./package.json":"./package.json"},"gitHead":"db114afd1005669b7440b8770603df767147e200","scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format && npm run test","format":"prettier . --check","release":"npm run build && changeset publish","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"saberzero1","email":"github@emilebangma.com"},"repository":{"url":"git+https://github.com/quartz-community/bases-page.git","type":"git"},"_npmVersion":"10.9.8","description":"Obsidian Bases page type plugin for Quartz v5. Renders database-like filtered views of notes from .base files.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"@quartz-community/types":"^0.2.1","@quartz-community/utils":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"sass":"^1.97.3","tsup":"^8.5.0","yaml":"^2.8.1","vfile":"^6.0.3","eslint":"^8.57.0","preact":"^10.28.2","vitest":"^2.1.9","prettier":"^3.6.2","typescript":"^5.9.3","@types/hast":"^3.0.4","@types/node":"^24.10.0","@types/mdast":"^4.0.4","github-slugger":"^2.0.0","@changesets/cli":"^2.29.2","unist-util-visit":"^5.1.0","hast-util-from-html":"^2.0.3","eslint-config-prettier":"^9.1.0","preact-render-to-string":"^6.6.6","hast-util-to-jsx-runtime":"^2.3.6","@typescript-eslint/parser":"^7.18.0","@typescript-eslint/eslint-plugin":"^7.18.0"},"peerDependencies":{"vfile":"^6.0.3","preact":"^10.0.0","@jackyzha0/quartz":"^5.0.0"},"peerDependenciesMeta":{"vfile":{"optional":true},"preact":{"optional":false},"@jackyzha0/quartz":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/bases-page_0.2.2_1784852248539_0.7069919284382582","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@quartz-community/bases-page","version":"1.0.0","description":"Obsidian Bases page type plugin for Quartz v5. Renders database-like filtered views of notes from .base files.","type":"module","license":"MIT","author":{"name":"Quartz Community"},"homepage":"https://quartz.jzhao.xyz","repository":{"type":"git","url":"git+https://github.com/quartz-community/bases-page.git"},"keywords":["quartz","quartz-plugin","obsidian","bases","database","page-type"],"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./components":{"types":"./dist/components/index.d.ts","import":"./dist/components/index.js"},"./registry":{"types":"./dist/registry.d.ts","import":"./dist/registry.js"},"./compiler":{"types":"./dist/compiler/index.d.ts","import":"./dist/compiler/index.js"},"./package.json":"./package.json"},"main":"./dist/index.js","types":"./dist/index.d.ts","sideEffects":false,"scripts":{"build":"tsup","dev":"tsup --watch","lint":"eslint . --max-warnings=0","format":"prettier . --check","test":"vitest run","typecheck":"tsc --noEmit","check":"npm run typecheck && npm run lint && npm run format && npm run test","prepublishOnly":"npm run build","release":"npm run build && changeset publish"},"peerDependencies":{"@jackyzha0/quartz":"^5.0.0","preact":"^10.0.0","vfile":"^6.0.3"},"peerDependenciesMeta":{"@jackyzha0/quartz":{"optional":true},"preact":{"optional":false},"vfile":{"optional":true}},"dependencies":{"@quartz-community/types":"^1.0.0","@quartz-community/utils":"^1.0.0"},"devDependencies":{"@types/hast":"^3.0.4","@types/mdast":"^4.0.4","@types/node":"^24.10.0","@typescript-eslint/eslint-plugin":"^7.18.0","@typescript-eslint/parser":"^7.18.0","eslint":"^8.57.0","eslint-config-prettier":"^9.1.0","github-slugger":"^2.0.0","hast-util-from-html":"^2.0.3","hast-util-to-jsx-runtime":"^2.3.6","preact":"^10.28.2","preact-render-to-string":"^6.6.6","prettier":"^3.6.2","sass":"^1.97.3","tsup":"^8.5.0","typescript":"^5.9.3","unist-util-visit":"^5.1.0","vfile":"^6.0.3","vitest":"^2.1.9","yaml":"^2.8.1","@changesets/cli":"^2.29.2"},"quartz":{"name":"bases-page","displayName":"Bases Page","category":["transformer","pageType","component"],"version":"1.0.0","quartzVersion":">=5.0.0","dependencies":[],"defaultOrder":50,"defaultEnabled":true,"defaultOptions":{"defaultViewType":"table","linkResolution":"shortest"},"optionSchema":{"defaultViewType":{"type":"string"},"linkResolution":{"type":"enum","values":["absolute","relative","shortest"]}}},"engines":{"node":">=22","npm":">=10.9.2"},"publishConfig":{"access":"public"},"_id":"@quartz-community/bases-page@1.0.0","gitHead":"5c729d1c6be7d89b05ad35fbf28f0b660ce17968","bugs":{"url":"https://github.com/quartz-community/bases-page/issues"},"_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-elqwinAnZTE0Z8F1odTzRmNj0CHDNwpNEBsrzjhs708wEf4MVHMvUce9r0ep/5gJBN1OvIeREAmsvwumG38KIA==","shasum":"f88eff9a9d819f0c8616ed2ce252cb5a92372eea","tarball":"https://registry.npmjs.org/@quartz-community/bases-page/-/bases-page-1.0.0.tgz","fileCount":28,"unpackedSize":2591118,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCID2J8lp0h7XyjdMxTrYWjc6MMRBpHfm1hPCm2elD0YYfAiBuM/TKeQAS5vnn5x0eRF5HRD/3VFob+fcf/Q5Pwja37A=="}]},"_npmUser":{"name":"saberzero1","email":"github@emilebangma.com"},"directories":{},"maintainers":[{"name":"aarnphm","email":"aaron.pham.2k21@gmail.com"},{"name":"saberzero1","email":"github@emilebangma.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bases-page_1.0.0_1789429362876_0.3471738866497396"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-22T22:57:42.079Z","modified":"2026-09-14T23:42:43.202Z","0.2.0":"2026-07-22T22:57:42.443Z","0.2.1":"2026-07-23T23:13:02.653Z","0.2.2":"2026-07-24T00:17:28.918Z","1.0.0":"2026-09-14T23:42:43.026Z"},"bugs":{"url":"https://github.com/quartz-community/bases-page/issues"},"author":{"name":"Quartz Community"},"license":"MIT","homepage":"https://quartz.jzhao.xyz","keywords":["quartz","quartz-plugin","obsidian","bases","database","page-type"],"repository":{"type":"git","url":"git+https://github.com/quartz-community/bases-page.git"},"description":"Obsidian Bases page type plugin for Quartz v5. Renders database-like filtered views of notes from .base files.","maintainers":[{"name":"aarnphm","email":"aaron.pham.2k21@gmail.com"},{"name":"saberzero1","email":"github@emilebangma.com"}],"readme":"# @quartz-community/bases-page\n\nA page type and component plugin for Quartz v5 that renders Obsidian Bases (.base files) as database-like filtered views. This plugin (v0.2.0) provides a powerful way to visualize and interact with your Obsidian data in a structured format.\n\n## Installation\n\n```bash\nnpx quartz plugin add github:quartz-community/bases-page\n```\n\n## Usage\n\nEnable the plugin in your Quartz configuration:\n\n```yaml title=\"quartz.config.yaml\"\nplugins:\n  - source: github:quartz-community/bases-page\n    enabled: true\n```\n\n## Interaction with `unlisted` pages\n\n`bases-page` respects the `file.data.unlisted` convention. Pages marked `unlisted: true` (by `@quartz-community/unlisted-pages`, or by `@quartz-community/encrypted-pages` via `unlistWhenEncrypted: true` or per-page `unlisted: true` / `stealth: true`) are excluded from every rendered base view — table, list, board, cards, gallery, and any custom view registered via `viewRegistry`. Both the main entry loop and the internal `fileLookup` used by `.asFile()` method resolution skip unlisted pages, so they cannot be dereferenced from formulas on visible pages either.\n\n> [!note]\n> Base views are **server-side rendered** HTML baked at build time. They do not update client-side after a visitor successfully decrypts an encrypted page. Graph, explorer, and search all re-hydrate from the patched in-memory content index after decryption and show newly-unlocked pages for the rest of the browser session — base views do not, because they were materialized at build time with unlisted pages already excluded. A visitor who decrypts a revealable encrypted page will see it appear in graph, explorer, and search, but **not** in any base view on the site, until the site is rebuilt with that page listed. This is the same structural limitation that applies to backlinks, recent notes, folder listings, and tag listings.\n\n### TypeScript Override\n\nFor advanced use cases (e.g. custom view renderers), you can override in TypeScript:\n\n```ts title=\"quartz.ts (override)\"\nimport * as ExternalPlugin from \"./.quartz/plugins\";\n\nExternalPlugin.BasesPage({\n  defaultViewType: \"table\",\n  linkResolution: \"shortest\",\n  customViews: {\n    myView: ({\n      entries,\n      view,\n      basesData,\n      total,\n      locale,\n      slug,\n      allSlugs,\n      linkResolution,\n      options,\n    }) => {\n      // return JSX\n    },\n  },\n});\n```\n\n## Built-in Views\n\n- **Table**: Sortable columns with automatic type rendering for strings, numbers, booleans, arrays, and links. Supports custom column widths and row heights.\n- **List**: A compact list view displaying metadata chips for each entry.\n- **Cards**: A card-based layout with support for an optional image property and configurable card size or aspect ratio.\n- **Gallery**: An image-focused grid layout designed for visual content with configurable card sizes.\n- **Board**: A Kanban-style board that groups entries by a specific property (using boardProperty or groupBy), creating columns for each group value.\n\n## Features\n\n- Multiple views per .base file (switchable tabs)\n- Recursive filter trees (and/or/not)\n- Formulas (computed properties via expression engine)\n- Summaries (column aggregations: Count, Average, Min, Max, Sum, Range, Median, Stddev, Earliest, Latest, Checked, Unchecked, Empty, Filled, Unique)\n- Property display configuration\n- Wikilink and Markdown link rendering\n- Sort and grouping\n\n## Expression Engine\n\nThe expression engine follows a pipeline of source, lexer, Pratt parser, AST, bytecode compiler, and stack interpreter.\n\n### Supported Types\n\n- Strings\n- Numbers\n- Booleans\n- Null\n- Lists\n\n### Operators\n\n- **Arithmetic**: +, -, \\*, /\n- **Comparison**: ==, !=, >, <, >=, <=\n- **Logical**: and / &&, or / ||, not / !\n\n### Property Access\n\n- `note.property`: Access a property on the current note.\n- `file.name`: The name of the file.\n- `file.path`: The full path of the file.\n- `file.folder`: The folder containing the file.\n- `file.ext`: The file extension.\n- `file.tags`: A list of tags associated with the file.\n- `file.links`: A list of links in the file.\n- `file.created`: The creation date of the file.\n- `file.modified`: The last modification date of the file.\n- `formula.name`: Access the result of another formula.\n\n### Built-in Global Functions\n\n- `if(condition, then, else)`\n- `contains(container, item)`\n- `date(string)`\n- `duration(string)`\n- `now()`\n- `today()`\n- `number(value)`\n- `min(a, b, ...)`\n- `max(a, b, ...)`\n- `list(value)`\n- `link(path, display?)`\n- `image(url)`\n- `icon(name)`\n- `html(string)`\n- `escapeHTML(string)`\n- `file(path)`\n\n### Method Functions\n\n**Strings**\n\n- `contains(substring)`\n- `startsWith(prefix)`\n- `endsWith(suffix)`\n- `lower()`\n- `upper()`\n- `trim()`\n- `replace(pattern, replacement)`\n- `slice(start, end?)`\n- `isEmpty()`\n- `repeat(count)`\n- `reverse()`\n\n**Numbers**\n\n- `toFixed(digits)`\n- `round()`\n- `floor()`\n- `ceil()`\n- `abs()`\n\n**Dates**\n\n- `format(formatString)`\n- `year()`\n- `month()`\n- `day()`\n- `time()`\n- `relative()`\n- `isEmpty()`\n\n**Lists**\n\n- `sum()`\n- `mean()`\n- `count()`\n- `min()`\n- `max()`\n- `round()`\n\n**File**\n\n- `hasTag(tag)`\n- `hasLink(link)`\n- `inFolder(folder)`\n- `hasProperty(property)`\n\n## Extending with Custom Views\n\nCommunity extensions can register custom view types using the view registry.\n\n### Registering a View\n\n```typescript\nimport { viewRegistry } from \"@quartz-community/bases-page/registry\";\n\nviewRegistry.register({\n  id: \"my-custom-view\",\n  name: \"My Custom View\",\n  icon: \"star\",\n  render: (props) => {\n    const { entries, view, basesData, total, locale, slug, allSlugs, linkResolution, options } =\n      props;\n    // Return your React/Preact component\n  },\n  css: `.my-custom-view { color: red; }`,\n  afterDOMLoaded: `console.log(\"My custom view loaded\");`,\n  options: { enableFeatureX: true },\n});\n```\n\n### Interfaces\n\n**ViewTypeRegistration**\n\n```typescript\ninterface ViewTypeRegistration {\n  id: string;\n  name: string;\n  icon?: string;\n  render: ViewRenderer;\n  css?: string;\n  afterDOMLoaded?: string;\n  options?: Record<string, unknown>;\n}\n```\n\n**ViewRendererProps**\n\n```typescript\ninterface ViewRendererProps {\n  entries: BasesEntry[];\n  view: BasesView;\n  basesData: BasesData;\n  total: number;\n  locale: string;\n  slug: string;\n  allSlugs: string[];\n  linkResolution: \"absolute\" | \"relative\" | \"shortest\";\n  options?: Record<string, unknown>;\n}\n```\n\n### Passing Options to a Custom View\n\nCommunity plugins can use the `options` field to accept configuration at registration time. This is useful for feature flags, API keys, or other plugin-level settings.\n\n```typescript\nimport { viewRegistry } from \"@quartz-community/bases-page/registry\";\nimport type { LeafletMapPluginOptions } from \"./types\";\n\nconst defaultOptions: LeafletMapPluginOptions = {\n  enableCopyTool: false,\n};\n\nexport function registerLeafletMap(userOpts?: Partial<LeafletMapPluginOptions>): void {\n  const opts = { ...defaultOptions, ...userOpts };\n  viewRegistry.register({\n    ...leafletMapViewRegistration,\n    options: opts,\n  });\n}\n```\n\nIn the renderer, these options are available via `props.options` and should be cast to the plugin's options type.\n\n## Compiler API\n\nThe expression engine is available as a public API for advanced usage. Import from `@quartz-community/bases-page/compiler`.\n\n```typescript\nimport {\n  compile,\n  evaluate,\n  evaluateFilter,\n  resolvePropertyValue,\n} from \"@quartz-community/bases-page/compiler\";\n\n// Compile an expression to bytecode\nconst compiled = compile(\"note.price * 1.2\");\n\n// Evaluate an expression in a context\nconst result = evaluate(\"note.price * 1.2\", context);\n\n// Evaluate a filter node\nconst isMatch = evaluateFilter(filterNode, context);\n\n// Resolve a property path\nconst value = resolvePropertyValue(\"file.name\", context);\n```\n\n### EvalContext Shape\n\n```typescript\ninterface EvalContext {\n  note: Record<string, unknown>;\n  file: {\n    name: string;\n    path: string;\n    folder: string;\n    ext: string;\n    tags: string[];\n    links: string[];\n    created?: string;\n    modified?: string;\n  };\n  formula: Record<string, unknown>;\n}\n```\n\n## Package Exports\n\n- `.`: Main plugin entry (BasesPage, BasesBody, viewRegistry, registerCustomViews, compiler API, types)\n- `./types`: All type definitions\n- `./components`: React/Preact components (BasesBody, ViewSelector)\n- `./registry`: View registry singleton and registerCustomViews helper\n- `./compiler`: Expression engine (compile, evaluate, evaluateFilter, resolvePropertyValue)\n\n## Configuration Options\n\n| Option            | Type                                     | Default      | Description                                                                                    |\n| :---------------- | :--------------------------------------- | :----------- | :--------------------------------------------------------------------------------------------- |\n| `defaultViewType` | `string`                                 | `\"table\"`    | The default view type used when none is specified in the .base file.                           |\n| `linkResolution`  | `\"absolute\" \\| \"relative\" \\| \"shortest\"` | `\"shortest\"` | How to resolve internal links in view renderers. Should match your crawl-links plugin setting. |\n| `customViews`     | `Record<string, ViewRenderer>`           | `{}`         | Custom view renderers provided via TypeScript override.                                        |\n\n## License\n\nMIT\n","readmeFilename":"README.md"}