diff --git a/CHANGELOG.md b/CHANGELOG.md
index 61fc363..fe16130 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,20 @@
All notable changes to Rich Foot will be documented in this file.
+## [1.7.2] - 2024-11-29
+### ✨ Added
+- `Date Display Format` option to allow users to specify their own date format
+
+### 🐛 Fixed
+- Date not formatted correctly if timestamp was included in the Custom Created/Modified Date Property
+
+## [1.7.1] - 2024-11-27
+### 🐛 Fixed
+- Note embeds in canvas now have the correct height
+- Duplicate "show dates" option in settings
+
+### ✨ Added
+- If using custom created/modified date properties, the date now displays in the format of "Month Day, Year" if in proper date format, otherwise it displays the raw frontmatter filed string value.
## [1.7.0] - 2024-11-26
### ✨ Added
diff --git a/UPDATE.md b/UPDATE.md
index 6e30f41..bc153bb 100644
--- a/UPDATE.md
+++ b/UPDATE.md
@@ -1,5 +1,20 @@
## 📆 Dates Your Way
+### v1.7.2
+#### ✨ Added
+- `Date Display Format` option to allow users to specify their own date format
+
+#### 🐛 Fixed
+- Date not formatted correctly if timestamp was included in the Custom Created/Modified Date Property
+
+### v1.7.1
+#### 🐛 Fixed
+- Note embeds in canvas now have the correct height
+- Duplicate "show dates" option in settings
+
+#### ✨ Added
+- If using custom created/modified date properties, the date now displays in the format of "Month Day, Year" if in proper date format, otherwise it displays the raw frontmatter filed string value.
+
### v1.7.0
#### ✨ Added
- `Custom Created/Modified Date Property` fields to allow users to specify their own frontmatter properties for dates, useful when file system dates are affected by sync processes and you track them separately.
diff --git a/example-vault.zip b/example-vault.zip
index c3769c7..d5e3f16 100644
Binary files a/example-vault.zip and b/example-vault.zip differ
diff --git a/example-vault/rich-foot-example/.obsidian/core-plugins.json b/example-vault/rich-foot-example/.obsidian/core-plugins.json
index 5fcbb97..be7dab5 100644
--- a/example-vault/rich-foot-example/.obsidian/core-plugins.json
+++ b/example-vault/rich-foot-example/.obsidian/core-plugins.json
@@ -4,7 +4,7 @@
"switcher": true,
"graph": false,
"backlink": false,
- "canvas": false,
+ "canvas": true,
"outgoing-link": false,
"tag-pane": true,
"properties": true,
diff --git a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/data.json b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/data.json
index 19c7f28..d785919 100644
--- a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/data.json
+++ b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/data.json
@@ -16,8 +16,9 @@
"linkBorderColor": "rgba(255, 255, 255, 0.204)",
"customCreatedDateProp": "created",
"customModifiedDateProp": "modified",
+ "dateDisplayFormat": "mmmm dd, yyyy",
"showBacklinks": true,
"showOutlinks": true,
"showDates": true,
- "lastVersion": "1.6.0"
+ "lastVersion": "1.7.1"
}
\ No newline at end of file
diff --git a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/main.js b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/main.js
index 1385e6a..c67c486 100644
--- a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/main.js
+++ b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/main.js
@@ -107,7 +107,7 @@ var ReleaseNotesModal = class extends import_obsidian.Modal {
};
// virtual-module:virtual:release-notes
-var releaseNotes = '
\u{1F4C6} Dates Your Way
\nv1.7.0
\n\u2728 Added
\n\nCustom Created/Modified Date Property
fields to allow users to specify their own frontmatter properties for dates, useful when file system dates are affected by sync processes and you track them separately. \n
\n
\n';
+var releaseNotes = '\u{1F4C6} Dates Your Way
\nv1.7.2
\n\u2728 Added
\n\nDate Display Format
option to allow users to specify their own date format \n
\n\u{1F41B} Fixed
\n\n- Date not formatted correctly if timestamp was included in the Custom Created/Modified Date Property
\n
\nv1.7.1
\n\u{1F41B} Fixed
\n\n- Note embeds in canvas now have the correct height
\n- Duplicate "show dates" option in settings
\n
\n\u2728 Added
\n\n- If using custom created/modified date properties, the date now displays in the format of "Month Day, Year" if in proper date format, otherwise it displays the raw frontmatter filed string value.
\n
\nv1.7.0
\n\u2728 Added
\n\nCustom Created/Modified Date Property
fields to allow users to specify their own frontmatter properties for dates, useful when file system dates are affected by sync processes and you track them separately. \n
\n
\n';
// src/main.js
var DEFAULT_SETTINGS = {
@@ -125,7 +125,8 @@ var DEFAULT_SETTINGS = {
linkBackgroundColor: "var(--tag-background)",
linkBorderColor: "rgba(255, 255, 255, 0.204)",
customCreatedDateProp: "",
- customModifiedDateProp: ""
+ customModifiedDateProp: "",
+ dateDisplayFormat: "mmmm dd, yyyy"
};
function rgbToHex(color) {
if (color.startsWith("hsl")) {
@@ -156,6 +157,42 @@ function blendRgbaWithBackground(rgba, backgroundRgb) {
const b = Math.round(fb * alpha + bb * (1 - alpha));
return `rgb(${r}, ${g}, ${b})`;
}
+function formatDate(date, format) {
+ const d = new Date(date);
+ const year = d.getFullYear();
+ const month = d.getMonth();
+ const day = d.getDate();
+ const weekday = d.getDay();
+ const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+ const monthsShort = months.map((m) => m.slice(0, 3));
+ const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
+ const weekdaysShort = weekdays.map((w) => w.slice(0, 3));
+ const pad = (num) => num.toString().padStart(2, "0");
+ const tokens = {
+ "dddd": weekdays[weekday],
+ "ddd": weekdaysShort[weekday],
+ "dd": pad(day),
+ "d": day.toString(),
+ "mmmm": months[month],
+ "mmm": monthsShort[month],
+ "mm": pad(month + 1),
+ "m": (month + 1).toString(),
+ "yyyy": year.toString(),
+ "yy": year.toString().slice(-2)
+ };
+ const sortedTokens = Object.keys(tokens).sort((a, b) => b.length - a.length);
+ let result = format;
+ const replacements = /* @__PURE__ */ new Map();
+ sortedTokens.forEach((token, index) => {
+ const placeholder = `__${index}__`;
+ replacements.set(placeholder, tokens[token]);
+ result = result.replace(new RegExp(token, "g"), placeholder);
+ });
+ replacements.forEach((value, placeholder) => {
+ result = result.replace(new RegExp(placeholder, "g"), value);
+ });
+ return result;
+}
var RichFootPlugin = class extends import_obsidian2.Plugin {
async onload() {
await this.loadSettings();
@@ -168,6 +205,18 @@ var RichFootPlugin = class extends import_obsidian2.Plugin {
await this.checkVersion();
this.updateRichFoot = (0, import_obsidian2.debounce)(this.updateRichFoot.bind(this), 100, true);
this.addSettingTab(new RichFootSettingTab(this.app, this));
+ this.registerEvent(
+ this.app.metadataCache.on("changed", (file) => {
+ const cache = this.app.metadataCache.getFileCache(file);
+ if (cache == null ? void 0 : cache.frontmatter) {
+ const customCreatedProp = this.settings.customCreatedDateProp;
+ const customModifiedProp = this.settings.customModifiedDateProp;
+ if (customCreatedProp && customCreatedProp in cache.frontmatter || customModifiedProp && customModifiedProp in cache.frontmatter) {
+ this.updateRichFoot();
+ }
+ }
+ })
+ );
this.app.workspace.onLayoutReady(() => {
this.registerEvent(
this.app.workspace.on("layout-change", this.updateRichFoot)
@@ -342,9 +391,42 @@ var RichFootPlugin = class extends import_obsidian2.Plugin {
let modifiedDate;
if (this.settings.customModifiedDateProp && frontmatter && frontmatter[this.settings.customModifiedDateProp]) {
modifiedDate = frontmatter[this.settings.customModifiedDateProp];
+ let isValidDate = false;
+ let tempDate = modifiedDate;
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = modifiedDate.replace(/\./g, (match) => {
+ count++;
+ return count <= 2 ? "-" : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = modifiedDate.replace(/\//g, (match) => {
+ count++;
+ return count <= 2 ? "-" : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+ if (isValidDate) {
+ const datePart = tempDate.split("T")[0];
+ const dateStr = tempDate.includes("T") ? tempDate : `${datePart}T00:00:00`;
+ const dateObj = new Date(dateStr);
+ modifiedDate = formatDate(dateObj, this.settings.dateDisplayFormat);
+ } else {
+ modifiedDate = modifiedDate;
+ }
} else {
modifiedDate = new Date(file.stat.mtime);
- modifiedDate = `${modifiedDate.toLocaleString("default", { month: "long" })} ${modifiedDate.getDate()}, ${modifiedDate.getFullYear()}`;
+ modifiedDate = formatDate(modifiedDate, this.settings.dateDisplayFormat);
}
datesWrapper.createDiv({
cls: "rich-foot--modified-date",
@@ -353,9 +435,42 @@ var RichFootPlugin = class extends import_obsidian2.Plugin {
let createdDate;
if (this.settings.customCreatedDateProp && frontmatter && frontmatter[this.settings.customCreatedDateProp]) {
createdDate = frontmatter[this.settings.customCreatedDateProp];
+ let isValidDate = false;
+ let tempDate = createdDate;
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = createdDate.replace(/\./g, (match) => {
+ count++;
+ return count <= 2 ? "-" : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = createdDate.replace(/\//g, (match) => {
+ count++;
+ return count <= 2 ? "-" : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+ if (isValidDate) {
+ const datePart = tempDate.split("T")[0];
+ const dateStr = tempDate.includes("T") ? tempDate : `${datePart}T00:00:00`;
+ const dateObj = new Date(dateStr);
+ createdDate = formatDate(dateObj, this.settings.dateDisplayFormat);
+ } else {
+ createdDate = createdDate;
+ }
} else {
createdDate = new Date(file.stat.ctime);
- createdDate = `${createdDate.toLocaleString("default", { month: "long" })} ${createdDate.getDate()}, ${createdDate.getFullYear()}`;
+ createdDate = formatDate(createdDate, this.settings.dateDisplayFormat);
}
datesWrapper.createDiv({
cls: "rich-foot--created-date",
@@ -500,17 +615,38 @@ var RichFootSettingTab = class extends import_obsidian2.PluginSettingTab {
await this.plugin.saveSettings();
this.plugin.updateRichFoot();
}));
- new import_obsidian2.Setting(containerEl).setName("Show Dates").setDesc("Show creation and modification dates in the footer").addToggle((toggle) => toggle.setValue(this.plugin.settings.showDates).onChange(async (value) => {
- this.plugin.settings.showDates = value;
- await this.plugin.saveSettings();
- this.plugin.updateRichFoot();
- }));
containerEl.createEl("h3", { text: "Date Settings" });
new import_obsidian2.Setting(containerEl).setName("Show Dates").setDesc("Show creation and modification dates in the footer").addToggle((toggle) => toggle.setValue(this.plugin.settings.showDates).onChange(async (value) => {
this.plugin.settings.showDates = value;
await this.plugin.saveSettings();
this.plugin.updateRichFoot();
}));
+ new import_obsidian2.Setting(containerEl).setName("Date Display Format").setDesc("Choose how dates should be displayed in the footer").addDropdown((dropdown) => {
+ const today = /* @__PURE__ */ new Date();
+ const formats = [
+ "mm/dd/yyyy",
+ "dd/mm/yyyy",
+ "yyyy-mm-dd",
+ "mmm dd, yyyy",
+ "dd mmm yyyy",
+ "mmmm dd, yyyy",
+ "ddd, mmm dd, yyyy",
+ "dddd, mmmm dd, yyyy",
+ "mm/dd/yy",
+ "dd/mm/yy",
+ "yy-mm-dd",
+ "m/d/yy"
+ ];
+ formats.forEach((format) => {
+ const example = formatDate(today, format);
+ dropdown.addOption(format, `${format} (example: ${example})`);
+ });
+ dropdown.setValue(this.plugin.settings.dateDisplayFormat).onChange(async (value) => {
+ this.plugin.settings.dateDisplayFormat = value;
+ await this.plugin.saveSettings();
+ this.plugin.updateRichFoot();
+ });
+ });
new import_obsidian2.Setting(containerEl).setName("Custom Created Date Property").setDesc("Specify a frontmatter property to use for creation date (leave empty to use file creation date)").addText((text) => {
text.setValue(this.plugin.settings.customCreatedDateProp).onChange(async (value) => {
this.plugin.settings.customCreatedDateProp = value;
diff --git a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/manifest.json b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/manifest.json
index 75890a4..f2b541b 100644
--- a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/manifest.json
+++ b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/manifest.json
@@ -1,7 +1,7 @@
{
"id": "rich-foot",
"name": "Rich Foot",
- "version": "1.7.0",
+ "version": "1.7.2",
"minAppVersion": "1.5.0",
"description": "Adds backlink tags and created/modified dates to the footer of your notes.",
"author": "Justin Parker (eQui\\\\ Labs)",
diff --git a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/styles.css b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/styles.css
index 5513eaf..0462a84 100644
--- a/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/styles.css
+++ b/example-vault/rich-foot-example/.obsidian/plugins/rich-foot/styles.css
@@ -156,12 +156,19 @@ body.theme-light .rich-foot--backlinks ul li a {
padding-bottom: 0 !important;
}
+/* fix note embed height scroll in canvas */
+.canvas-node-content.markdown-embed div.cm-sizer,
+.canvas-node-content.markdown-embed div.markdown-preview-sizer {
+ min-height: unset !important;
+}
+
+
.cm-sizer .rich-foot--backlinks {
margin-top: 0;
}
.markdown-preview-sizer > div {
- flex: 0;
+ flex: 0 auto;
}
.markdown-preview-sizer > .rich-foot {
diff --git a/example-vault/rich-foot-example/.obsidian/workspace.json b/example-vault/rich-foot-example/.obsidian/workspace.json
index e9304e9..5986c69 100644
--- a/example-vault/rich-foot-example/.obsidian/workspace.json
+++ b/example-vault/rich-foot-example/.obsidian/workspace.json
@@ -13,13 +13,13 @@
"state": {
"type": "markdown",
"state": {
- "file": "🦶 Rich Foot.md",
+ "file": "releases/v1.7.0 - 📆 Dates Your Way.md",
"mode": "preview",
"backlinks": false,
"source": false
},
"icon": "lucide-file",
- "title": "🦶 Rich Foot"
+ "title": "v1.7.0 - 📆 Dates Your Way"
}
}
]
@@ -178,6 +178,196 @@
{
"id": "4674f52fab9186d3",
"type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "c27c8283769f4466",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "c4f94b5118e3d0e8",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "459a2d3da0268437",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "dbaf43fb57cc4699",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "facf9bbf4043ed4c",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "d1a82455e37d17f2",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "c0acc529bba3c2a2",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "b7f24a3bc892f7ce",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "9c84df65d40032a2",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "ae96266198a50c4c",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "fb7d7d767937b219",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "bcb7b70e87d22128",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "864edfa85a3c930c",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "1618e93fe6d7ef12",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "79156bd6731a2904",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "8aaf706b35cce35a",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "55c54da986a31382",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "138dd6cbe7f3aecb",
+ "type": "leaf",
+ "state": {
+ "type": "empty",
+ "state": {},
+ "icon": "lucide-file",
+ "title": "New tab"
+ }
+ },
+ {
+ "id": "2c847f2d16aaf127",
+ "type": "leaf",
"state": {
"type": "Saved Queries View",
"state": {},
@@ -186,7 +376,7 @@
}
}
],
- "currentTab": 8
+ "currentTab": 27
}
],
"direction": "horizontal",
@@ -201,17 +391,20 @@
"cmdr:Reload app without saving": false,
"switcher:Open quick switcher": false,
"templates:Insert template": true,
- "command-palette:Open command palette": false
+ "command-palette:Open command palette": false,
+ "canvas:Create new canvas": false
}
},
"active": "e2b1b7584f7a474c",
"lastOpenFiles": [
- "releases/v1.7.0 - 📆 Dates Your Way.md",
"🦶 Rich Foot.md",
- "pixel-banner-images/calendar-feet.png",
+ "releases/v1.7.0 - 📆 Dates Your Way.md",
+ "backlink test.md",
+ "note with table.md",
+ "Untitled.canvas",
"exclude/no rich-feet here.md",
"exclude/me too/no rich-feet here either.md",
- "backlink test.md",
+ "pixel-banner-images/calendar-feet.png",
"images/rich-feet-3.jpg",
"images/rich-feet-2.jpg",
"images/rich-feet.jpg",
diff --git "a/example-vault/rich-foot-example/releases/v1.7.0 - \360\237\223\206 Dates Your Way.md" "b/example-vault/rich-foot-example/releases/v1.7.0 - \360\237\223\206 Dates Your Way.md"
index 2217e5a..c5b305e 100644
--- "a/example-vault/rich-foot-example/releases/v1.7.0 - \360\237\223\206 Dates Your Way.md"
+++ "b/example-vault/rich-foot-example/releases/v1.7.0 - \360\237\223\206 Dates Your Way.md"
@@ -3,8 +3,8 @@ banner: "[[calendar-feet.png]]"
banner-height: "500"
banner-y: "30"
content-start: "250"
-created: Super Cool Day (who knows when ❔)
-modified: Cold day in Nov (2024-11-26)
+created: 2024/11/30T23:59:00
+modified: 2024-11-29
---
# 🦶 Rich Foot ⋅ v1.7.0 - 📆 Dates Your Way { .release-title }
diff --git a/manifest.json b/manifest.json
index 75890a4..f2b541b 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"id": "rich-foot",
"name": "Rich Foot",
- "version": "1.7.0",
+ "version": "1.7.2",
"minAppVersion": "1.5.0",
"description": "Adds backlink tags and created/modified dates to the footer of your notes.",
"author": "Justin Parker (eQui\\\\ Labs)",
diff --git a/src/main.js b/src/main.js
index d633eb7..831cc12 100644
--- a/src/main.js
+++ b/src/main.js
@@ -18,6 +18,7 @@ const DEFAULT_SETTINGS = {
linkBorderColor: 'rgba(255, 255, 255, 0.204)',
customCreatedDateProp: '',
customModifiedDateProp: '',
+ dateDisplayFormat: 'mmmm dd, yyyy',
};
class RichFootSettings {
@@ -40,6 +41,7 @@ class RichFootSettings {
this.linkBorderColor = DEFAULT_SETTINGS.linkBorderColor;
this.customCreatedDateProp = DEFAULT_SETTINGS.customCreatedDateProp;
this.customModifiedDateProp = DEFAULT_SETTINGS.customModifiedDateProp;
+ this.dateDisplayFormat = DEFAULT_SETTINGS.dateDisplayFormat;
}
}
@@ -120,6 +122,57 @@ function blendRgbaWithBackground(rgba, backgroundRgb) {
return `rgb(${r}, ${g}, ${b})`;
}
+// Add this helper function to format dates
+function formatDate(date, format) {
+ const d = new Date(date);
+ const year = d.getFullYear();
+ const month = d.getMonth();
+ const day = d.getDate();
+ const weekday = d.getDay();
+
+ const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+ const monthsShort = months.map(m => m.slice(0, 3));
+ const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+ const weekdaysShort = weekdays.map(w => w.slice(0, 3));
+
+ // Helper to pad numbers
+ const pad = (num) => num.toString().padStart(2, '0');
+
+ // Create a map of tokens to their values
+ const tokens = {
+ 'dddd': weekdays[weekday],
+ 'ddd': weekdaysShort[weekday],
+ 'dd': pad(day),
+ 'd': day.toString(),
+ 'mmmm': months[month],
+ 'mmm': monthsShort[month],
+ 'mm': pad(month + 1),
+ 'm': (month + 1).toString(),
+ 'yyyy': year.toString(),
+ 'yy': year.toString().slice(-2)
+ };
+
+ // Sort tokens by length (longest first) to avoid partial matches
+ const sortedTokens = Object.keys(tokens).sort((a, b) => b.length - a.length);
+
+ // Replace each token with a unique placeholder
+ let result = format;
+ const replacements = new Map();
+
+ sortedTokens.forEach((token, index) => {
+ const placeholder = `__${index}__`;
+ replacements.set(placeholder, tokens[token]);
+ result = result.replace(new RegExp(token, 'g'), placeholder);
+ });
+
+ // Replace placeholders with final values
+ replacements.forEach((value, placeholder) => {
+ result = result.replace(new RegExp(placeholder, 'g'), value);
+ });
+
+ return result;
+}
+
class RichFootPlugin extends Plugin {
async onload() {
await this.loadSettings();
@@ -139,6 +192,22 @@ class RichFootPlugin extends Plugin {
this.addSettingTab(new RichFootSettingTab(this.app, this));
+ // Register for frontmatter changes
+ this.registerEvent(
+ this.app.metadataCache.on('changed', (file) => {
+ const cache = this.app.metadataCache.getFileCache(file);
+ if (cache?.frontmatter) {
+ const customCreatedProp = this.settings.customCreatedDateProp;
+ const customModifiedProp = this.settings.customModifiedDateProp;
+
+ if ((customCreatedProp && customCreatedProp in cache.frontmatter) ||
+ (customModifiedProp && customModifiedProp in cache.frontmatter)) {
+ this.updateRichFoot();
+ }
+ }
+ })
+ );
+
// Wait for the layout to be ready before registering events
this.app.workspace.onLayoutReady(() => {
this.registerEvent(
@@ -307,7 +376,9 @@ class RichFootPlugin extends Plugin {
const richFoot = createDiv({ cls: 'rich-foot' });
const richFootDashedLine = richFoot.createDiv({ cls: 'rich-foot--dashed-line' });
- // Backlinks
+ // ---------------
+ // -- Backlinks --
+ // ---------------
if (this.settings.showBacklinks) {
const backlinksData = this.app.metadataCache.getBacklinksForFile(file);
@@ -335,7 +406,9 @@ class RichFootPlugin extends Plugin {
}
}
- // Outlinks
+ // --------------
+ // -- Outlinks --
+ // --------------
if (this.settings.showOutlinks) {
const outlinks = this.getOutlinks(file);
@@ -360,32 +433,116 @@ class RichFootPlugin extends Plugin {
}
}
- // Dates
+ // -----------
+ // -- Dates --
+ // -----------
if (this.settings.showDates) {
const datesWrapper = richFoot.createDiv({ cls: 'rich-foot--dates-wrapper' });
const cache = this.app.metadataCache.getFileCache(file);
const frontmatter = cache?.frontmatter;
- // Modified date
+ // -- Modified date --
let modifiedDate;
if (this.settings.customModifiedDateProp && frontmatter && frontmatter[this.settings.customModifiedDateProp]) {
modifiedDate = frontmatter[this.settings.customModifiedDateProp];
+ let isValidDate = false;
+ let tempDate = modifiedDate;
+
+ // Try original string
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ // Try replacing periods with hyphens (only first two occurrences)
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = modifiedDate.replace(/\./g, (match) => {
+ count++;
+ return count <= 2 ? '-' : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+ // Try replacing forward slashes with hyphens (only first two occurrences)
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = modifiedDate.replace(/\//g, (match) => {
+ count++;
+ return count <= 2 ? '-' : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+
+ if (isValidDate) {
+ // Split on 'T' to handle timestamps
+ const datePart = tempDate.split('T')[0];
+ // If there's no time component, parse in local timezone by appending T00:00:00
+ const dateStr = tempDate.includes('T') ? tempDate : `${datePart}T00:00:00`;
+ // Create a Date object from the parts
+ const dateObj = new Date(dateStr);
+ modifiedDate = formatDate(dateObj, this.settings.dateDisplayFormat);
+ } else {
+ modifiedDate = modifiedDate;
+ }
} else {
modifiedDate = new Date(file.stat.mtime);
- modifiedDate = `${modifiedDate.toLocaleString('default', { month: 'long' })} ${modifiedDate.getDate()}, ${modifiedDate.getFullYear()}`;
+ modifiedDate = formatDate(modifiedDate, this.settings.dateDisplayFormat);
}
datesWrapper.createDiv({
cls: 'rich-foot--modified-date',
text: `${modifiedDate}`
});
- // Created date
+ // -- Created date --
let createdDate;
if (this.settings.customCreatedDateProp && frontmatter && frontmatter[this.settings.customCreatedDateProp]) {
createdDate = frontmatter[this.settings.customCreatedDateProp];
+ let isValidDate = false;
+ let tempDate = createdDate;
+
+ // Try original string
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ // Try replacing periods with hyphens (only first two occurrences)
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = createdDate.replace(/\./g, (match) => {
+ count++;
+ return count <= 2 ? '-' : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+ // Try replacing forward slashes with hyphens (only first two occurrences)
+ if (!isValidDate) {
+ let count = 0;
+ tempDate = createdDate.replace(/\//g, (match) => {
+ count++;
+ return count <= 2 ? '-' : match;
+ });
+ if (!isNaN(Date.parse(tempDate))) {
+ isValidDate = true;
+ }
+ }
+
+ if (isValidDate) {
+ // Split on 'T' to handle timestamps
+ const datePart = tempDate.split('T')[0];
+ // If there's no time component, parse in local timezone by appending T00:00:00
+ const dateStr = tempDate.includes('T') ? tempDate : `${datePart}T00:00:00`;
+ // Create a Date object from the parts
+ const dateObj = new Date(dateStr);
+ createdDate = formatDate(dateObj, this.settings.dateDisplayFormat);
+ } else {
+ createdDate = createdDate;
+ }
} else {
createdDate = new Date(file.stat.ctime);
- createdDate = `${createdDate.toLocaleString('default', { month: 'long' })} ${createdDate.getDate()}, ${createdDate.getFullYear()}`;
+ createdDate = formatDate(createdDate, this.settings.dateDisplayFormat);
}
datesWrapper.createDiv({
cls: 'rich-foot--created-date',
@@ -582,17 +739,6 @@ class RichFootSettingTab extends PluginSettingTab {
this.plugin.updateRichFoot();
}));
- new Setting(containerEl)
- .setName('Show Dates')
- .setDesc('Show creation and modification dates in the footer')
- .addToggle(toggle => toggle
- .setValue(this.plugin.settings.showDates)
- .onChange(async (value) => {
- this.plugin.settings.showDates = value;
- await this.plugin.saveSettings();
- this.plugin.updateRichFoot();
- }));
-
// Add Date Settings
containerEl.createEl('h3', { text: 'Date Settings' });
@@ -607,6 +753,40 @@ class RichFootSettingTab extends PluginSettingTab {
this.plugin.updateRichFoot();
}));
+ new Setting(containerEl)
+ .setName('Date Display Format')
+ .setDesc('Choose how dates should be displayed in the footer')
+ .addDropdown(dropdown => {
+ const today = new Date();
+ const formats = [
+ 'mm/dd/yyyy',
+ 'dd/mm/yyyy',
+ 'yyyy-mm-dd',
+ 'mmm dd, yyyy',
+ 'dd mmm yyyy',
+ 'mmmm dd, yyyy',
+ 'ddd, mmm dd, yyyy',
+ 'dddd, mmmm dd, yyyy',
+ 'mm/dd/yy',
+ 'dd/mm/yy',
+ 'yy-mm-dd',
+ 'm/d/yy'
+ ];
+
+ formats.forEach(format => {
+ const example = formatDate(today, format);
+ dropdown.addOption(format, `${format} (example: ${example})`);
+ });
+
+ dropdown
+ .setValue(this.plugin.settings.dateDisplayFormat)
+ .onChange(async (value) => {
+ this.plugin.settings.dateDisplayFormat = value;
+ await this.plugin.saveSettings();
+ this.plugin.updateRichFoot();
+ });
+ });
+
new Setting(containerEl)
.setName('Custom Created Date Property')
.setDesc('Specify a frontmatter property to use for creation date (leave empty to use file creation date)')
diff --git a/styles.css b/styles.css
index 5513eaf..0462a84 100644
--- a/styles.css
+++ b/styles.css
@@ -156,12 +156,19 @@ body.theme-light .rich-foot--backlinks ul li a {
padding-bottom: 0 !important;
}
+/* fix note embed height scroll in canvas */
+.canvas-node-content.markdown-embed div.cm-sizer,
+.canvas-node-content.markdown-embed div.markdown-preview-sizer {
+ min-height: unset !important;
+}
+
+
.cm-sizer .rich-foot--backlinks {
margin-top: 0;
}
.markdown-preview-sizer > div {
- flex: 0;
+ flex: 0 auto;
}
.markdown-preview-sizer > .rich-foot {