@riebeckite/plugin-daily-notes 0.0.13 → 0.0.15
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 +27 -3
- package/README_ja.md +17 -3
- package/dist/components/daily-notes.js +2 -7
- package/dist/index.d.ts +5 -4
- package/dist/index.js +184 -56
- package/dist/src/daily-notes.d.ts +26 -2
- package/dist/src/daily-notes.server.d.ts +11 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -52,9 +52,15 @@ getDailyNotes({
|
|
|
52
52
|
manifest,
|
|
53
53
|
config,
|
|
54
54
|
options: {
|
|
55
|
-
source: {
|
|
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
|
-
-
|
|
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: {
|
|
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
|
-
-
|
|
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:
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
359
|
+
const discoverable = discoverableSlugs.has(entry.slug);
|
|
360
|
+
const date = resolveDailyNoteDate(entry, slugDateFormat);
|
|
247
361
|
notes.push({
|
|
248
|
-
date
|
|
362
|
+
date,
|
|
363
|
+
dateDisplay: formatDailyNoteDate(date, display),
|
|
249
364
|
snippet,
|
|
250
365
|
slug: entry.slug,
|
|
251
|
-
sourceUrl:
|
|
252
|
-
sourceTitle:
|
|
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:
|
|
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
|
-
|
|
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
|
|
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 {
|
|
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
|
|
8
|
-
* so
|
|
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.
|
|
3
|
+
"version": "0.0.15",
|
|
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.
|
|
25
|
+
"@riebeckite/core": "0.0.15"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"tsx": "^4.22.4"
|