@riebeckite/plugin-daily-notes 0.0.14 → 0.0.16

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/README.md CHANGED
@@ -52,9 +52,15 @@ getDailyNotes({
52
52
  manifest,
53
53
  config,
54
54
  options: {
55
- source: { directory: "Daily", pathPattern: "Daily/{YYYY}-{MM}-{DD}" },
55
+ source: {
56
+ directory: "Daily",
57
+ pathPattern: "Daily/{YYYY}-{MM}-{DD}",
58
+ dateFormat: "YYYY/MM/DD",
59
+ },
56
60
  extract: { frontmatter: "daily-summary", section: "今日のひとこと" },
57
61
  widget: { limit: 3 },
62
+ dateFormat: "iso",
63
+ locale: "en",
58
64
  },
59
65
  });
60
66
  ```
@@ -62,13 +68,31 @@ getDailyNotes({
62
68
  Set a strategy to `false` to disable it. `pathPattern` supports `{YYYY}`,
63
69
  `{MM}`, `{DD}`, and `*` so a note filename can be matched precisely.
64
70
 
71
+ `source.dateFormat` is the Obsidian/Moment date format used by the note
72
+ filenames (default `YYYY-MM-DD`). Set it to match Obsidian's Daily Notes date
73
+ format (for example `YYYY/MM/DD` or `YYYY.MM.DD`); the slug date is read with
74
+ exactly that format, and an unsupported format resolves no date rather than
75
+ guessing another one.
76
+
77
+ `dateFormat` controls the widget date: `"iso"` (the default, `YYYY-MM-DD`),
78
+ `"long"`, or `"short"`. `"long"` and `"short"` are rendered with `locale`
79
+ (default `"en"`). The machine-readable `YYYY-MM-DD` value stays on the
80
+ `<time datetime>` attribute regardless, and `DailyNote.date` keeps that ISO
81
+ form while `DailyNote.dateDisplay` holds the formatted text.
82
+
65
83
  ## Exports
66
84
 
67
85
  - `dailyNotesPlugin(options?)` — plugin factory (registers `style.css`)
68
86
  - `getDailyNotes({ manifest, config, options? })` — sorted `DailyNote[]`
69
87
  - `DailyNotes` — widget component (`{ notes, limit? }`)
70
- - Types: `DailyNote`, `DailyNotesOptions`, `ResolvedDailyNotesExtract`
88
+ - `resolveDisplayOptions(options?)` — apply date-format defaults
89
+ - `formatDailyNoteDate(dateIso, display)` — pure date formatter
90
+ - Constants: `DEFAULT_DAILY_NOTES_DATE_FORMAT`, `DEFAULT_DAILY_NOTES_LOCALE`,
91
+ `DEFAULT_SLUG_DATE_FORMAT`
92
+ - Types: `DailyNote`, `DailyNotesOptions`, `DailyNotesDateFormat`,
93
+ `ResolvedDailyNotesExtract`, `ResolvedDailyNotesDisplay`
71
94
 
72
95
  ## See also
73
96
 
74
- - [Plugin guide](../../../docs/en/reference/plugin-api.md)
97
+ - [Plugin guide](../../../docs/en/docs/reference/plugin-api.md)
98
+
package/README_ja.md CHANGED
@@ -45,22 +45,36 @@ getDailyNotes({
45
45
  manifest,
46
46
  config,
47
47
  options: {
48
- source: { directory: "Daily", pathPattern: "Daily/{YYYY}-{MM}-{DD}" },
48
+ source: {
49
+ directory: "Daily",
50
+ pathPattern: "Daily/{YYYY}-{MM}-{DD}",
51
+ dateFormat: "YYYY/MM/DD",
52
+ },
49
53
  extract: { frontmatter: "daily-summary", section: "今日のひとこと" },
50
54
  widget: { limit: 3 },
55
+ dateFormat: "iso",
56
+ locale: "en",
51
57
  },
52
58
  });
53
59
  ```
54
60
 
