diffwiki-core 0.17.3 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Config, R as Registry, a as CollectionEntry, A as Audience, b as Article, P as PublishStatus, c as RepoConfig, d as ProjectConfig, S as SiteConfig, e as CollectionInfo, f as CollectionTree, g as PageData, h as ArticleNode, T as TreeNode, Q as QueryHit, i as QueryOptions, D as Diagnostic, j as ParsedArticle, k as ArticleContent, l as TocItem, L as LinkGraph, m as LocalGraph, n as SearchMode, o as SearchProvider, p as PluginRecord, q as PluginEvent, r as PluginKind, s as PluginRegistryFile } from './frontmatter-ghMCpLNf.cjs';
2
- export { t as CollectionType, u as DiagnosticLevel, v as DocData, G as GraphEdge, w as GraphNode, H as HomeCard, x as ListingEntry, N as NATIVE_ENGINE, y as NodeMeta, z as PluginCapabilities, B as PluginHealth, E as PluginReadiness, F as ProjectCollection, I as ProjectContext, J as SearchExpansion, K as SerializableArticle, M as SiteCopyright, O as SiteHome, U as parseArticle, V as parseFrontmatter, W as serializeArticle, X as stripFrontmatter } from './frontmatter-ghMCpLNf.cjs';
1
+ import { C as Config, a as CollectionEntry, R as Registry, A as Audience, P as PublishStatus, b as Article, c as RepoConfig, d as ProjectConfig, S as SiteConfig, e as CollectionInfo, f as CollectionTree, g as PageData, h as ArticleNode, T as TreeNode, Q as QueryHit, i as QueryOptions, D as Diagnostic, j as ParsedArticle, k as ArticleContent, l as TocItem, L as LinkGraph, m as LocalGraph, n as SearchMode, o as SearchProvider, p as PluginRecord, q as PluginEvent, r as PluginKind, s as PluginRegistryFile } from './frontmatter-D7gO1fg4.cjs';
2
+ export { t as CollectionType, u as DiagnosticLevel, v as DocData, G as GraphEdge, w as GraphNode, H as HomeCard, x as ListingEntry, N as NATIVE_ENGINE, y as NodeMeta, z as PluginCapabilities, B as PluginHealth, E as PluginReadiness, F as ProjectCollection, I as ProjectContext, J as SearchExpansion, K as SerializableArticle, M as SiteCopyright, O as SiteHome, U as parseArticle, V as parseFrontmatter, W as patchArticle, X as serializeArticle, Y as stripFrontmatter } from './frontmatter-D7gO1fg4.cjs';
3
3
  import { SearchDoc } from './bm25.cjs';
4
4
  export { RankableFields, rankDocs, tokenize } from './bm25.cjs';
5
5
  import { LogLevel, Logger } from '@logtape/logtape';
@@ -42,6 +42,8 @@ declare function configPath(): string;
42
42
  declare function collectionsDir(): string;
43
43
  /** Where authoring templates live (user-overridable), seeded by `diffwiki templates init`. */
44
44
  declare function templatesDir(): string;
45
+ /** Raw source records and per-article source manifests. */
46
+ declare function metaDir(): string;
45
47
  declare function collectionDir(name: string): string;
46
48
  declare function pluginsDir(): string;
47
49
  declare function pluginsRegistryPath(): string;
