inital commit
This commit is contained in:
523
main.js
Normal file
523
main.js
Normal file
@@ -0,0 +1,523 @@
|
||||
const obsidian = require('obsidian');
|
||||
const Plugin = obsidian.Plugin;
|
||||
const ItemView = obsidian.ItemView;
|
||||
|
||||
const DateFormat = {
|
||||
week: "y[0-9]{2}w[0-9]{2}",
|
||||
days: ["zo", "ma", "di", "wo", "do", "vrij", "za"],
|
||||
time: "[0-9]{2}:[0-9]{2}[ap]m",
|
||||
date: ""
|
||||
}
|
||||
DateFormat.date = "(?:" + DateFormat.week + ")?(?: ?(?:" + DateFormat.days.join('|') + ") ?)?(?:" + DateFormat.time + ")?";
|
||||
|
||||
function parseSingleDate(d, defal)
|
||||
{
|
||||
let year = -1, week = -1, dow = -1, time = defal;
|
||||
|
||||
d = d.toLowerCase();
|
||||
|
||||
// year
|
||||
let res = d.match(/y([0-9]{2})/);
|
||||
if (res !== null)
|
||||
{
|
||||
year = parseInt(res[1]) + 2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
year = defal.isoWeekYear();
|
||||
}
|
||||
|
||||
// week
|
||||
res = d.match(/w([0-9]{2})/);
|
||||
if (res !== null)
|
||||
{
|
||||
week = parseInt(res[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
week = defal.isoWeek();
|
||||
}
|
||||
|
||||
// day of week
|
||||
res = d.split(' ');
|
||||
for (const p in res)
|
||||
{
|
||||
let i = DateFormat.days.indexOf(res[p]);
|
||||
if (i != -1){
|
||||
dow = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dow == -1)
|
||||
{
|
||||
dow = defal.day()
|
||||
}
|
||||
|
||||
// time
|
||||
res = d.match(/([0-9]{2}:[0-9]{2}[ap]m)/);
|
||||
if (res !== null)
|
||||
{
|
||||
time = moment(res[1], "hh:mma");
|
||||
}
|
||||
|
||||
// combine
|
||||
time.day(dow);
|
||||
time.isoWeek(week);
|
||||
time.isoWeekYear(year);
|
||||
return time;
|
||||
}
|
||||
|
||||
function stringifySingleDate(date)
|
||||
{
|
||||
let week = date.format("[y]GG[w]WW");
|
||||
let dow = DateFormat.days[date.day()];
|
||||
let time = date.format("hh:mma");
|
||||
return [week, dow, time].join(' ');
|
||||
}
|
||||
|
||||
function stringifyDate(date)
|
||||
{
|
||||
let res = stringifySingleDate(date[0]);
|
||||
if (date[1].diff(date[0]) > 1000)
|
||||
{
|
||||
res += "-" + stringifySingleDate(date[1])
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function parseDate(d, defal)
|
||||
{
|
||||
let start, end;
|
||||
let res = d.match(/([^-]+)-([^-]+)/);
|
||||
if (res !== null)
|
||||
{
|
||||
start = parseSingleDate(res[1], defal);
|
||||
end = parseSingleDate(res[2], start);
|
||||
}
|
||||
else
|
||||
{
|
||||
start = parseSingleDate(d, defal);
|
||||
end = start;
|
||||
}
|
||||
return [start, end]
|
||||
}
|
||||
|
||||
function findDate(line, defal)
|
||||
{
|
||||
let res = line.match("\\[(" + DateFormat.date + "(?:-" + DateFormat.date + ")?)\\]");
|
||||
if (res !== null)
|
||||
{
|
||||
res[1] = parseDate(res[1], defal);
|
||||
}
|
||||
return {
|
||||
"line": line,
|
||||
"dateRemoved": (res === null) ? line : line.replace(res[0], ''),
|
||||
'date': (res === null) ? null : res[1]
|
||||
}
|
||||
}
|
||||
|
||||
function scanFile(editor, data)
|
||||
{
|
||||
let lineNum = 0, lineCount = editor.lineCount();
|
||||
let defal = parseSingleDate("00:00am", moment());
|
||||
|
||||
while ((lineNum < lineCount))
|
||||
{
|
||||
let res, line = editor.getLine(lineNum);
|
||||
|
||||
res = line.match("weekboek: (" + DateFormat.date + ")");
|
||||
if (res != null)
|
||||
{
|
||||
defal = parseSingleDate(res[1], defal);
|
||||
}
|
||||
|
||||
res = [...line.matchAll("\\[(" + DateFormat.date + "(?:-" + DateFormat.date + ")?)\\]")];
|
||||
if (res.length > 0)
|
||||
{
|
||||
if ((res[0] == "[-]" && res.length > 1) || res[0] != "[-]")
|
||||
{
|
||||
if (res[0][0] == "[-]")
|
||||
{
|
||||
res[0] = res[1];
|
||||
}
|
||||
res = res[0]
|
||||
res[1] = parseDate(res[1], defal);
|
||||
let procesed = processLine(line, line.replace(res[0], ''), res[1], data);
|
||||
data = procesed['data'];
|
||||
editor.setLine(lineNum, procesed['line']);
|
||||
}
|
||||
}
|
||||
|
||||
lineNum++;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function processLine(line, noDate, date, data)
|
||||
{
|
||||
let res;
|
||||
let item = {
|
||||
"id": null,
|
||||
"date": stringifyDate(date),
|
||||
"title": "Untitled",
|
||||
"group": "default",
|
||||
"location": null,
|
||||
"state": "reminder"
|
||||
};
|
||||
|
||||
// id
|
||||
res = noDate.match(/<([a-z0-9]+)\/>/);
|
||||
if (res != null)
|
||||
{
|
||||
item["id"] = res[1];
|
||||
noDate = noDate.replace(res[0], '');
|
||||
}
|
||||
else
|
||||
{
|
||||
item["id"] = generateId();
|
||||
line += " <" + item["id"] + "/>";
|
||||
}
|
||||
|
||||
// location
|
||||
res = noDate.match(/\{([^\}\{]+)\}/);
|
||||
if (res != null)
|
||||
{
|
||||
item["location"] = res[1];
|
||||
noDate = noDate.replace(res[0], '');
|
||||
}
|
||||
|
||||
// state (checkbox)
|
||||
res = noDate.match(/^[ \t]*- \[(.)\] /);
|
||||
if (res != null)
|
||||
{
|
||||
switch (res[1])
|
||||
{
|
||||
case ' ':
|
||||
item["state"] = "task";
|
||||
break;
|
||||
case 'x':
|
||||
item["state"] = "done";
|
||||
break;
|
||||
case '-':
|
||||
item["state"] = "canceled";
|
||||
break;
|
||||
case '>':
|
||||
item["state"] = "moved";
|
||||
break;
|
||||
case '/':
|
||||
item["state"] = "partly finished";
|
||||
break;
|
||||
default:
|
||||
item['state'] = res[1];
|
||||
break;
|
||||
}
|
||||
noDate = noDate.replace('[' + res[1] + '] ', '');
|
||||
}
|
||||
|
||||
noDate = noDate.replace(/[ \t][ \t]+/g, ' '); // remve multeple spaces/tabs in a row
|
||||
|
||||
// title and group
|
||||
res = noDate.match(/^ ?- ([^\[\]<>{}]*) - ([^\[\]<>{}]*)/);
|
||||
if (res != null)
|
||||
{
|
||||
item["group"] = res[1];
|
||||
item["title"] = res[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
// no group look for only title
|
||||
res = noDate.match(/^ ?- ([^\[\]<>\{\}]*)/);
|
||||
if (res != null)
|
||||
{
|
||||
item["title"] = res[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
item["title"] = noDate;
|
||||
}
|
||||
}
|
||||
// remove leading and ending spaces
|
||||
item["title"] = item['title'].replaceAll(/(^ +)?( +$)?/g, '')
|
||||
item["group"] = item['group'].replaceAll(/(^ +)?( +$)?/g, '')
|
||||
|
||||
// add/update to database
|
||||
if (data == null) data = {};
|
||||
data[item["id"]] = item;
|
||||
|
||||
return { line: line, data: data};
|
||||
}
|
||||
|
||||
function generateId()
|
||||
{
|
||||
let id = '';
|
||||
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let l = 0;
|
||||
while (l < 10) {
|
||||
id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
l += 1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
const VIEW_TYPE_CALENDAR = "fr-calendar"
|
||||
|
||||
class CalendarView extends ItemView
|
||||
{
|
||||
constructor(leaf, plugin)
|
||||
{
|
||||
super(leaf);
|
||||
this.plugin = plugin;
|
||||
this.week = stringifySingleDate(moment()).match(DateFormat.week)[0]
|
||||
}
|
||||
|
||||
getViewType()
|
||||
{
|
||||
return VIEW_TYPE_CALENDAR;
|
||||
}
|
||||
|
||||
getDisplayText()
|
||||
{
|
||||
return "Calender " + this.week;
|
||||
}
|
||||
|
||||
async onOpen()
|
||||
{
|
||||
const container = this.containerEl.children[1];
|
||||
container.empty();
|
||||
|
||||
// month
|
||||
this.monthEl = container.createEl("div", { cls: "frcal__month" });
|
||||
|
||||
this.monthEl.createEl("div", { cls: "frcal__time" });
|
||||
this.mountFirstEl = this.monthEl.createEl("div", { cls: "frcal__month_first", attr: { style: "flex: 70" } });
|
||||
this.mountFirstSpanEl = this.mountFirstEl.createEl("span");
|
||||
this.mountSecondEl = this.monthEl.createEl("div", { cls: "frcal__month_second", attr: { style: "flex: 0" } });
|
||||
this.mountSecondSpanEl = this.mountSecondEl.createEl("span");
|
||||
|
||||
// day header
|
||||
this.headEl = container.createEl("div", { cls: "frcal__days frcal__day_head" });
|
||||
|
||||
this.headEl.createEl("div", { cls: "frcal__time" });
|
||||
this.dayHeads = [null, null, null, null, null, null, null];
|
||||
for (let i = 0; i < 7; i++)
|
||||
{
|
||||
let dayEl = this.headEl.createEl("div", { cls: "frcal__day frcal__day_head_item" });
|
||||
this.dayHeads[i] = dayEl.createEl("span");
|
||||
}
|
||||
|
||||
// all day events
|
||||
this.alldayEl = container.createEl("div", { cls: "frcal__days frcal__day_allday" });
|
||||
|
||||
this.alldayEl.createEl("div", { cls: "frcal__time" });
|
||||
this.allday = [null, null, null, null, null, null, null];
|
||||
for (let i = 0; i < 7; i++)
|
||||
{
|
||||
this.allday[i] = this.alldayEl.createEl("div", { cls: "frcal__day frcal__day_allday_item" });
|
||||
}
|
||||
|
||||
// timed events
|
||||
this.timedEl = container.createEl("div", { cls: "frcal__days frcal__day_timed" });
|
||||
|
||||
let timed = this.timedEl.createEl("div", { cls: "frcal__time" });
|
||||
let median = "am"
|
||||
for (let i = 1; i <= 12; i++)
|
||||
{
|
||||
timed.createEl("div", { cls: "frcal__hour " + median, text: i.toString() });
|
||||
if (i == 12 && median == "am"){
|
||||
i = 0;
|
||||
median = "pm";
|
||||
}
|
||||
}
|
||||
this.timed = [null, null, null, null, null, null, null];
|
||||
for (let i = 0; i < 7; i++)
|
||||
{
|
||||
this.timed[i] = this.timedEl.createEl("div", { cls: "frcal__day frcal__timed_item" });
|
||||
}
|
||||
|
||||
this.addEvents();
|
||||
this.updateWeek();
|
||||
}
|
||||
|
||||
async onClose()
|
||||
{
|
||||
// Nothing to clean up.
|
||||
}
|
||||
|
||||
addEvents()
|
||||
{
|
||||
this.backButtonEl.ariaDisabled = "false";
|
||||
this.backButtonEl.addEventListener('click', this.gotoPreviusWeek.bind(this));
|
||||
this.forwardButtonEl.ariaDisabled = "false";
|
||||
this.forwardButtonEl.addEventListener('click', this.gotoNextWeek.bind(this));
|
||||
}
|
||||
|
||||
gotoPreviusWeek()
|
||||
{
|
||||
let date = this.week.match(/y([0-9]{2})w([0-9]{2})/);
|
||||
this.week = "y" + date[1] + "w" + (parseInt(date[2]) - 1).toString();
|
||||
this.updateWeek();
|
||||
}
|
||||
|
||||
gotoNextWeek()
|
||||
{
|
||||
let date = this.week.match(/y([0-9]{2})w([0-9]{2})/);
|
||||
this.week = "y" + date[1] + "w" + (parseInt(date[2]) + 1).toString();
|
||||
this.updateWeek();
|
||||
}
|
||||
|
||||
updateWeek()
|
||||
{
|
||||
let months = ["januarie", "februarie", "maart", "april", "mei", "juni", "juli", "augustis", "september", "oktober", "november", "december"];
|
||||
let monthF = parseSingleDate(this.week + " ma 00:00am",).month();
|
||||
this.mountFirstSpanEl.innerText = (monthF+1).toString() + " - " + months[monthF];
|
||||
|
||||
let zoDate = parseSingleDate(this.week + " zo 00:00am");
|
||||
let monthS = zoDate.month();
|
||||
if (monthF != monthS)
|
||||
{
|
||||
this.mountSecondSpanEl.innerText = (monthS+1).toString() + " - " + months[monthS];
|
||||
|
||||
let dow = zoDate.date();
|
||||
|
||||
this.mountFirstEl.setAttr("style", "flex: " + ((7-dow)*10).toString());
|
||||
this.mountSecondEl.setAttr("style", "flex: " + ((dow)*10).toString())
|
||||
}
|
||||
else
|
||||
{
|
||||
this.mountSecondSpanEl.innerText = "";
|
||||
this.mountFirstEl.setAttr("style", "flex: 70")
|
||||
this.mountSecondEl.setAttr("style", "flex: 0")
|
||||
}
|
||||
|
||||
|
||||
let days = ["Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"];
|
||||
for (let day = 0; day < 7; day++)
|
||||
{
|
||||
let date = parseSingleDate(this.week + " " + DateFormat.days[(day + 1) % 7] + " 12:00pm");
|
||||
this.dayHeads[day].innerHTML = days[day] + "<br/>" + date.date().toString();
|
||||
}
|
||||
|
||||
this.updateEvents();
|
||||
}
|
||||
|
||||
updateEvents()
|
||||
{
|
||||
// let item = {
|
||||
// "id": null,
|
||||
// "date": stringifyDate(date),
|
||||
// "allDay": false,
|
||||
// "title": "Untitled",
|
||||
// "group": "default",
|
||||
// "location": null,
|
||||
// "state": "reminder"
|
||||
// };
|
||||
|
||||
// clear events
|
||||
for (let day = 0; day < 7; day++)
|
||||
{
|
||||
this.allday[day].innerHTML = "";
|
||||
this.timed[day].innerHTML = "";
|
||||
}
|
||||
|
||||
let start = parseSingleDate(this.week + " ma 00:00am");
|
||||
let end = parseSingleDate(this.week + " zo 11:59pm");
|
||||
for (let event in this.plugin.data)
|
||||
{
|
||||
event = this.plugin.data[event];
|
||||
let date = parseDate(event['date'])
|
||||
if (
|
||||
(date[0] > start && date[0] < end)
|
||||
|| (date[1] > start && date[1] < end)
|
||||
)
|
||||
{
|
||||
let day = date[0].day() - 1
|
||||
day = (day == -1) ? 6 : day;
|
||||
if (event.date.match(DateFormat.time) == '12:00am')
|
||||
{
|
||||
this.renderEvent(event, this.allday[day]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderEvent(event, this.timed[day]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderEvent(event, container)
|
||||
{
|
||||
el = container.createEl('div', {
|
||||
cls: 'frcal__event',
|
||||
id: "fr_event_" + event.id,
|
||||
attr: {
|
||||
'data-group': event.group,
|
||||
'date-state': event.state
|
||||
}
|
||||
});
|
||||
el.createEl('span', { text: event.title });
|
||||
return el;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FRCalander extends Plugin
|
||||
{
|
||||
async onload()
|
||||
{
|
||||
this.registerView(VIEW_TYPE_CALENDAR, (leaf) => { return new CalendarView(leaf, this) });
|
||||
|
||||
this.addCommand({
|
||||
id: 'calnder-scan',
|
||||
name: 'scan active file',
|
||||
editorCallback: (editor) => {
|
||||
//TODO: check if editor is valid
|
||||
if (this.data == null) this.data = this.loadData();
|
||||
this.data = scanFile(editor, this.data);
|
||||
this.saveData(this.data);
|
||||
}
|
||||
});
|
||||
//TODO: scan folder; with DataAdapter
|
||||
// this.addCommand({
|
||||
// id: 'calnder-save',
|
||||
// name: 'save the calander',
|
||||
// editorCallback: () => {
|
||||
// this.saveData(data);
|
||||
// }
|
||||
// });
|
||||
// this.addCommand({
|
||||
// id: 'calnder-load',
|
||||
// name: 'save the calander',
|
||||
// editorCallback: () => {
|
||||
// data = this.loadData();
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
this.addRibbonIcon("calendar", "show fr calender", () => {
|
||||
let leaf = app.workspace.getLeavesOfType(VIEW_TYPE_CALENDAR);
|
||||
if (leaf.length > 0)
|
||||
{
|
||||
leaf = leaf[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
leaf = app.workspace.getLeavesOfType('empty');
|
||||
if (leaf.length > 0)
|
||||
{
|
||||
leaf = leaf[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
leaf = app.workspace.getLeaf('tab');
|
||||
}
|
||||
}
|
||||
|
||||
leaf.setViewState({ type: VIEW_TYPE_CALENDAR });
|
||||
app.workspace.setActiveLeaf(leaf);
|
||||
});
|
||||
|
||||
this.data = this.loadData();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FRCalander;
|
||||
10
manifest.json
Normal file
10
manifest.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "fr-calander",
|
||||
"name": "calendar thingimegig",
|
||||
"version": "0.0.1",
|
||||
"minAppVersion": "1.3.0",
|
||||
"description": "creates a calender from notes",
|
||||
"author": "Finn van Reenen",
|
||||
"authorUrl": "https://github.com/freenen",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
96
style.css
Normal file
96
style.css
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
.workspace-leaf-content[data-type="fr-calendar"] span {
|
||||
padding: 5px 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.frcal__time {
|
||||
flex: 2;
|
||||
border-right: var(--color-base-40) 1px solid;
|
||||
}
|
||||
|
||||
.frcal__month {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
/*position: fixed;*/
|
||||
}
|
||||
|
||||
.frcal__month_first {
|
||||
background-color: var(--background-primary);
|
||||
border-top: var(--color-base-40) 1px solid;
|
||||
border-right: var(--color-base-40) 1px solid;
|
||||
border-bottom: var(--color-base-40) 1px solid;
|
||||
}
|
||||
|
||||
.frcal__month_second {
|
||||
background-color: var(--background-secondary);
|
||||
border-top: var(--color-base-40) 1px solid;
|
||||
border-right: var(--color-base-40) 1px solid;
|
||||
border-bottom: var(--color-base-40) 1px solid;
|
||||
}
|
||||
|
||||
.frcal__days {
|
||||
display: flex;
|
||||
}
|
||||
.frcal__day {
|
||||
flex: 10;
|
||||
border-right: var(--color-base-40) 1px solid;
|
||||
}
|
||||
.frcal__day:nth-child(even) {
|
||||
background-color: var(--background-primary);
|
||||
}
|
||||
.frcal__day:nth-child(odd) {
|
||||
background-color: var(--background-primary-alt);
|
||||
}
|
||||
|
||||
.frcal__day_head {
|
||||
text-align: center;
|
||||
/*position: fixed;*/
|
||||
width: 100%;
|
||||
/*top: 30px;*/
|
||||
}
|
||||
|
||||
.frcal__day_head .frcal__day {
|
||||
border-bottom: var(--color-base-40) 1px solid;
|
||||
}
|
||||
|
||||
.frcal__day_allday {
|
||||
width: 100%;
|
||||
/*margin-top: 60px*/
|
||||
|
||||
/*position: fixed;*/
|
||||
/*top: 60px;*/
|
||||
}
|
||||
|
||||
.frcal__day_allday .frcal__day {
|
||||
min-height: 30px;
|
||||
border-bottom: var(--color-base-40) 1px solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.frcal__day_timed {
|
||||
border-bottom: var(--color-base-40) 1px solid;
|
||||
text-align: left;
|
||||
align-items: stretch;
|
||||
/*margin-top: 60px*/
|
||||
}
|
||||
|
||||
.frcal__hour {
|
||||
height: 30px;
|
||||
border-bottom: var(--color-base-40) 1px solid;
|
||||
padding: 3px;
|
||||
}
|
||||
.frcal__hour.am{
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.frcal__hour.pm{
|
||||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.frcal__event span {
|
||||
background-color: var(--color-accent);
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
margin: 5px 3px;
|
||||
display: block;
|
||||
}
|
||||
Reference in New Issue
Block a user