55
61
  方法を `false` にすると、その抽出を無効にできます。`pathPattern` では `{YYYY}`、`{MM}`、`{DD}`、`*` が使え、ノートのファイル名を厳密に絞り込めます。
56
62
 
63
+ `source.dateFormat` はノートのファイル名が使う Obsidian(Moment)の日付フォーマットです(既定 `YYYY-MM-DD`)。Obsidian の Daily Notes の日付フォーマットに合わせて設定します(例: `YYYY/MM/DD`、`YYYY.MM.DD`)。slug の日付はこの形式ちょうどで読み取り、対応していない形式ではほかの形式を推測せず日付なしにします。
64
+
65
+ `dateFormat` はウィジェットの日付表示を決めます。既定は `"iso"`(`YYYY-MM-DD`)で、ほかに `"long"` と `"short"` があります。`"long"` と `"short"` は `locale`(既定 `"en"`)で整形します。機械可読な `YYYY-MM-DD` は常に `<time datetime>` 属性に残り、`DailyNote.date` はその ISO 形式のまま、`DailyNote.dateDisplay` に整形後の文字列が入ります。
66
+
57
67
  ## 主なエクスポート
58
68
 
59
69
  - `dailyNotesPlugin(options?)`: プラグインを作る(`style.css` を登録する)
60
70
  - `getDailyNotes({ manifest, config, options? })`: 並べ替え済みの `DailyNote[]` を返す
61
71
  - `DailyNotes`: ウィジェットのコンポーネント(`{ notes, limit? }`)
62
- - 型: `DailyNote`、`DailyNotesOptions`、`ResolvedDailyNotesExtract`
72
+ - `resolveDisplayOptions(options?)`: 日付表示の既定値を適用する
73
+ - `formatDailyNoteDate(dateIso, display)`: 純粋な日付整形関数
74
+ - 定数: `DEFAULT_DAILY_NOTES_DATE_FORMAT`、`DEFAULT_DAILY_NOTES_LOCALE`、`DEFAULT_SLUG_DATE_FORMAT`
75
+ - 型: `DailyNote`、`DailyNotesOptions`、`DailyNotesDateFormat`、`ResolvedDailyNotesExtract`、`ResolvedDailyNotesDisplay`
63
76
 
64
77
  ## 関連資料
65
78
 
