main.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
  3. if you want to view the source visit the plugins github repository
  4. */
  5. 'use strict';
  6. var obsidian = require('obsidian');
  7. /******************************************************************************
  8. Copyright (c) Microsoft Corporation.
  9. Permission to use, copy, modify, and/or distribute this software for any
  10. purpose with or without fee is hereby granted.
  11. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  12. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  13. AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  14. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  15. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  16. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  17. PERFORMANCE OF THIS SOFTWARE.
  18. ***************************************************************************** */
  19. function __awaiter(thisArg, _arguments, P, generator) {
  20. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  21. return new (P || (P = Promise))(function (resolve, reject) {
  22. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  23. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  24. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  25. step((generator = generator.apply(thisArg, _arguments || [])).next());
  26. });
  27. }
  28. const DEFAULT_SETTINGS = {
  29. startOfWeek: '0',
  30. monthFormat: 'YYYY-MM',
  31. displayHead: true,
  32. enableHTML: false,
  33. enableMarkdown: true,
  34. Sunday: 'SUN',
  35. Monday: 'MON',
  36. Tuesday: 'TUE',
  37. Wednesday: 'WED',
  38. Thursday: 'THU',
  39. Friday: 'FRI',
  40. Saturday: 'SAT'
  41. };
  42. class HabitTrackerPlugin extends obsidian.Plugin {
  43. onload() {
  44. return __awaiter(this, void 0, void 0, function* () {
  45. yield this.loadSettings();
  46. this.addSettingTab(new HabitTrackerSettingTab(this.app, this));
  47. //@ts-ignore
  48. window.renderHabitCalendar = (el, dv, calendarParam) => {
  49. dv.current().file.path;
  50. let calendarData = param2CalendarData(dv, calendarParam);
  51. let ctx = fromCalendarData(calendarData, this.settings);
  52. const styles = ctx.tableWidth ? `width: ${ctx.tableWidth};` : '';
  53. const table = createEl('table', { cls: 'habitt', attr: { style: styles } });
  54. table.appendChild(renderHead(ctx));
  55. table.appendChild(renderBody(ctx));
  56. el.appendChild(table);
  57. };
  58. });
  59. }
  60. loadSettings() {
  61. return __awaiter(this, void 0, void 0, function* () {
  62. this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
  63. });
  64. }
  65. saveSettings() {
  66. return __awaiter(this, void 0, void 0, function* () {
  67. yield this.saveData(this.settings);
  68. });
  69. }
  70. }
  71. function createContext(calendarData, settings) {
  72. return {
  73. startOfWeek: parseInt(settings.startOfWeek, 10),
  74. startDay: 0,
  75. monthDays: 0,
  76. displayMonth: '',
  77. tableWidth: '',
  78. marks: new Map(),
  79. settings,
  80. error: '',
  81. calendarData,
  82. filepath: calendarData.filepath
  83. };
  84. }
  85. function isTableData(data) {
  86. return data.successful && data.value && data.value.type == 'table';
  87. }
  88. function param2CalendarData(dv, params) {
  89. const calendarData = {
  90. year: params.year,
  91. month: params.month,
  92. filepath: dv.current().file.path,
  93. width: params.width || "100%",
  94. entries: params.data,
  95. format: params.format || 'text',
  96. date_pattern: params.date_pattern || params.note_pattern || 'YYYY-MM-DD'
  97. };
  98. if (isTableData(params.data)) {
  99. const headers = params.data.value.headers;
  100. const values = params.data.value.values;
  101. const dataDict = {};
  102. for (let ri = 0; ri < values.length; ri += 1) {
  103. // fill calendar day
  104. const value = values[ri];
  105. const link = value[0];
  106. const date = obsidian.moment(link.fileName(), calendarData.date_pattern);
  107. if (!date.isValid()) {
  108. continue;
  109. }
  110. const dateString = link.fileName();
  111. let entry = dataDict[dateString];
  112. if (!entry) {
  113. entry = {
  114. 'date': dateString,
  115. 'content': '',
  116. 'link': link.path
  117. };
  118. dataDict[dateString] = entry;
  119. }
  120. // fill content
  121. for (let ci = 1; ci < value.length; ci++) {
  122. if (value[ci]) {
  123. // if the header contains a "|", use the string after "|" as label
  124. const splited = headers[ci].split("|");
  125. const label = splited[splited.length - 1];
  126. entry.content += `${label} ${value[ci]}\n`;
  127. }
  128. }
  129. }
  130. calendarData.entries = Object.values(dataDict);
  131. calendarData.format = 'text';
  132. }
  133. return calendarData;
  134. }
  135. function fromCalendarData(calendarData, settings) {
  136. const ctx = createContext(calendarData, settings);
  137. const mon = obsidian.moment(`${calendarData.year}-${calendarData.month}`, 'YYYY-M');
  138. if (!mon.isValid()) {
  139. ctx.error = `Fail: Invalid Date ${calendarData.year}-${calendarData.month}`;
  140. return ctx;
  141. }
  142. ctx.displayMonth = mon.format(settings.monthFormat);
  143. ctx.startDay = mon.startOf('month').day();
  144. ctx.monthDays = mon.endOf('month').date();
  145. // table width (optional)
  146. if (calendarData.width) {
  147. ctx.tableWidth = calendarData.width;
  148. }
  149. // punch in
  150. calendarData.entries.forEach(entry => {
  151. const d = obsidian.moment(entry.date, calendarData.date_pattern);
  152. if (d.year() == calendarData.year && d.month() + 1 == calendarData.month) {
  153. ctx.marks.set(d.date(), entry);
  154. }
  155. });
  156. return ctx;
  157. }
  158. function renderHead(ctx) {
  159. const { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } = ctx.settings;
  160. const WEEK = [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday];
  161. const thead = createEl('thead');
  162. if (ctx.settings.displayHead) {
  163. const tr = thead.createEl('tr');
  164. tr.createEl('th', { cls: 'habitt-head', attr: { colspan: 7 }, text: ctx.displayMonth });
  165. }
  166. const tr = thead.createEl('tr');
  167. for (let i = 0; i < 7; i++) {
  168. tr.createEl('th', { cls: `habitt-th habitt-th-${i}`, text: WEEK[(i + ctx.startOfWeek) % 7] });
  169. }
  170. return thead;
  171. }
  172. function renderBody(ctx) {
  173. const startHolds = ctx.startDay >= ctx.startOfWeek ? ctx.startDay - ctx.startOfWeek : 7 - ctx.startOfWeek + ctx.startDay;
  174. let days = (new Array(ctx.monthDays)).fill(0).map((v, i) => i + 1);
  175. const weeks = [];
  176. if (startHolds) {
  177. const startWeekDays = 7 - startHolds;
  178. const firstWeek = (new Array(startHolds)).fill(0);
  179. weeks.push(firstWeek.concat(days.slice(0, startWeekDays)));
  180. days = days.slice(startWeekDays);
  181. }
  182. let i = 0;
  183. while (i < days.length) {
  184. weeks.push(days.slice(i, i + 7));
  185. i = i + 7;
  186. }
  187. const lastWeek = weeks[weeks.length - 1];
  188. if (lastWeek.length < 7) {
  189. const pad = 7 - lastWeek.length;
  190. for (let i = 0; i < pad; i++) {
  191. lastWeek.push(0);
  192. }
  193. }
  194. const tbody = createEl('tbody');
  195. const { enableHTML } = ctx.settings;
  196. for (let i = 0; i < weeks.length; i++) {
  197. const tr = tbody.createEl('tr');
  198. for (let j = 0; j < weeks[i].length; j++) {
  199. const d = weeks[i][j];
  200. const hasOwn = ctx.marks.has(d);
  201. const td = tr.createEl('td', { cls: `habitt-td habitt-td--${d || 'disabled'} ${hasOwn ? 'habitt-td--checked' : ''}` });
  202. const div = td.createDiv({ cls: 'habitt-c' });
  203. // create link to file
  204. if (hasOwn) {
  205. const day_div = div.createDiv({ cls: 'habitt-date' });
  206. const link = ctx.marks.get(d).link ? ctx.marks.get(d).link : ctx.marks.get(d).date;
  207. day_div.createEl('a', { text: `${d || ''}`, cls: "internal-link", href: link, attr: { "data-href": link, "target": "_blank", "rel": "noopener" } });
  208. }
  209. else {
  210. div.createDiv({ cls: 'habitt-date', text: `${d || ''}` });
  211. }
  212. const dots = div.createDiv({ cls: 'habitt-dots' });
  213. if (hasOwn) {
  214. const input = ctx.marks.get(d).content;
  215. // treat as HTML
  216. if (enableHTML && ctx.calendarData.format == 'html') {
  217. dots.innerHTML = `<div>${input}</div>`;
  218. }
  219. else if (ctx.settings.enableMarkdown && ctx.calendarData.format == 'markdown') {
  220. const md_div = dots.createDiv();
  221. obsidian.MarkdownRenderer.renderMarkdown(input, md_div, ctx.filepath, this);
  222. }
  223. else {
  224. dots.createDiv({ cls: 'habit-content', text: input });
  225. }
  226. }
  227. }
  228. }
  229. return tbody;
  230. }
  231. class HabitTrackerSettingTab extends obsidian.PluginSettingTab {
  232. constructor(app, plugin) {
  233. super(app, plugin);
  234. this.plugin = plugin;
  235. }
  236. display() {
  237. const { containerEl } = this;
  238. containerEl.empty();
  239. // containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'});
  240. const weeks = {
  241. '0': 'Sunday',
  242. '1': 'Monday',
  243. '2': 'Tuesday',
  244. '3': 'Wednesday',
  245. '4': 'Thursday',
  246. '5': 'Friday',
  247. '6': 'Saturday'
  248. };
  249. new obsidian.Setting(containerEl)
  250. .setName('Start Of Week')
  251. .setDesc('The day a week begins.')
  252. .addDropdown(dropdown => dropdown
  253. .addOptions(weeks)
  254. .setValue(this.plugin.settings.startOfWeek)
  255. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  256. this.plugin.settings.startOfWeek = value;
  257. yield this.plugin.saveSettings();
  258. })));
  259. new obsidian.Setting(containerEl)
  260. .setName('Display Table Header')
  261. .addToggle(dropdown => dropdown
  262. .setValue(this.plugin.settings.displayHead)
  263. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  264. this.plugin.settings.displayHead = value;
  265. yield this.plugin.saveSettings();
  266. })));
  267. new obsidian.Setting(containerEl)
  268. .setName('Enable HTML')
  269. .setDesc('Treat your input text as HTML. Be careful, it may cause DOM injection attacks')
  270. .addToggle(dropdown => dropdown
  271. .setValue(this.plugin.settings.enableHTML)
  272. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  273. this.plugin.settings.enableHTML = value;
  274. yield this.plugin.saveSettings();
  275. })));
  276. new obsidian.Setting(containerEl)
  277. .setName('Enable Markdown Rendering')
  278. .setDesc('Treat your input text as Markdown.')
  279. .addToggle(dropdown => dropdown
  280. .setValue(this.plugin.settings.enableMarkdown)
  281. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  282. this.plugin.settings.enableMarkdown = value;
  283. yield this.plugin.saveSettings();
  284. })));
  285. new obsidian.Setting(containerEl)
  286. .setName('Month Format')
  287. .setDesc('To format the month text which displays in the header')
  288. .addText(text => text
  289. .setValue(this.plugin.settings.monthFormat)
  290. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  291. this.plugin.settings.monthFormat = value;
  292. yield this.plugin.saveSettings();
  293. })));
  294. new obsidian.Setting(containerEl)
  295. .setName('Sunday Label')
  296. .setDesc('Default is SUN')
  297. .addText(text => text
  298. .setValue(this.plugin.settings.Sunday)
  299. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  300. this.plugin.settings.Sunday = value || DEFAULT_SETTINGS.Sunday;
  301. yield this.plugin.saveSettings();
  302. })));
  303. new obsidian.Setting(containerEl)
  304. .setName('Monday Label')
  305. .setDesc('Default is MON')
  306. .addText(text => text
  307. .setValue(this.plugin.settings.Monday)
  308. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  309. this.plugin.settings.Monday = value || DEFAULT_SETTINGS.Monday;
  310. yield this.plugin.saveSettings();
  311. })));
  312. new obsidian.Setting(containerEl)
  313. .setName('Tuesday Label')
  314. .setDesc('Default is TUE')
  315. .addText(text => text
  316. .setValue(this.plugin.settings.Tuesday)
  317. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  318. this.plugin.settings.Tuesday = value || DEFAULT_SETTINGS.Tuesday;
  319. yield this.plugin.saveSettings();
  320. })));
  321. new obsidian.Setting(containerEl)
  322. .setName('Wednesday Label')
  323. .setDesc('Default is WED')
  324. .addText(text => text
  325. .setValue(this.plugin.settings.Wednesday)
  326. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  327. this.plugin.settings.Wednesday = value || DEFAULT_SETTINGS.Wednesday;
  328. yield this.plugin.saveSettings();
  329. })));
  330. new obsidian.Setting(containerEl)
  331. .setName('Thursday Label')
  332. .setDesc('Default is THU')
  333. .addText(text => text
  334. .setValue(this.plugin.settings.Thursday)
  335. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  336. this.plugin.settings.Thursday = value || DEFAULT_SETTINGS.Thursday;
  337. yield this.plugin.saveSettings();
  338. })));
  339. new obsidian.Setting(containerEl)
  340. .setName('Friday Label')
  341. .setDesc('Default is FRI')
  342. .addText(text => text
  343. .setValue(this.plugin.settings.Friday)
  344. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  345. this.plugin.settings.Friday = value || DEFAULT_SETTINGS.Friday;
  346. yield this.plugin.saveSettings();
  347. })));
  348. new obsidian.Setting(containerEl)
  349. .setName('Saturday Label')
  350. .setDesc('Default is SAT')
  351. .addText(text => text
  352. .setValue(this.plugin.settings.Saturday)
  353. .onChange((value) => __awaiter(this, void 0, void 0, function* () {
  354. this.plugin.settings.Saturday = value || DEFAULT_SETTINGS.Saturday;
  355. yield this.plugin.saveSettings();
  356. })));
  357. }
  358. }
  359. module.exports = HabitTrackerPlugin;