|
@@ -0,0 +1,367 @@
|
|
|
|
+/*
|
|
|
|
+THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
|
|
|
+if you want to view the source visit the plugins github repository
|
|
|
|
+*/
|
|
|
|
+
|
|
|
|
+'use strict';
|
|
|
|
+
|
|
|
|
+var obsidian = require('obsidian');
|
|
|
|
+
|
|
|
|
+/******************************************************************************
|
|
|
|
+Copyright (c) Microsoft Corporation.
|
|
|
|
+
|
|
|
|
+Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
+purpose with or without fee is hereby granted.
|
|
|
|
+
|
|
|
|
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
|
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
+PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
+***************************************************************************** */
|
|
|
|
+
|
|
|
|
+function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
|
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
|
|
+ return new (P || (P = Promise))(function (resolve, reject) {
|
|
|
|
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
|
|
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
|
|
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
|
|
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const DEFAULT_SETTINGS = {
|
|
|
|
+ startOfWeek: '0',
|
|
|
|
+ monthFormat: 'YYYY-MM',
|
|
|
|
+ displayHead: true,
|
|
|
|
+ enableHTML: false,
|
|
|
|
+ enableMarkdown: true,
|
|
|
|
+ Sunday: 'SUN',
|
|
|
|
+ Monday: 'MON',
|
|
|
|
+ Tuesday: 'TUE',
|
|
|
|
+ Wednesday: 'WED',
|
|
|
|
+ Thursday: 'THU',
|
|
|
|
+ Friday: 'FRI',
|
|
|
|
+ Saturday: 'SAT'
|
|
|
|
+};
|
|
|
|
+class HabitTrackerPlugin extends obsidian.Plugin {
|
|
|
|
+ onload() {
|
|
|
|
+ return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ yield this.loadSettings();
|
|
|
|
+ this.addSettingTab(new HabitTrackerSettingTab(this.app, this));
|
|
|
|
+ //@ts-ignore
|
|
|
|
+ window.renderHabitCalendar = (el, dv, calendarParam) => {
|
|
|
|
+ dv.current().file.path;
|
|
|
|
+ let calendarData = param2CalendarData(dv, calendarParam);
|
|
|
|
+ let ctx = fromCalendarData(calendarData, this.settings);
|
|
|
|
+ const styles = ctx.tableWidth ? `width: ${ctx.tableWidth};` : '';
|
|
|
|
+ const table = createEl('table', { cls: 'habitt', attr: { style: styles } });
|
|
|
|
+ table.appendChild(renderHead(ctx));
|
|
|
|
+ table.appendChild(renderBody(ctx));
|
|
|
|
+ el.appendChild(table);
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ loadSettings() {
|
|
|
|
+ return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ saveSettings() {
|
|
|
|
+ return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ yield this.saveData(this.settings);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+function createContext(calendarData, settings) {
|
|
|
|
+ return {
|
|
|
|
+ startOfWeek: parseInt(settings.startOfWeek, 10),
|
|
|
|
+ startDay: 0,
|
|
|
|
+ monthDays: 0,
|
|
|
|
+ displayMonth: '',
|
|
|
|
+ tableWidth: '',
|
|
|
|
+ marks: new Map(),
|
|
|
|
+ settings,
|
|
|
|
+ error: '',
|
|
|
|
+ calendarData,
|
|
|
|
+ filepath: calendarData.filepath
|
|
|
|
+ };
|
|
|
|
+}
|
|
|
|
+function isTableData(data) {
|
|
|
|
+ return data.successful && data.value && data.value.type == 'table';
|
|
|
|
+}
|
|
|
|
+function param2CalendarData(dv, params) {
|
|
|
|
+ const calendarData = {
|
|
|
|
+ year: params.year,
|
|
|
|
+ month: params.month,
|
|
|
|
+ filepath: dv.current().file.path,
|
|
|
|
+ width: params.width || "100%",
|
|
|
|
+ entries: params.data,
|
|
|
|
+ format: params.format || 'text',
|
|
|
|
+ date_pattern: params.date_pattern || params.note_pattern || 'YYYY-MM-DD'
|
|
|
|
+ };
|
|
|
|
+ if (isTableData(params.data)) {
|
|
|
|
+ const headers = params.data.value.headers;
|
|
|
|
+ const values = params.data.value.values;
|
|
|
|
+ const dataDict = {};
|
|
|
|
+ for (let ri = 0; ri < values.length; ri += 1) {
|
|
|
|
+ // fill calendar day
|
|
|
|
+ const value = values[ri];
|
|
|
|
+ const link = value[0];
|
|
|
|
+ const date = obsidian.moment(link.fileName(), calendarData.date_pattern);
|
|
|
|
+ if (!date.isValid()) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ const dateString = link.fileName();
|
|
|
|
+ let entry = dataDict[dateString];
|
|
|
|
+ if (!entry) {
|
|
|
|
+ entry = {
|
|
|
|
+ 'date': dateString,
|
|
|
|
+ 'content': '',
|
|
|
|
+ 'link': link.path
|
|
|
|
+ };
|
|
|
|
+ dataDict[dateString] = entry;
|
|
|
|
+ }
|
|
|
|
+ // fill content
|
|
|
|
+ for (let ci = 1; ci < value.length; ci++) {
|
|
|
|
+ if (value[ci]) {
|
|
|
|
+ // if the header contains a "|", use the string after "|" as label
|
|
|
|
+ const splited = headers[ci].split("|");
|
|
|
|
+ const label = splited[splited.length - 1];
|
|
|
|
+ entry.content += `${label} ${value[ci]}\n`;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ calendarData.entries = Object.values(dataDict);
|
|
|
|
+ calendarData.format = 'text';
|
|
|
|
+ }
|
|
|
|
+ return calendarData;
|
|
|
|
+}
|
|
|
|
+function fromCalendarData(calendarData, settings) {
|
|
|
|
+ const ctx = createContext(calendarData, settings);
|
|
|
|
+ const mon = obsidian.moment(`${calendarData.year}-${calendarData.month}`, 'YYYY-M');
|
|
|
|
+ if (!mon.isValid()) {
|
|
|
|
+ ctx.error = `Fail: Invalid Date ${calendarData.year}-${calendarData.month}`;
|
|
|
|
+ return ctx;
|
|
|
|
+ }
|
|
|
|
+ ctx.displayMonth = mon.format(settings.monthFormat);
|
|
|
|
+ ctx.startDay = mon.startOf('month').day();
|
|
|
|
+ ctx.monthDays = mon.endOf('month').date();
|
|
|
|
+ // table width (optional)
|
|
|
|
+ if (calendarData.width) {
|
|
|
|
+ ctx.tableWidth = calendarData.width;
|
|
|
|
+ }
|
|
|
|
+ // punch in
|
|
|
|
+ calendarData.entries.forEach(entry => {
|
|
|
|
+ const d = obsidian.moment(entry.date, calendarData.date_pattern);
|
|
|
|
+ if (d.year() == calendarData.year && d.month() + 1 == calendarData.month) {
|
|
|
|
+ ctx.marks.set(d.date(), entry);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return ctx;
|
|
|
|
+}
|
|
|
|
+function renderHead(ctx) {
|
|
|
|
+ const { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } = ctx.settings;
|
|
|
|
+ const WEEK = [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday];
|
|
|
|
+ const thead = createEl('thead');
|
|
|
|
+ if (ctx.settings.displayHead) {
|
|
|
|
+ const tr = thead.createEl('tr');
|
|
|
|
+ tr.createEl('th', { cls: 'habitt-head', attr: { colspan: 7 }, text: ctx.displayMonth });
|
|
|
|
+ }
|
|
|
|
+ const tr = thead.createEl('tr');
|
|
|
|
+ for (let i = 0; i < 7; i++) {
|
|
|
|
+ tr.createEl('th', { cls: `habitt-th habitt-th-${i}`, text: WEEK[(i + ctx.startOfWeek) % 7] });
|
|
|
|
+ }
|
|
|
|
+ return thead;
|
|
|
|
+}
|
|
|
|
+function renderBody(ctx) {
|
|
|
|
+ const startHolds = ctx.startDay >= ctx.startOfWeek ? ctx.startDay - ctx.startOfWeek : 7 - ctx.startOfWeek + ctx.startDay;
|
|
|
|
+ let days = (new Array(ctx.monthDays)).fill(0).map((v, i) => i + 1);
|
|
|
|
+ const weeks = [];
|
|
|
|
+ if (startHolds) {
|
|
|
|
+ const startWeekDays = 7 - startHolds;
|
|
|
|
+ const firstWeek = (new Array(startHolds)).fill(0);
|
|
|
|
+ weeks.push(firstWeek.concat(days.slice(0, startWeekDays)));
|
|
|
|
+ days = days.slice(startWeekDays);
|
|
|
|
+ }
|
|
|
|
+ let i = 0;
|
|
|
|
+ while (i < days.length) {
|
|
|
|
+ weeks.push(days.slice(i, i + 7));
|
|
|
|
+ i = i + 7;
|
|
|
|
+ }
|
|
|
|
+ const lastWeek = weeks[weeks.length - 1];
|
|
|
|
+ if (lastWeek.length < 7) {
|
|
|
|
+ const pad = 7 - lastWeek.length;
|
|
|
|
+ for (let i = 0; i < pad; i++) {
|
|
|
|
+ lastWeek.push(0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ const tbody = createEl('tbody');
|
|
|
|
+ const { enableHTML } = ctx.settings;
|
|
|
|
+ for (let i = 0; i < weeks.length; i++) {
|
|
|
|
+ const tr = tbody.createEl('tr');
|
|
|
|
+ for (let j = 0; j < weeks[i].length; j++) {
|
|
|
|
+ const d = weeks[i][j];
|
|
|
|
+ const hasOwn = ctx.marks.has(d);
|
|
|
|
+ const td = tr.createEl('td', { cls: `habitt-td habitt-td--${d || 'disabled'} ${hasOwn ? 'habitt-td--checked' : ''}` });
|
|
|
|
+ const div = td.createDiv({ cls: 'habitt-c' });
|
|
|
|
+ // create link to file
|
|
|
|
+ if (hasOwn) {
|
|
|
|
+ const day_div = div.createDiv({ cls: 'habitt-date' });
|
|
|
|
+ const link = ctx.marks.get(d).link ? ctx.marks.get(d).link : ctx.marks.get(d).date;
|
|
|
|
+ day_div.createEl('a', { text: `${d || ''}`, cls: "internal-link", href: link, attr: { "data-href": link, "target": "_blank", "rel": "noopener" } });
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ div.createDiv({ cls: 'habitt-date', text: `${d || ''}` });
|
|
|
|
+ }
|
|
|
|
+ const dots = div.createDiv({ cls: 'habitt-dots' });
|
|
|
|
+ if (hasOwn) {
|
|
|
|
+ const input = ctx.marks.get(d).content;
|
|
|
|
+ // treat as HTML
|
|
|
|
+ if (enableHTML && ctx.calendarData.format == 'html') {
|
|
|
|
+ dots.innerHTML = `<div>${input}</div>`;
|
|
|
|
+ }
|
|
|
|
+ else if (ctx.settings.enableMarkdown && ctx.calendarData.format == 'markdown') {
|
|
|
|
+ const md_div = dots.createDiv();
|
|
|
|
+ obsidian.MarkdownRenderer.renderMarkdown(input, md_div, ctx.filepath, this);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ dots.createDiv({ cls: 'habit-content', text: input });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return tbody;
|
|
|
|
+}
|
|
|
|
+class HabitTrackerSettingTab extends obsidian.PluginSettingTab {
|
|
|
|
+ constructor(app, plugin) {
|
|
|
|
+ super(app, plugin);
|
|
|
|
+ this.plugin = plugin;
|
|
|
|
+ }
|
|
|
|
+ display() {
|
|
|
|
+ const { containerEl } = this;
|
|
|
|
+ containerEl.empty();
|
|
|
|
+ // containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'});
|
|
|
|
+ const weeks = {
|
|
|
|
+ '0': 'Sunday',
|
|
|
|
+ '1': 'Monday',
|
|
|
|
+ '2': 'Tuesday',
|
|
|
|
+ '3': 'Wednesday',
|
|
|
|
+ '4': 'Thursday',
|
|
|
|
+ '5': 'Friday',
|
|
|
|
+ '6': 'Saturday'
|
|
|
|
+ };
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Start Of Week')
|
|
|
|
+ .setDesc('The day a week begins.')
|
|
|
|
+ .addDropdown(dropdown => dropdown
|
|
|
|
+ .addOptions(weeks)
|
|
|
|
+ .setValue(this.plugin.settings.startOfWeek)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.startOfWeek = value;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Display Table Header')
|
|
|
|
+ .addToggle(dropdown => dropdown
|
|
|
|
+ .setValue(this.plugin.settings.displayHead)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.displayHead = value;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Enable HTML')
|
|
|
|
+ .setDesc('Treat your input text as HTML. Be careful, it may cause DOM injection attacks')
|
|
|
|
+ .addToggle(dropdown => dropdown
|
|
|
|
+ .setValue(this.plugin.settings.enableHTML)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.enableHTML = value;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Enable Markdown Rendering')
|
|
|
|
+ .setDesc('Treat your input text as Markdown.')
|
|
|
|
+ .addToggle(dropdown => dropdown
|
|
|
|
+ .setValue(this.plugin.settings.enableMarkdown)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.enableMarkdown = value;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Month Format')
|
|
|
|
+ .setDesc('To format the month text which displays in the header')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.monthFormat)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.monthFormat = value;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Sunday Label')
|
|
|
|
+ .setDesc('Default is SUN')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Sunday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Sunday = value || DEFAULT_SETTINGS.Sunday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Monday Label')
|
|
|
|
+ .setDesc('Default is MON')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Monday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Monday = value || DEFAULT_SETTINGS.Monday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Tuesday Label')
|
|
|
|
+ .setDesc('Default is TUE')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Tuesday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Tuesday = value || DEFAULT_SETTINGS.Tuesday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Wednesday Label')
|
|
|
|
+ .setDesc('Default is WED')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Wednesday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Wednesday = value || DEFAULT_SETTINGS.Wednesday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Thursday Label')
|
|
|
|
+ .setDesc('Default is THU')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Thursday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Thursday = value || DEFAULT_SETTINGS.Thursday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Friday Label')
|
|
|
|
+ .setDesc('Default is FRI')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Friday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Friday = value || DEFAULT_SETTINGS.Friday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ new obsidian.Setting(containerEl)
|
|
|
|
+ .setName('Saturday Label')
|
|
|
|
+ .setDesc('Default is SAT')
|
|
|
|
+ .addText(text => text
|
|
|
|
+ .setValue(this.plugin.settings.Saturday)
|
|
|
|
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
+ this.plugin.settings.Saturday = value || DEFAULT_SETTINGS.Saturday;
|
|
|
|
+ yield this.plugin.saveSettings();
|
|
|
|
+ })));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+module.exports = HabitTrackerPlugin;
|