@@ -80,6 +82,7 @@ interface SeedResult {
80
82
  declare function seedTemplates(srcDir: string): Promise<SeedResult>;
81
83
  /** The template shape names bundled at `srcDir`, e.g. `['guide', 'recipe', …]`. */
82
84
  declare function listTemplateShapes(srcDir: string): Promise<string[]>;
85
+ type TemplateCategory = 'article' | 'meta';
83
86
  /** A template's self-describing metadata, read from its frontmatter. */
84
87
  interface TemplateInfo {
85
88
  /** The shape id (frontmatter `shape:`, else the filename stem). */
@@ -90,6 +93,9 @@ interface TemplateInfo {
90
93
  budget?: [number, number];
91
94
  /** The template file name. */
92
95
  file: string;
96
+ /** Effective user override or bundled file. */
97
+ path: string;
98
+ category: TemplateCategory;
93
99
  }
94
100
  /**
95
101
  * List the templates bundled at `srcDir` with their self-describing metadata
@@ -98,7 +104,7 @@ interface TemplateInfo {
98
104
  * hard-coding shape names, so dropping in a template with frontmatter
99
105
  * makes it discoverable. Falls back to the filename stem when `shape:` is absent.
100
106
  */
101
- declare function listTemplates(srcDir: string): Promise<TemplateInfo[]>;
107
+ declare function listTemplates(srcDir: string, category?: TemplateCategory | 'all'): Promise<TemplateInfo[]>;
102
108
 
103
109
  declare function readConfig(): Promise<Config>;
104
110
  declare function writeConfig(config: Config): Promise<void>;
@@ -107,6 +113,34 @@ declare function getConfigValue(key: string): Promise<string | undefined>;
107
113
  /** Whether system-audience content should be shown (config `showSystem` set to true or "true"). */
108
114
  declare function showSystemEnabled(): Promise<boolean>;
109
115
 
116
+ type MetaKind = (typeof META_KINDS)[number];
117
+ type Collection = Pick<CollectionEntry, 'name' | 'path'>;
118
+ interface MetaResult {
119
+ created: string[];
120
+ kept: string[];
121
+ index_paths: string[];
122
+ warnings: string[];
123
+ errors: string[];
124
+ }
125
+ interface MetaRecordResult {
126
+ id: string;
127
+ path: string;
128
+ target: string;
129
+ mirror_path?: string;
130
+ index_paths: string[];
131
+ }
132
+ declare const META_KINDS: readonly ["history", "external-source-extract", "dream-learning"];
133
+ /** Exact file identity; unlike article titles, this must never be slugified. */
134
+ declare function validateMetaArticlePath(file: string): string;
135
+ declare function ensureCollectionMeta(entry: Collection): Promise<string>;
136
+ declare function ensureArticleMeta(entry: Collection, articlePath: string): Promise<string>;
137
+ /** A successful article write must remain visible when its mirror cannot be saved. */
138
+ declare function mirrorSavedArticle(entry: Collection, file: string): Promise<void>;
139
+ /** Rebuild only generated listings. Raw records are ordinary user-editable files. */
140
+ declare function reindexMeta(collection?: string): Promise<MetaResult>;
141
+ declare function initMeta(entries: Collection[]): Promise<MetaResult>;
142
+ declare function createMetaRecord(entry: Collection, articlePath: string | undefined, kind: MetaKind, body: string): Promise<MetaRecordResult>;
143
+
110
144
  declare function readRegistry(): Promise<Registry>;
111
145
  declare function writeRegistry(registry: Registry): Promise<void>;
112
146
  /** Insert or replace the entry with the same name. */
@@ -148,13 +182,22 @@ declare function createArticle(opts: {
148
182
  audience?: Audience;
149
183
  status?: PublishStatus;
150
184
  }): Promise<Article>;
185
+ interface ArticleUpdates {
186
+ title?: string;
187
+ body?: string;
188
+ tags?: string[];
189
+ audience?: Audience;
190
+ status?: PublishStatus;
191
+ }
192
+ /** Compose requested edits once so title/body/meta combinations retain unrelated fields. */
193
+ declare function updateArticle(target: string, updates: ArticleUpdates): Promise<Article>;
151
194
  declare function updateArticleBody(target: string, body: string): Promise<Article>;
152
195
  declare function addTags(target: string, tags: string[]): Promise<Article>;
153
196
  declare function removeTags(target: string, tags: string[]): Promise<Article>;
154
197
  declare function setTags(target: string, tags: string[]): Promise<Article>;
155
198
  /**
156
199
  * Set an article's audience and/or status. Unspecified axes are left as-is; the
157
- * serializer drops frontmatter for default values (public/published), so setting
200
+ * writer drops frontmatter for default values (public/published), so setting
158
201
  * an axis back to its default cleans it out of the file.
159
202
  */
160
203
  declare function setArticleMeta(target: string, meta: {
@@ -803,4 +846,4 @@ declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<Plu
803
846
  /** Find a plugin record by name (regardless of enabled state). */
804
847
  declare function findPluginRecord(name: string): Promise<PluginRecord | undefined>;
805
848
 
806
- export { type AddExternalOptions, Article, ArticleContent, ArticleNode, ArticleNotFoundError, Audience, CollectionAlreadyAddedError, CollectionEntry, CollectionExistsError, type CollectionGitStatus, CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, CollectionTree, Config, Diagnostic, DiffwikiError, type DiffwikiLogLevel, type EditTarget, type FileTimestamps, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, LinkGraph, type LintFileResult, type LintFinding, type LintLevel, type LintResult, LocalGraph, NoDefaultCollectionError, PROJECT_CONFIG_FILE, PageData, ParsedArticle, PluginError, PluginEvent, PluginKind, PluginRecord, PluginRegistryFile, ProjectConfig, PublishStatus, QueryHit, QueryOptions, REPO_CONFIG_FILE, Registry, type RenderContext, type RenderedArticle, RepoConfig, SearchDoc, SearchMode, type SearchOutcome, SearchProvider, type SeedResult, type SetupOutcome, type SetupStep, SiteConfig, type TemplateInfo, TocItem, TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensureHome, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, lintArticle, lintCollections, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, listTemplateShapes, listTemplates, loadSearchProvider, localGraph, nativeSearch, parseAddTarget, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readContextCollections, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repairPlugins, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, seedTemplates, setArticleMeta, setConfigValue, setContextCollections, setTags, showSystemEnabled, slugify, slugifyPath, templatesDir, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
849
+ export { type AddExternalOptions, Article, ArticleContent, ArticleNode, ArticleNotFoundError, type ArticleUpdates, Audience, CollectionAlreadyAddedError, CollectionEntry, CollectionExistsError, type CollectionGitStatus, CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, CollectionTree, Config, Diagnostic, DiffwikiError, type DiffwikiLogLevel, type EditTarget, type FileTimestamps, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, LinkGraph, type LintFileResult, type LintFinding, type LintLevel, type LintResult, LocalGraph, META_KINDS, type MetaKind, type MetaRecordResult, type MetaResult, NoDefaultCollectionError, PROJECT_CONFIG_FILE, PageData, ParsedArticle, PluginError, PluginEvent, PluginKind, PluginRecord, PluginRegistryFile, ProjectConfig, PublishStatus, QueryHit, QueryOptions, REPO_CONFIG_FILE, Registry, type RenderContext, type RenderedArticle, RepoConfig, SearchDoc, SearchMode, type SearchOutcome, SearchProvider, type SeedResult, type SetupOutcome, type SetupStep, SiteConfig, type TemplateCategory, type TemplateInfo, TocItem, TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, createMetaRecord, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureArticleMeta, ensureCollectionMeta, ensureGitRepo, ensureHome, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initMeta, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, lintArticle, lintCollections, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, listTemplateShapes, listTemplates, loadSearchProvider, localGraph, metaDir, mirrorSavedArticle, nativeSearch, parseAddTarget, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readContextCollections, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, reindexMeta, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repairPlugins, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, seedTemplates, setArticleMeta, setConfigValue, setContextCollections, setTags, showSystemEnabled, slugify, slugifyPath, templatesDir, toTreeNodes, unregisterCollection, updateArticle, updateArticleBody, upsertPlugin, upstreamStatus, validateMetaArticlePath, writeConfig, writePluginRegistry, writeRegistry };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Config, R as Registry, a as CollectionEntry, A as Audience, b as Article, P as PublishStatus, c as RepoConfig, d as ProjectConfig, S as SiteConfig, e as CollectionInfo, f as CollectionTree, g as PageData, h as ArticleNode, T as TreeNode, Q as QueryHit, i as QueryOptions, D as Diagnostic, j as ParsedArticle, k as ArticleContent, l as TocItem, L as LinkGraph, m as LocalGraph, n as SearchMode, o as SearchProvider, p as PluginRecord, q as PluginEvent, r as PluginKind, s as PluginRegistryFile } from './frontmatter-ghMCpLNf.js';
2
- export { t as CollectionType, u as DiagnosticLevel, v as DocData, G as GraphEdge, w as GraphNode, H as HomeCard, x as ListingEntry, N as NATIVE_ENGINE, y as NodeMeta, z as PluginCapabilities, B as PluginHealth, E as PluginReadiness, F as ProjectCollection, I as ProjectContext, J as SearchExpansion, K as SerializableArticle, M as SiteCopyright, O as SiteHome, U as parseArticle, V as parseFrontmatter, W as serializeArticle, X as stripFrontmatter } from './frontmatter-ghMCpLNf.js';
1
+ import { C as Config, a as CollectionEntry, R as Registry, A as Audience, P as PublishStatus, b as Article, c as RepoConfig, d as ProjectConfig, S as SiteConfig, e as CollectionInfo, f as CollectionTree, g as PageData, h as ArticleNode, T as TreeNode, Q as QueryHit, i as QueryOptions, D as Diagnostic, j as ParsedArticle, k as ArticleContent, l as TocItem, L as LinkGraph, m as LocalGraph, n as SearchMode, o as SearchProvider, p as PluginRecord, q as PluginEvent, r as PluginKind, s as PluginRegistryFile } from './frontmatter-D7gO1fg4.js';
2
+ export { t as CollectionType, u as DiagnosticLevel, v as DocData, G as GraphEdge, w as GraphNode, H as HomeCard, x as ListingEntry, N as NATIVE_ENGINE, y as NodeMeta, z as PluginCapabilities, B as PluginHealth, E as PluginReadiness, F as ProjectCollection, I as ProjectContext, J as SearchExpansion, K as SerializableArticle, M as SiteCopyright, O as SiteHome, U as parseArticle, V as parseFrontmatter, W as patchArticle, X as serializeArticle, Y as stripFrontmatter } from './frontmatter-D7gO1fg4.js';
3
3
  import { SearchDoc } from './bm25.js';
4
4
  export { RankableFields, rankDocs, tokenize } from './bm25.js';
5
5
  import { LogLevel, Logger } from '@logtape/logtape';
@@ -42,6 +42,8 @@ declare function configPath(): string;
42
42
  declare function collectionsDir(): string;
43
43
  /** Where authoring templates live (user-overridable), seeded by `diffwiki templates init`. */
44
44
  declare function templatesDir(): string;
45
+ /** Raw source records and per-article source manifests. */
46
+ declare function metaDir(): string;
45
47
  declare function collectionDir(name: string): string;
46
48
  declare function pluginsDir(): string;
47
49
  declare function pluginsRegistryPath(): string;
@@ -80,6 +82,7 @@ interface SeedResult {
80
82
  declare function seedTemplates(srcDir: string): Promise<SeedResult>;
81
83
  /** The template shape names bundled at `srcDir`, e.g. `['guide', 'recipe', …]`. */
82
84
  declare function listTemplateShapes(srcDir: string): Promise<string[]>;
85
+ type TemplateCategory = 'article' | 'meta';
83
86
  /** A template's self-describing metadata, read from its frontmatter. */
84
87
  interface TemplateInfo {
85
88
  /** The shape id (frontmatter `shape:`, else the filename stem). */
@@ -90,6 +93,9 @@ interface TemplateInfo {
90
93
  budget?: [number, number];
91
94
  /** The template file name. */
92
95
  file: string;
96
+ /** Effective user override or bundled file. */
97
+ path: string;
98
+ category: TemplateCategory;
93
99
  }
94
100
  /**
95
101
  * List the templates bundled at `srcDir` with their self-describing metadata
@@ -98,7 +104,7 @@ interface TemplateInfo {
98
104
  * hard-coding shape names, so dropping in a template with frontmatter
99
105
  * makes it discoverable. Falls back to the filename stem when `shape:` is absent.
100
106
  */
101
- declare function listTemplates(srcDir: string): Promise<TemplateInfo[]>;
107
+ declare function listTemplates(srcDir: string, category?: TemplateCategory | 'all'): Promise<TemplateInfo[]>;
102
108
 
103
109
  declare function readConfig(): Promise<Config>;
104
110
  declare function writeConfig(config: Config): Promise<void>;
@@ -107,6 +113,34 @@ declare function getConfigValue(key: string): Promise<string | undefined>;
107
113
  /** Whether system-audience content should be shown (config `showSystem` set to true or "true"). */
108
114
  declare function showSystemEnabled(): Promise<boolean>;
109
115
 
116
+ type MetaKind = (typeof META_KINDS)[number];
117
+ type Collection = Pick<CollectionEntry, 'name' | 'path'>;
118
+ interface MetaResult {
119
+ created: string[];
120
+ kept: string[];
121
+ index_paths: string[];
122
+ warnings: string[];
123
+ errors: string[];
124
+ }
125
+ interface MetaRecordResult {
126
+ id: string;
127
+ path: string;
128
+ target: string;
129
+ mirror_path?: string;
130
+ index_paths: string[];
131
+ }
132
+ declare const META_KINDS: readonly ["history", "external-source-extract", "dream-learning"];
133
+ /** Exact file identity; unlike article titles, this must never be slugified. */
134
+ declare function validateMetaArticlePath(file: string): string;
135
+ declare function ensureCollectionMeta(entry: Collection): Promise<string>;
136
+ declare function ensureArticleMeta(entry: Collection, articlePath: string): Promise<string>;
137
+ /** A successful article write must remain visible when its mirror cannot be saved. */
138
+ declare function mirrorSavedArticle(entry: Collection, file: string): Promise<void>;
139
+ /** Rebuild only generated listings. Raw records are ordinary user-editable files. */
140
+ declare function reindexMeta(collection?: string): Promise<MetaResult>;
141
+ declare function initMeta(entries: Collection[]): Promise<MetaResult>;
142
+ declare function createMetaRecord(entry: Collection, articlePath: string | undefined, kind: MetaKind, body: string): Promise<MetaRecordResult>;
143
+
110
144
  declare function readRegistry(): Promise<Registry>;
111
145
  declare function writeRegistry(registry: Registry): Promise<void>;
112
146
  /** Insert or replace the entry with the same name. */
@@ -148,13 +182,22 @@ declare function createArticle(opts: {
148
182
  audience?: Audience;
149
183
  status?: PublishStatus;
150
184
  }): Promise<Article>;
185
+ interface ArticleUpdates {
186
+ title?: string;
187
+ body?: string;
188
+ tags?: string[];
189
+ audience?: Audience;
190
+ status?: PublishStatus;
191
+ }
192
+ /** Compose requested edits once so title/body/meta combinations retain unrelated fields. */
193
+ declare function updateArticle(target: string, updates: ArticleUpdates): Promise<Article>;
151
194
  declare function updateArticleBody(target: string, body: string): Promise<Article>;
152
195
  declare function addTags(target: string, tags: string[]): Promise<Article>;
153
196
  declare function removeTags(target: string, tags: string[]): Promise<Article>;
154
197
  declare function setTags(target: string, tags: string[]): Promise<Article>;
155
198
  /**
156
199
  * Set an article's audience and/or status. Unspecified axes are left as-is; the
157
- * serializer drops frontmatter for default values (public/published), so setting
200
+ * writer drops frontmatter for default values (public/published), so setting
158
201
  * an axis back to its default cleans it out of the file.
159
202
  */
160
203
  declare function setArticleMeta(target: string, meta: {
@@ -803,4 +846,4 @@ declare function findEnabledPlugin(kind: PluginKind, name?: string): Promise<Plu
803
846
  /** Find a plugin record by name (regardless of enabled state). */
804
847
  declare function findPluginRecord(name: string): Promise<PluginRecord | undefined>;
805
848
 
806
- export { type AddExternalOptions, Article, ArticleContent, ArticleNode, ArticleNotFoundError, Audience, CollectionAlreadyAddedError, CollectionEntry, CollectionExistsError, type CollectionGitStatus, CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, CollectionTree, Config, Diagnostic, DiffwikiError, type DiffwikiLogLevel, type EditTarget, type FileTimestamps, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, LinkGraph, type LintFileResult, type LintFinding, type LintLevel, type LintResult, LocalGraph, NoDefaultCollectionError, PROJECT_CONFIG_FILE, PageData, ParsedArticle, PluginError, PluginEvent, PluginKind, PluginRecord, PluginRegistryFile, ProjectConfig, PublishStatus, QueryHit, QueryOptions, REPO_CONFIG_FILE, Registry, type RenderContext, type RenderedArticle, RepoConfig, SearchDoc, SearchMode, type SearchOutcome, SearchProvider, type SeedResult, type SetupOutcome, type SetupStep, SiteConfig, type TemplateInfo, TocItem, TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureGitRepo, ensureHome, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, lintArticle, lintCollections, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, listTemplateShapes, listTemplates, loadSearchProvider, localGraph, nativeSearch, parseAddTarget, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readContextCollections, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repairPlugins, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, seedTemplates, setArticleMeta, setConfigValue, setContextCollections, setTags, showSystemEnabled, slugify, slugifyPath, templatesDir, toTreeNodes, unregisterCollection, updateArticleBody, upsertPlugin, upstreamStatus, writeConfig, writePluginRegistry, writeRegistry };
849
+ export { type AddExternalOptions, Article, ArticleContent, ArticleNode, ArticleNotFoundError, type ArticleUpdates, Audience, CollectionAlreadyAddedError, CollectionEntry, CollectionExistsError, type CollectionGitStatus, CollectionInfo, CollectionNotFoundError, type CollectionSelection, type CollectionSelectionResult, CollectionTree, Config, Diagnostic, DiffwikiError, type DiffwikiLogLevel, type EditTarget, type FileTimestamps, type InitOptions, type InstallOutcome, InvalidExportSelectionError, InvalidTargetError, type KnownPlugin, LinkGraph, type LintFileResult, type LintFinding, type LintLevel, type LintResult, LocalGraph, META_KINDS, type MetaKind, type MetaRecordResult, type MetaResult, NoDefaultCollectionError, PROJECT_CONFIG_FILE, PageData, ParsedArticle, PluginError, PluginEvent, PluginKind, PluginRecord, PluginRegistryFile, ProjectConfig, PublishStatus, QueryHit, QueryOptions, REPO_CONFIG_FILE, Registry, type RenderContext, type RenderedArticle, RepoConfig, SearchDoc, SearchMode, type SearchOutcome, SearchProvider, type SeedResult, type SetupOutcome, type SetupStep, SiteConfig, type TemplateCategory, type TemplateInfo, TocItem, TreeNode, type UpstreamStatus, WorktreeNotAllowedError, addExternalCollection, addTags, buildArticleTree, buildCollections, buildLinkGraph, buildNavTree, buildSearchIndex, buildSiteConfig, collectionDir, collectionGitStatus, collectionMeta, collectionsDir, configPath, createArticle, createCollection, createMetaRecord, currentBranch, deregisterPlugin, doctor, emitPluginEvent, ensureArticleMeta, ensureCollectionMeta, ensureGitRepo, ensureHome, ensurePluginRoot, fileTimestamps, findCollection, findCollectionById, findEnabledPlugin, findPluginRecord, getConfigValue, getLogger, gitToplevel, initMeta, initRepoWiki, installPlugin, invalidateLinkGraph, isLinkedWorktree, lintArticle, lintCollections, listArticleTree, listAvailablePlugins, listCollections, listEnabledPlugins, listPlugins, listSearchModes, listTemplateShapes, listTemplates, loadSearchProvider, localGraph, metaDir, mirrorSavedArticle, nativeSearch, parseAddTarget, parsePathTarget, pluginsDir, pluginsRegistryPath, query, readArticle, readConfig, readContextCollections, readPluginRegistry, readProjectConfig, readRegistry, readRepoConfig, readSiteConfig, registerCollection, registerPlugin, registryPath, reindexMeta, removeArticle, removeCollection, removePlugin, removeTags, renderArticle, repairPlugins, repoId, repoRemoteName, resolveCollectionSelection, resolveCwdCollection, resolveDefaultSearchMode, resolveEditTarget, resolveEditorCommand, resolveHome, resolveLogLevel, resolvePage, resolveProjectCollections, search, seedProjectHome, seedTemplates, setArticleMeta, setConfigValue, setContextCollections, setTags, showSystemEnabled, slugify, slugifyPath, templatesDir, toTreeNodes, unregisterCollection, updateArticle, updateArticleBody, upsertPlugin, upstreamStatus, validateMetaArticlePath, writeConfig, writePluginRegistry, writeRegistry };
package/dist/index.js CHANGED
@@ -5,54 +5,66 @@ import {
5
5
  import {
6
6
  parseArticle,
7
7
  parseFrontmatter,
8
+ patchArticle,
8
9
  runProcess,
9
10
  serializeArticle,
10
11
  stripFrontmatter
11
- } from "./chunk-6MW6KSS4.js";
12
+ } from "./chunk-NLBHSMHA.js";
12
13
  import {
13
- ArticleNotFoundError,
14
- CollectionAlreadyAddedError,
15
- CollectionExistsError,
16
- CollectionNotFoundError,
17
- DiffwikiError,
18
- InvalidExportSelectionError,
19
- InvalidTargetError,
20
14
  LONG_TIMEOUT_MS,
15
+ META_KINDS,
21
16
  NATIVE_ENGINE,
22
- NoDefaultCollectionError,
23
- PluginError,
24
- WorktreeNotAllowedError,
25
17
  collectionDir,
26
18
  collectionsDir,
27
19
  configPath,
28
20
  createCollection,
21
+ createMetaRecord,
29
22
  deregisterPlugin,
30
23
  emitPluginEvent,
24
+ ensureArticleMeta,
25
+ ensureCollectionMeta,
31
26
  findCollection,
32
27
  findCollectionById,
33
28
  findEnabledPlugin,
34
29
  findPluginRecord,
35
30
  getLogger,
31
+ initMeta,
36
32
  invokePlugin,
37
33
  listCollections,
38
34
  listEnabledPlugins,
39
35
  listSearchModes,
40
36
  loadSearchProvider,
37
+ metaDir,
38
+ mirrorSavedArticle,
41
39
  pluginsDir,
42
40
  pluginsRegistryPath,
43
41
  readPluginRegistry,
44
42
  readRegistry,
45
43
  registerCollection,
46
44
  registryPath,
45
+ reindexMeta,
47
46
  removeCollection,
48
47
  resolveHome,
49
48
  resolveLogLevel,
50
49
  templatesDir,
51
50
  unregisterCollection,
52
51
  upsertPlugin,
52
+ validateMetaArticlePath,
53
53
  writePluginRegistry,
54
54
  writeRegistry
55
- } from "./chunk-TXM4OGBA.js";
55
+ } from "./chunk-KUX7GHHM.js";
56
+ import {
57
+ ArticleNotFoundError,
58
+ CollectionAlreadyAddedError,
59
+ CollectionExistsError,
60
+ CollectionNotFoundError,
61
+ DiffwikiError,
62
+ InvalidExportSelectionError,
63
+ InvalidTargetError,
64
+ NoDefaultCollectionError,
65
+ PluginError,
66
+ WorktreeNotAllowedError
67
+ } from "./chunk-FJ5XD2JN.js";
56
68
 
57
69
  // src/home.ts
58
70
  import fs from "fs/promises";
@@ -98,22 +110,34 @@ async function seedTemplates(srcDir) {
98
110
  return { seeded, skipped, dir };
99
111
  }
100
112
  async function listTemplateShapes(srcDir) {
101
- const files = await fs2.readdir(srcDir);
102
- return files.filter((f) => f.endsWith("-template.md")).map((f) => f.replace(/-template\.md$/, "")).sort();
113
+ return (await listTemplates(srcDir)).map((info) => info.shape).sort();
103
114
  }
104
- async function listTemplates(srcDir) {
105
- const files = (await fs2.readdir(srcDir)).filter((f) => f.endsWith("-template.md")).sort();
115
+ async function listTemplates(srcDir, category = "article") {
116
+ const files = /* @__PURE__ */ new Map();
117
+ for (const dir of [srcDir, templatesDir()]) {
118
+ let names;
119
+ try {
120
+ names = await fs2.readdir(dir);
121
+ } catch (err) {
122
+ if (err.code === "ENOENT") continue;
123
+ throw err;
124
+ }
125
+ for (const name of names.filter((name2) => name2.endsWith("-template.md")).sort())
126
+ files.set(name, path.resolve(dir, name));
127
+ }
106
128
  const out = [];
107
- for (const file of files) {
129
+ for (const [file, filePath] of [...files].sort(([a], [b]) => a.localeCompare(b))) {
108
130
  let data = {};
109
131
  try {
110
- ({ data } = parseFrontmatter(await fs2.readFile(path.join(srcDir, file), "utf8")));
132
+ ({ data } = parseFrontmatter(await fs2.readFile(filePath, "utf8")));
111
133
  } catch {
112
134
  }
113
135
  const shape = typeof data.shape === "string" && data.shape ? data.shape : file.replace(/-template\.md$/, "");
114
136
  const purpose = typeof data.purpose === "string" ? data.purpose : "";
115
137
  const budget = Array.isArray(data.budget) && data.budget.length === 2 ? [Number(data.budget[0]), Number(data.budget[1])] : void 0;
116
- out.push({ shape, purpose, budget, file });
138
+ const templateCategory = data.category === "meta" ? "meta" : "article";
139
+ if (category === "all" || category === templateCategory)
140
+ out.push({ shape, purpose, budget, file, path: filePath, category: templateCategory });
117
141
  }
118
142
  return out;
119
143
  }
@@ -180,7 +204,7 @@ import fs4 from "fs/promises";
180
204
  import path2 from "path";
181
205
  async function fireHook(event, collection, relPath) {
182
206
  try {
183
- const { emitPluginEvent: emitPluginEvent2 } = await import("./events-K3MKWACA.js");
207
+ const { emitPluginEvent: emitPluginEvent2 } = await import("./events-UG4JPZDZ.js");
184
208
  await emitPluginEvent2(event, collection, relPath);
185
209
  } catch {
186
210
  }
@@ -232,12 +256,13 @@ async function createArticle(opts) {
232
256
  "utf8"
233
257
  );
234
258
  void fireHook("article-created", name, path2.relative(dir, filePath));
259
+ await mirrorSavedArticle({ name, path: dir }, filePath);
235
260
  return { title, tags: opts.tags, path: filePath, collection: name };
236
261
  }
237
262
  async function loadArticle(target) {
238
263
  const { collection, file } = parsePathTarget(target);
239
264
  const { dir } = await resolveCollectionDir(collection);
240
- const filePath = path2.join(dir, ensureMdPath(file));
265
+ const filePath = path2.join(dir, validateMetaArticlePath(ensureMdPath(file)));
241
266
  try {
242
267
  return { filePath, dir, raw: await fs4.readFile(filePath, "utf8"), collection };
243
268
  } catch (err) {
@@ -245,40 +270,29 @@ async function loadArticle(target) {
245
270
  throw err;
246
271
  }
247
272
  }
248
- async function updateArticleBody(target, body) {
273
+ async function updateArticle(target, updates) {
249
274
  const { filePath, dir, raw, collection } = await loadArticle(target);
250
- const parsed = parseArticle(raw);
251
- await fs4.writeFile(
252
- filePath,
253
- serializeArticle({
254
- title: parsed.title,
255
- tags: parsed.tags,
256
- audience: parsed.audience,
257
- status: parsed.status,
258
- body
259
- }),
260
- "utf8"
261
- );
275
+ if (updates.title !== void 0 && !updates.title.trim())
276
+ throw new InvalidTargetError(updates.title, "title cannot be empty");
277
+ const fields = {};
278
+ if (updates.title !== void 0) fields.title = updates.title;
279
+ if (updates.tags !== void 0) fields.tags = Array.from(new Set(updates.tags));
280
+ if (updates.audience !== void 0) fields.audience = updates.audience === "public" ? void 0 : updates.audience;
281
+ if (updates.status !== void 0) fields.status = updates.status === "published" ? void 0 : updates.status;
282
+ const next = patchArticle(raw, fields, updates.body);
283
+ await fs4.writeFile(filePath, next, "utf8");
284
+ const parsed = parseArticle(next);
262
285
  void fireHook("article-updated", collection, path2.relative(dir, filePath));
286
+ await mirrorSavedArticle({ name: collection, path: dir }, filePath);
263
287
  return { title: parsed.title, tags: parsed.tags, path: filePath, collection };
264
288
  }
289
+ function updateArticleBody(target, body) {
290
+ return updateArticle(target, { body });
291
+ }
265
292
  async function mutateTags(target, fn) {
266
- const { filePath, dir, raw, collection } = await loadArticle(target);
293
+ const { raw } = await loadArticle(target);
267
294
  const parsed = parseArticle(raw);
268
- const tags = fn(parsed.tags);
269
- await fs4.writeFile(
270
- filePath,
271
- serializeArticle({
272
- title: parsed.title,
273
- tags,
274
- audience: parsed.audience,
275
- status: parsed.status,
276
- body: parsed.body
277
- }),
278
- "utf8"
279
- );
280
- void fireHook("article-updated", collection, path2.relative(dir, filePath));
281
- return { title: parsed.title, tags, path: filePath, collection };
295
+ return updateArticle(target, { tags: fn(parsed.tags) });
282
296
  }
283
297
  function addTags(target, tags) {
284
298
  return mutateTags(target, (current) => Array.from(/* @__PURE__ */ new Set([...current, ...tags])));
@@ -291,17 +305,7 @@ function setTags(target, tags) {
291
305
  return mutateTags(target, () => Array.from(new Set(tags)));
292
306
  }
293
307
  async function setArticleMeta(target, meta) {
294
- const { filePath, dir, raw, collection } = await loadArticle(target);
295
- const parsed = parseArticle(raw);
296
- const audience = meta.audience ?? parsed.audience;
297
- const status = meta.status ?? parsed.status;
298
- await fs4.writeFile(
299
- filePath,
300
- serializeArticle({ title: parsed.title, tags: parsed.tags, audience, status, body: parsed.body }),
301
- "utf8"
302
- );
303
- void fireHook("article-updated", collection, path2.relative(dir, filePath));
304
- return { title: parsed.title, tags: parsed.tags, path: filePath, collection };
308
+ return updateArticle(target, meta);
305
309
  }
306
310
  async function removeArticle(target) {
307
311
  const { filePath, dir, collection } = await loadArticle(target);
@@ -2023,6 +2027,7 @@ export {
2023
2027
  DiffwikiError,
2024
2028
  InvalidExportSelectionError,
2025
2029
  InvalidTargetError,
2030
+ META_KINDS,
2026
2031
  NATIVE_ENGINE,
2027
2032
  NoDefaultCollectionError,
2028
2033
  PROJECT_CONFIG_FILE,
@@ -2044,10 +2049,13 @@ export {
2044
2049
  configPath,
2045
2050
  createArticle,
2046
2051
  createCollection,
2052
+ createMetaRecord,
2047
2053
  currentBranch,
2048
2054
  deregisterPlugin,
2049
2055
  doctor,
2050
2056
  emitPluginEvent,
2057
+ ensureArticleMeta,
2058
+ ensureCollectionMeta,
2051
2059
  ensureGitRepo,
2052
2060
  ensureHome,
2053
2061
  ensurePluginRoot,
@@ -2059,6 +2067,7 @@ export {
2059
2067
  getConfigValue,
2060
2068
  getLogger,
2061
2069
  gitToplevel,
2070
+ initMeta,
2062
2071
  initRepoWiki,
2063
2072
  installPlugin,
2064
2073
  invalidateLinkGraph,
@@ -2075,11 +2084,14 @@ export {
2075
2084
  listTemplates,
2076
2085
  loadSearchProvider,
2077
2086
  localGraph,
2087
+ metaDir,
2088
+ mirrorSavedArticle,
2078
2089
  nativeSearch,
2079
2090
  parseAddTarget,
2080
2091
  parseArticle,
2081
2092
  parseFrontmatter,
2082
2093
  parsePathTarget,
2094
+ patchArticle,
2083
2095
  pluginsDir,
2084
2096
  pluginsRegistryPath,
2085
2097
  query,
@@ -2095,6 +2107,7 @@ export {
2095
2107
  registerCollection,
2096
2108
  registerPlugin,
2097
2109
  registryPath,
2110
+ reindexMeta,
2098
2111
  removeArticle,
2099
2112
  removeCollection,
2100
2113
  removePlugin,
@@ -2128,9 +2141,11 @@ export {
2128
2141
  toTreeNodes,
2129
2142
  tokenize,
2130
2143
  unregisterCollection,
2144
+ updateArticle,
2131
2145
  updateArticleBody,
2132
2146
  upsertPlugin,
2133
2147
  upstreamStatus,
2148
+ validateMetaArticlePath,
2134
2149
  writeConfig,
2135
2150
  writePluginRegistry,
2136
2151
  writeRegistry
package/dist/plugin.cjs CHANGED
@@ -53,7 +53,7 @@ var import_gray_matter = __toESM(require("gray-matter"), 1);
53
53
  var import_yaml = require("yaml");
54
54
  var YAML_ENGINE = {
55
55
  parse: (input) => {
56
- const data = (0, import_yaml.parse)(input);
56
+ const data = (0, import_yaml.parse)(input.replace(/\r\n?/g, "\n"));
57
57
  return data && typeof data === "object" ? data : {};
58
58
  },
59
59
  stringify: (data) => (0, import_yaml.stringify)(data)
package/dist/plugin.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { Y as PluginDefinition, Z as DefinedPlugin, _ as PluginDependency, $ as ResolvedDependency, a0 as RunProcessOptions } from './frontmatter-ghMCpLNf.cjs';
2
- export { a1 as EventHandlerResult, a2 as EventParams, a3 as HealthHandlerResult, a4 as HealthParams, a5 as IndexHandlerResult, a6 as IndexParams, a7 as LogLevel, j as ParsedArticle, a8 as PluginCapabilities, a9 as PluginHandlers, aa as PluginLogFn, J as SearchExpansion, ab as SearchHandlerHit, ac as SearchHandlerResult, ad as SearchParams, ae as SetupHandlerResult, af as SetupParams, ag as WireCollection, ah as WireDiagnostic, ai as WireReadiness, U as parseArticle, X as stripFrontmatter } from './frontmatter-ghMCpLNf.cjs';
1
+ import { Z as PluginDefinition, _ as DefinedPlugin, $ as PluginDependency, a0 as ResolvedDependency, a1 as RunProcessOptions } from './frontmatter-D7gO1fg4.cjs';
2
+ export { a2 as EventHandlerResult, a3 as EventParams, a4 as HealthHandlerResult, a5 as HealthParams, a6 as IndexHandlerResult, a7 as IndexParams, a8 as LogLevel, j as ParsedArticle, a9 as PluginCapabilities, aa as PluginHandlers, ab as PluginLogFn, J as SearchExpansion, ac as SearchHandlerHit, ad as SearchHandlerResult, ae as SearchParams, af as SetupHandlerResult, ag as SetupParams, ah as WireCollection, ai as WireDiagnostic, aj as WireReadiness, U as parseArticle, Y as stripFrontmatter } from './frontmatter-D7gO1fg4.cjs';
3
3
 
4
4
  /**
5
5
  * diffwiki plugin authoring SDK — the public surface for plugin authors, imported
package/dist/plugin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Y as PluginDefinition, Z as DefinedPlugin, _ as PluginDependency, $ as ResolvedDependency, a0 as RunProcessOptions } from './frontmatter-ghMCpLNf.js';
2
- export { a1 as EventHandlerResult, a2 as EventParams, a3 as HealthHandlerResult, a4 as HealthParams, a5 as IndexHandlerResult, a6 as IndexParams, a7 as LogLevel, j as ParsedArticle, a8 as PluginCapabilities, a9 as PluginHandlers, aa as PluginLogFn, J as SearchExpansion, ab as SearchHandlerHit, ac as SearchHandlerResult, ad as SearchParams, ae as SetupHandlerResult, af as SetupParams, ag as WireCollection, ah as WireDiagnostic, ai as WireReadiness, U as parseArticle, X as stripFrontmatter } from './frontmatter-ghMCpLNf.js';
1
+ import { Z as PluginDefinition, _ as DefinedPlugin, $ as PluginDependency, a0 as ResolvedDependency, a1 as RunProcessOptions } from './frontmatter-D7gO1fg4.js';
2
+ export { a2 as EventHandlerResult, a3 as EventParams, a4 as HealthHandlerResult, a5 as HealthParams, a6 as IndexHandlerResult, a7 as IndexParams, a8 as LogLevel, j as ParsedArticle, a9 as PluginCapabilities, aa as PluginHandlers, ab as PluginLogFn, J as SearchExpansion, ac as SearchHandlerHit, ad as SearchHandlerResult, ae as SearchParams, af as SetupHandlerResult, ag as SetupParams, ah as WireCollection, ai as WireDiagnostic, aj as WireReadiness, U as parseArticle, Y as stripFrontmatter } from './frontmatter-D7gO1fg4.js';
3
3
 
4
4
  /**
5
5
  * diffwiki plugin authoring SDK — the public surface for plugin authors, imported
package/dist/plugin.js CHANGED
@@ -7,7 +7,8 @@ import {
7
7
  runProcess,
8
8
  runProcessJson,
9
9
  stripFrontmatter
10
- } from "./chunk-6MW6KSS4.js";
10
+ } from "./chunk-NLBHSMHA.js";
11
+ import "./chunk-FJ5XD2JN.js";
11
12
  export {
12
13
  commandExists,
13
14
  definePlugin,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diffwiki-core",
3
- "version": "0.17.3",
3
+ "version": "0.18.0",
4
4
  "description": "Core configuration, registry, and article management for diffwiki",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,6 +0,0 @@
1
- import {
2
- emitPluginEvent
3
- } from "./chunk-TXM4OGBA.js";
4
- export {
5
- emitPluginEvent
6
- };