66
- - [プラグインシステム](../../../docs/ja/reference/plugin-api.md)
79
+ - [プラグインシステム](../../../docs/ja/docs/reference/plugin-api.md)
80
+
@@ -13,11 +13,11 @@ function DailyNotes(props) {
13
13
  children: [
14
14
  /* @__PURE__ */ jsxs("div", { class: "daily-notes__header", children: [
15
15
  /* @__PURE__ */ jsx("p", { class: "daily-notes__eyebrow", children: "DAILY NOTES" }),
16
- /* @__PURE__ */ jsx("h2", { class: "daily-notes__title", id: "daily-notes-title", children: "最近のデイリーノート" })
16
+ /* @__PURE__ */ jsx("h2", { class: "daily-notes__title", id: "daily-notes-title", children: "Recent Daily Notes" })
17
17
  ] }),
18
18
  /* @__PURE__ */ jsx("ul", { class: "daily-notes__list", children: notes.map((note) => /* @__PURE__ */ jsxs("li", { class: "daily-notes__item", children: [
19
19
  /* @__PURE__ */ jsxs("div", { class: "daily-notes__meta", children: [
20
- note.date.length > 0 ? /* @__PURE__ */ jsx("time", { class: "daily-notes__date", dateTime: note.date, children: formatDisplayDate(note.date) }) : null,
20
+ note.date.length > 0 ? /* @__PURE__ */ jsx("time", { class: "daily-notes__date", dateTime: note.date, children: note.dateDisplay }) : null,
21
21
  note.sourceUrl !== null ? /* @__PURE__ */ jsx("a", { class: "daily-notes__source", href: note.sourceUrl, children: resolveSourceLabel(note) }) : null
22
22
  ] }),
23
23
  /* @__PURE__ */ jsx("p", { class: "daily-notes__snippet", children: note.snippet })
@@ -32,11 +32,6 @@ function resolveSourceLabel(note) {
32
32
  }
33
33
  return note.sourceUrl ?? "";
34
34
  }
35
- function formatDisplayDate(date) {
36
- const [year, month, day] = date.split("-");
37
- if (!year || !month || !day) return date;
38
- return `${year}年${Number(month)}月${Number(day)}日`;
39
- }
40
35
  export {
41
36
  DailyNotes as default
42
37
  };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { type RiebeckitePlugin } from "@riebeckite/core";
2
- import type { DailyNotesOptions } from "./src/daily-notes.js";
2
+ import { type DailyNotesOptions } from "./src/daily-notes.js";
3
3
  export { default as DailyNotes } from "./components/daily-notes.js";
4
- export type { DailyNote, DailyNotesOptions, ResolvedDailyNotesExtract, } from "./src/daily-notes.js";
5
- export { getDailyNotes } from "./src/daily-notes.server.js";
4
+ export type { DailyNote, DailyNotesDateFormat, DailyNotesOptions, ResolvedDailyNotesDisplay, ResolvedDailyNotesExtract, } from "./src/daily-notes.js";
5
+ export { DAILY_NOTES_PLUGIN_NAME, DEFAULT_DAILY_NOTES_DATE_FORMAT, DEFAULT_DAILY_NOTES_LOCALE, DEFAULT_SLUG_DATE_FORMAT, formatDailyNoteDate, resolveDisplayOptions, } from "./src/daily-notes.js";
6
+ export { getDailyNotes, resolveDailyNotesOptionsFromConfig, } from "./src/daily-notes.server.js";
6
7
  /**
7
8
  * Registers the Daily Notes widget. Extraction options are consumed by
8
- * `getDailyNotes`; the plugin itself only wires the stylesheet.
9
+ * `getDailyNotes`; the plugin wires the stylesheet and output dependencies.
9
10
  */
10
11
  export declare function dailyNotesPlugin(options?: DailyNotesOptions): RiebeckitePlugin<DailyNotesOptions | undefined>;
package/dist/index.js CHANGED
@@ -4,57 +4,16 @@ import {
4
4
  definePlugin
5
5
  } from "@riebeckite/core";
6
6
 
7
- // components/daily-notes.tsx
8
- import { jsx, jsxs } from "hono/jsx/jsx-runtime";
9
- var DEFAULT_LIMIT = 5;
10
- function DailyNotes(props) {
11
- const limit = props.limit ?? DEFAULT_LIMIT;
12
- const notes = props.notes.slice(0, Math.max(0, limit));
13
- if (notes.length === 0) return null;
14
- return /* @__PURE__ */ jsxs(
15
- "section",
16
- {
17
- class: "daily-notes rr-daily-notes",
18
- "aria-labelledby": "daily-notes-title",
19
- children: [
20
- /* @__PURE__ */ jsxs("div", { class: "daily-notes__header", children: [
21
- /* @__PURE__ */ jsx("p", { class: "daily-notes__eyebrow", children: "DAILY NOTES" }),
22
- /* @__PURE__ */ jsx("h2", { class: "daily-notes__title", id: "daily-notes-title", children: "最近のデイリーノート" })
23
- ] }),
24
- /* @__PURE__ */ jsx("ul", { class: "daily-notes__list", children: notes.map((note) => /* @__PURE__ */ jsxs("li", { class: "daily-notes__item", children: [
25
- /* @__PURE__ */ jsxs("div", { class: "daily-notes__meta", children: [
26
- note.date.length > 0 ? /* @__PURE__ */ jsx("time", { class: "daily-notes__date", dateTime: note.date, children: formatDisplayDate(note.date) }) : null,
27
- note.sourceUrl !== null ? /* @__PURE__ */ jsx("a", { class: "daily-notes__source", href: note.sourceUrl, children: resolveSourceLabel(note) }) : null
28
- ] }),
29
- /* @__PURE__ */ jsx("p", { class: "daily-notes__snippet", children: note.snippet })
30
- ] }, note.slug)) })
31
- ]
32
- }
33
- );
34
- }
35
- function resolveSourceLabel(note) {
36
- if (note.sourceTitle !== null && note.sourceTitle.length > 0) {
37
- return note.sourceTitle;
38
- }
39
- return note.sourceUrl ?? "";
40
- }
41
- function formatDisplayDate(date) {
42
- const [year, month, day] = date.split("-");
43
- if (!year || !month || !day) return date;
44
- return `${year}年${Number(month)}月${Number(day)}日`;
45
- }
46
-
47
- // src/daily-notes.server.ts
48
- import {
49
- isPublished
50
- } from "@riebeckite/core";
51
-
52
7
  // src/daily-notes.ts
8
+ var DAILY_NOTES_PLUGIN_NAME = "daily-notes";
53
9
  var DEFAULT_DIRECTORY = "Daily";
54
10
  var DEFAULT_FRONTMATTER_KEY = "daily-summary";
55
11
  var DEFAULT_SECTION = "今日のひとこと";
56
12
  var DEFAULT_CODE_BLOCK = "daily-snippet";
57
- var DEFAULT_LIMIT2 = 5;
13
+ var DEFAULT_LIMIT = 5;
14
+ var DEFAULT_DAILY_NOTES_DATE_FORMAT = "iso";
15
+ var DEFAULT_DAILY_NOTES_LOCALE = "en";
16
+ var DEFAULT_SLUG_DATE_FORMAT = "YYYY-MM-DD";
58
17
  function resolveExtractOptions(options) {
59
18
  const extract = options?.extract;
60
19
  return {
@@ -63,6 +22,22 @@ function resolveExtractOptions(options) {
63
22
  codeBlock: extract?.codeBlock === void 0 ? DEFAULT_CODE_BLOCK : extract.codeBlock
64
23
  };
65
24
  }
25
+ function resolveDisplayOptions(options) {
26
+ const locale = options?.locale;
27
+ return {
28
+ dateFormat: options?.dateFormat ?? DEFAULT_DAILY_NOTES_DATE_FORMAT,
29
+ locale: typeof locale === "string" && locale.trim() !== "" ? locale.trim() : DEFAULT_DAILY_NOTES_LOCALE
30
+ };
31
+ }
32
+ function formatDailyNoteDate(dateIso, display) {
33
+ if (display.dateFormat === "iso") return dateIso;
34
+ const date = /* @__PURE__ */ new Date(`${dateIso}T00:00:00Z`);
35
+ if (Number.isNaN(date.getTime())) return dateIso;
36
+ return new Intl.DateTimeFormat(display.locale, {
37
+ dateStyle: display.dateFormat === "long" ? "long" : "medium",
38
+ timeZone: "UTC"
39
+ }).format(date);
40
+ }
66
41
  function isDailyNoteSlug(slug, directory, pathPattern) {
67
42
  if (directory.length > 0) {
68
43
  const prefix = `${directory}/`;
@@ -149,10 +124,101 @@ function extractCodeBlockSnippet(html, language) {
149
124
  }
150
125
  return null;
151
126
  }
152
- function resolveDailyNoteDate(entry) {
127
+ function resolveDailyNoteDate(entry, slugDateFormat = DEFAULT_SLUG_DATE_FORMAT) {
153
128
  const fromFrontmatter = normalizeDateValue(entry.frontmatter.date) ?? normalizeDateValue(entry.frontmatter.created);
154
129
  if (fromFrontmatter !== null) return fromFrontmatter;
155
- return matchDate(entry.slug) ?? "";
130
+ return matchSlugDate(entry.slug, slugDateFormat) ?? "";
131
+ }
132
+ var SLUG_DATE_TOKEN_SOURCES = {
133
+ YYYY: "\\d{4}",
134
+ YY: "\\d{2}",
135
+ MM: "\\d{2}",
136
+ M: "\\d{1,2}",
137
+ DD: "\\d{2}",
138
+ D: "\\d{1,2}"
139
+ };
140
+ var SLUG_DATE_TOKEN_FIELDS = {
141
+ YYYY: "year",
142
+ YY: "year",
143
+ MM: "month",
144
+ M: "month",
145
+ DD: "day",
146
+ D: "day"
147
+ };
148
+ function matchSlugDate(slug, format) {
149
+ const matcher = compileSlugDateFormat(format);
150
+ if (matcher === null) return null;
151
+ const match = matcher.exec(slug);
152
+ if (match?.groups === void 0) return null;
153
+ const year = resolveSlugDateYear(match.groups);
154
+ const month = Number(match.groups.month);
155
+ const day = Number(match.groups.day);
156
+ if (year === null) return null;
157
+ return formatDate(year, month, day);
158
+ }
159
+ function resolveSlugDateYear(groups) {
160
+ if (groups.year !== void 0) {
161
+ const year = Number(groups.year);
162
+ return Number.isInteger(year) ? year : null;
163
+ }
164
+ if (groups.yearShort !== void 0) {
165
+ const value = Number(groups.yearShort);
166
+ if (!Number.isInteger(value)) return null;
167
+ return value < 69 ? 2e3 + value : 1900 + value;
168
+ }
169
+ return null;
170
+ }
171
+ function compileSlugDateFormat(format) {
172
+ let source = "";
173
+ const captured = /* @__PURE__ */ new Set();
174
+ let hasYear = false;
175
+ let hasMonth = false;
176
+ let hasDay = false;
177
+ let index = 0;
178
+ while (index < format.length) {
179
+ const character = format[index];
180
+ if (character === "[") {
181
+ const end = format.indexOf("]", index + 1);
182
+ if (end === -1) return null;
183
+ source += escapeRegExp(format.slice(index + 1, end));
184
+ index = end + 1;
185
+ continue;
186
+ }
187
+ if (/[A-Za-z]/.test(character)) {
188
+ const token = readSlugDateToken(format, index);
189
+ if (token === null) return null;
190
+ const field = SLUG_DATE_TOKEN_FIELDS[token.value];
191
+ const group = field === "year" && token.value === "YY" ? "yearShort" : field;
192
+ if (captured.has(field)) {
193
+ source += `(?:${SLUG_DATE_TOKEN_SOURCES[token.value]})`;
194
+ } else {
195
+ captured.add(field);
196
+ source += `(?<${group}>${SLUG_DATE_TOKEN_SOURCES[token.value]})`;
197
+ }
198
+ if (field === "year") hasYear = true;
199
+ if (field === "month") hasMonth = true;
200
+ if (field === "day") hasDay = true;
201
+ index = token.end;
202
+ continue;
203
+ }
204
+ source += escapeRegExp(character);
205
+ index += 1;
206
+ }
207
+ if (!hasYear || !hasMonth || !hasDay) return null;
208
+ return new RegExp(source);
209
+ }
210
+ function readSlugDateToken(format, start) {
211
+ const character = format[start];
212
+ let end = start;
213
+ while (end < format.length && format[end] === character) end += 1;
214
+ const run = format.slice(start, end);
215
+ if (character === "Y" && (run === "YYYY" || run === "YY")) {
216
+ return { value: run, end };
217
+ }
218
+ if ((character === "M" || character === "D") && (run === "M" || run === "MM" || run === "D" || run === "DD")) {
219
+ return { value: run, end };
220
+ }
221
+ return null;
156
222
  }
157
223
  var DATE_PATTERN = /(\d{4})-(\d{1,2})-(\d{1,2})/;
158
224
  function normalizeDateValue(value) {
@@ -231,25 +297,74 @@ function fromCodePoint(match, code) {
231
297
  return String.fromCodePoint(code);
232
298
  }
233
299
 
300
+ // components/daily-notes.tsx
301
+ import { jsx, jsxs } from "hono/jsx/jsx-runtime";
302
+ var DEFAULT_LIMIT2 = 5;
303
+ function DailyNotes(props) {
304
+ const limit = props.limit ?? DEFAULT_LIMIT2;
305
+ const notes = props.notes.slice(0, Math.max(0, limit));
306
+ if (notes.length === 0) return null;
307
+ return /* @__PURE__ */ jsxs(
308
+ "section",
309
+ {
310
+ class: "daily-notes rr-daily-notes",
311
+ "aria-labelledby": "daily-notes-title",
312
+ children: [
313
+ /* @__PURE__ */ jsxs("div", { class: "daily-notes__header", children: [
314
+ /* @__PURE__ */ jsx("p", { class: "daily-notes__eyebrow", children: "DAILY NOTES" }),
315
+ /* @__PURE__ */ jsx("h2", { class: "daily-notes__title", id: "daily-notes-title", children: "Recent Daily Notes" })
316
+ ] }),
317
+ /* @__PURE__ */ jsx("ul", { class: "daily-notes__list", children: notes.map((note) => /* @__PURE__ */ jsxs("li", { class: "daily-notes__item", children: [
318
+ /* @__PURE__ */ jsxs("div", { class: "daily-notes__meta", children: [
319
+ note.date.length > 0 ? /* @__PURE__ */ jsx("time", { class: "daily-notes__date", dateTime: note.date, children: note.dateDisplay }) : null,
320
+ note.sourceUrl !== null ? /* @__PURE__ */ jsx("a", { class: "daily-notes__source", href: note.sourceUrl, children: resolveSourceLabel(note) }) : null
321
+ ] }),
322
+ /* @__PURE__ */ jsx("p", { class: "daily-notes__snippet", children: note.snippet })
323
+ ] }, note.slug)) })
324
+ ]
325
+ }
326
+ );
327
+ }
328
+ function resolveSourceLabel(note) {
329
+ if (note.sourceTitle !== null && note.sourceTitle.length > 0) {
330
+ return note.sourceTitle;
331
+ }
332
+ return note.sourceUrl ?? "";
333
+ }
334
+
234
335
  // src/daily-notes.server.ts
336
+ import { resolvePlugins } from "@riebeckite/core";
337
+ function resolveDailyNotesOptionsFromConfig(config) {
338
+ const plugin = resolvePlugins(config.plugins).find(
339
+ (candidate) => candidate.name === DAILY_NOTES_PLUGIN_NAME
340
+ );
341
+ return plugin?.options ?? {};
342
+ }
235
343
  function getDailyNotes(args) {
236
- const options = args.options;
344
+ const options = args.options ?? resolveDailyNotesOptionsFromConfig(args.config);
237
345
  const extract = resolveExtractOptions(options);
346
+ const display = resolveDisplayOptions(options);
238
347
  const directory = options?.source?.directory ?? DEFAULT_DIRECTORY;
239
348
  const pathPattern = options?.source?.pathPattern;
240
- const limit = Math.max(0, options?.widget?.limit ?? DEFAULT_LIMIT2);
349
+ const slugDateFormat = options?.source?.dateFormat ?? DEFAULT_SLUG_DATE_FORMAT;
350
+ const limit = Math.max(0, options?.widget?.limit ?? DEFAULT_LIMIT);
241
351
  const notes = [];
352
+ const discoverableSlugs = new Set(
353
+ args.manifest.discoverableEntries.map((entry) => entry.slug)
354
+ );
242
355
  for (const entry of args.manifest.entries) {
243
356
  if (!isDailyNoteSlug(entry.slug, directory, pathPattern)) continue;
244
357
  const snippet = extractDailyNoteSnippet(entry, extract);
245
358
  if (snippet === null) continue;
246
- const published = isPublished(args.config, entry.frontmatter);
359
+ const discoverable = discoverableSlugs.has(entry.slug);
360
+ const date = resolveDailyNoteDate(entry, slugDateFormat);
247
361
  notes.push({
248
- date: resolveDailyNoteDate(entry),
362
+ date,
363
+ dateDisplay: formatDailyNoteDate(date, display),
249
364
  snippet,
250
365
  slug: entry.slug,
251
- sourceUrl: published ? entry.permalink : null,
252
- sourceTitle: published ? entry.title : null
366
+ sourceUrl: discoverable ? entry.permalink : null,
367
+ sourceTitle: discoverable ? entry.title : null
253
368
  });
254
369
  }
255
370
  return notes.toSorted(compareDailyNotes).slice(0, limit);
@@ -258,14 +373,27 @@ function getDailyNotes(args) {
258
373
  // index.ts
259
374
  function dailyNotesPlugin(options) {
260
375
  return definePlugin({
261
- name: "daily-notes",
376
+ name: DAILY_NOTES_PLUGIN_NAME,
262
377
  options,
263
378
  cacheVersion: "1",
379
+ outputDependencies: resolveOutputDependencies(options),
264
380
  assets: [createStyleAsset("daily-notes")]
265
381
  });
266
382
  }
383
+ function resolveOutputDependencies(options) {
384
+ const directory = options?.source?.directory ?? DEFAULT_DIRECTORY;
385
+ if (directory.length === 0) return [{ type: "global" }];
386
+ return [{ type: "folder", folder: directory }];
387
+ }
267
388
  export {
389
+ DAILY_NOTES_PLUGIN_NAME,
390
+ DEFAULT_DAILY_NOTES_DATE_FORMAT,
391
+ DEFAULT_DAILY_NOTES_LOCALE,
392
+ DEFAULT_SLUG_DATE_FORMAT,
268
393
  DailyNotes,
269
394
  dailyNotesPlugin,
270
- getDailyNotes
395
+ formatDailyNoteDate,
396
+ getDailyNotes,
397
+ resolveDailyNotesOptionsFromConfig,
398
+ resolveDisplayOptions
271
399
  };
@@ -1,17 +1,25 @@
1
1
  import type { ContentManifestEntry } from "@riebeckite/core";
2
2
  export type DailyNote = {
3
3
  date: string;
4
+ dateDisplay: string;
4
5
  snippet: string;
5
6
  slug: string;
6
7
  sourceUrl: string | null;
7
8
  sourceTitle: string | null;
8
9
  };
10
+ /** How Daily Note dates are formatted in the widget. */
11
+ export type DailyNotesDateFormat = "iso" | "long" | "short";
9
12
  export type DailyNotesOptions = {
10
13
  source?: {
11
14
  /** Slug prefix that holds Daily Notes. Defaults to `"Daily"`. */
12
15
  directory?: string;
13
16
  /** Optional slug template (for example `"Daily/{YYYY}-{MM}-{DD}"`). */
14
17
  pathPattern?: string;
18
+ /**
19
+ * Obsidian/Moment date format used by the note filenames. Defaults to
20
+ * `"YYYY-MM-DD"`.
21
+ */
22
+ dateFormat?: string;
15
23
  };
16
24
  extract?: {
17
25
  /** Frontmatter key to read the snippet from. Defaults to `"daily-summary"`. */
@@ -25,18 +33,33 @@ export type DailyNotesOptions = {
25
33
  /** Maximum number of notes to surface. Defaults to `5`. */
26
34
  limit?: number;
27
35
  };
36
+ /** Date format for the widget. Defaults to `"iso"`. */
37
+ dateFormat?: DailyNotesDateFormat;
38
+ /** Locale used by `"long"` and `"short"` dates. Defaults to `"en"`. */
39
+ locale?: string;
28
40
  };
29
41
  export type ResolvedDailyNotesExtract = {
30
42
  frontmatter: string | false;
31
43
  section: string | false;
32
44
  codeBlock: string | false;
33
45
  };
46
+ export type ResolvedDailyNotesDisplay = {
47
+ dateFormat: DailyNotesDateFormat;
48
+ locale: string;
49
+ };
50
+ export declare const DAILY_NOTES_PLUGIN_NAME = "daily-notes";
34
51
  export declare const DEFAULT_DIRECTORY = "Daily";
35
52
  export declare const DEFAULT_FRONTMATTER_KEY = "daily-summary";
36
53
  export declare const DEFAULT_SECTION = "\u4ECA\u65E5\u306E\u3072\u3068\u3053\u3068";
37
54
  export declare const DEFAULT_CODE_BLOCK = "daily-snippet";
38
55
  export declare const DEFAULT_LIMIT = 5;
56
+ export declare const DEFAULT_DAILY_NOTES_DATE_FORMAT: DailyNotesDateFormat;
57
+ export declare const DEFAULT_DAILY_NOTES_LOCALE = "en";
58
+ export declare const DEFAULT_SLUG_DATE_FORMAT = "YYYY-MM-DD";
39
59
  export declare function resolveExtractOptions(options: DailyNotesOptions | undefined): ResolvedDailyNotesExtract;
60
+ export declare function resolveDisplayOptions(options: DailyNotesOptions | undefined): ResolvedDailyNotesDisplay;
61
+ /** Formats a normalized `YYYY-MM-DD` date for display. */
62
+ export declare function formatDailyNoteDate(dateIso: string, display: ResolvedDailyNotesDisplay): string;
40
63
  /**
41
64
  * Matches a manifest slug against the configured Daily Notes location. The
42
65
  * directory is a fast prefix filter; `pathPattern` refines it when present.
@@ -53,8 +76,9 @@ export declare function extractSectionSnippet(html: string, section: string): st
53
76
  export declare function extractCodeBlockSnippet(html: string, language: string): string | null;
54
77
  /**
55
78
  * Derives the note date deterministically: frontmatter `date`, then `created`,
56
- * then a `YYYY-MM-DD` sequence in the slug. Never reads the clock.
79
+ * then the note filename parsed with the configured Obsidian date format.
80
+ * Never reads the clock.
57
81
  */
58
- export declare function resolveDailyNoteDate(entry: ContentManifestEntry): string;
82
+ export declare function resolveDailyNoteDate(entry: ContentManifestEntry, slugDateFormat?: string): string;
59
83
  /** Newest first, then slug ascending. Notes without a date sort last. */
60
84
  export declare function compareDailyNotes(a: DailyNote, b: DailyNote): number;
@@ -1,11 +1,19 @@
1
- import { type ContentManifest, type ResolvedRiebeckiteConfig } from "@riebeckite/core";
1
+ import type { ContentManifest, ResolvedRiebeckiteConfig } from "@riebeckite/core";
2
2
  import { type DailyNote, type DailyNotesOptions } from "./daily-notes.js";
3
+ /**
4
+ * Reads the daily-notes plugin's options back from a Riebeckite config.
5
+ *
6
+ * The widget is rendered by the host application route rather than the plugin
7
+ * itself, so `getDailyNotes` resolves the registered options here to keep the
8
+ * displayed widget in sync with `dailyNotesPlugin(options)`.
9
+ */
10
+ export declare function resolveDailyNotesOptionsFromConfig(config: ResolvedRiebeckiteConfig): DailyNotesOptions;
3
11
  /**
4
12
  * Builds the widget view of the Daily Notes collection.
5
13
  *
6
14
  * Reads `manifest.entries` (the raw view) on purpose: a private note may opt
7
- * in a snippet. Only `sourceUrl` / `sourceTitle` are gated by `isPublished`,
8
- * so an unpublished note never leaks its permalink or title. The note body is
15
+ * in a snippet. Only `sourceUrl` / `sourceTitle` are exposed for discoverable
16
+ * notes, so hidden notes never leak their permalink or title. The note body is
9
17
  * never emitted wholesale — a note without a valid snippet is skipped.
10
18
  */
11
19
  export declare function getDailyNotes(args: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/plugin-daily-notes",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "hono": "^4.12.25",
25
- "@riebeckite/core": "0.0.14"
25
+ "@riebeckite/core": "0.0.16"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsx": "^4.22.4"