1. Added: merge by dae

2. Code improvement
This commit is contained in:
Oliver Yu 2023-07-15 22:47:38 +08:00
parent 2139db2120
commit ae8bfc58a4
10 changed files with 101 additions and 25420 deletions

View file

@ -1,39 +1,45 @@
import { parse, HTMLElement } from 'node-html-parser';
import { NodeHtmlMarkdown } from 'node-html-markdown';
export class Flomo {
private memoNodes: Array<HTMLElement>;
private tagNodes: Array<HTMLElement>;
stat: Record<string, number>
memos: Record<string, string>[];
tags: string[];
files: Record<string, string[]>;
constructor(flomoData: string) {
const root = parse(flomoData);
this.memoNodes = root.querySelectorAll(".memo");
this.tagNodes = root.getElementById("tag").querySelectorAll("option");
this.stat = { "memo": this.memoNodes.length, "tag": this.tagNodes.length }
this.memos = this.loadMemos(root.querySelectorAll(".memo"));
this.tags = this.loadTags(root.getElementById("tag").querySelectorAll("option"));
this.files = {};
}
memos(): Record<string, string>[] {
private loadMemos(memoNodes: Array<HTMLElement>): Record<string, string>[] {
const res: Record<string, string>[] = [];
this.memoNodes.forEach(i => {
res.push({"title": (this.extrtactTitle(i.querySelector(".time").textContent)) as string,
"date": (i.querySelector(".time").textContent.split(" ")[0]) as string,
"content": `Created at: ${this.extractContent(i.innerHTML)} \n\n`})
const extrtactTitle = (item: string) => { return item.replace(/(-|:|\s)/gi, "_") }
const extractContent = (content: string) => {
return NodeHtmlMarkdown.translate(content).replace('\[','[').replace('\]',']')
}
memoNodes.forEach(i => {
const dateTime = i.querySelector(".time").textContent;
const title = extrtactTitle(dateTime);
const content = extractContent(i.querySelector(".content").innerHTML) + "\n" +
extractContent(i.querySelector(".files").innerHTML);
res.push({
"title": title,
"date": dateTime.split(" ")[0],
"content": "`" + dateTime + "`\n" + content,
})
});
return res;
}
tags(): string[] {
private loadTags(tagNodes: Array<HTMLElement>): string[] {
const res: string[] = [];
this.tagNodes.slice(1).forEach(i => { res.push(i.textContent); })
tagNodes.slice(1).forEach( i => { res.push(i.textContent); })
return res;
}
private extrtactTitle(item: string): string {
return item.replace(/(-|:|\s)/gi, "_")
}
private extractContent(content: string): string {
return NodeHtmlMarkdown.translate(content).replace('\[','[').replace('\]',']')
}
}

View file

@ -14,7 +14,7 @@ const FLOMO_CACHE_LOC = path.join(os.homedir(), ".flomo/cache/");
export class FlomoImporter {
private config: Record<string, string>;
private config: Record<string, any>;
private app: App;
constructor(app: App, config: Record<string, string>) {
@ -29,27 +29,44 @@ export class FlomoImporter {
return parse5.serialize(document);
}
private async importMemos(flomo: Flomo): Promise<void> {
for (const [idx, memo] of flomo.memos().entries()) {
private async importMemos(flomo: Flomo): Promise<Flomo> {
const allowBilink: boolean = this.config["expOptionAllowbilink"];
const margeByDate: boolean = this.config["mergeByDate"];
for (const [idx, memo] of flomo.memos.entries()) {
const memoSubDir = `${this.config["flomoTarget"]}/${this.config["memoTarget"]}/${memo["date"]}`;
const memoFilePath = `${memoSubDir}/memo@${memo["title"]}_${flomo.stat["memo"] - idx}.md`;
const memoFilePath = margeByDate ? `${memoSubDir}/memo@${memo["date"]}.md` : `${memoSubDir}/memo@${memo["title"]}_${flomo.memos.length - idx}.md`;
await fs.mkdirp(`${this.config["baseDir"]}/${memoSubDir}`);
const content = (() => {
const res = memo["content"].replace(/!\[\]\(file\//gi, "![](flomo/");
if (this.config["expOptionAllowbilink"] == true) {
if (allowBilink == true) {
return res.replace(`\\[\\[`, "[[").replace(`\\]\\]`, "]]")
}
return res;
})();
if (!(memoFilePath in flomo.files)) {
flomo.files[memoFilePath] = []
}
flomo.files[memoFilePath].push(content);
}
console.log(flomo.files);
for (const filePath in flomo.files) {
await this.app.vault.adapter.write(
`${memoFilePath}`,
content
filePath,
flomo.files[filePath].join("\n\n")
);
}
return flomo;
}
async import(): Promise<Flomo> {
@ -79,7 +96,7 @@ export class FlomoImporter {
const backupData = await this.sanitize(`${tmpDir}/${files[0].path}/index.html`)
const flomo = new Flomo(backupData);
await this.importMemos(flomo)
const memos = await this.importMemos(flomo)
// 5. Ob Intergations
@ -90,7 +107,7 @@ export class FlomoImporter {
// If Generate Canvas
if (this.config["optionsCanvas"] != "skip") {
await generateCanvas(app, flomo, this.config);
await generateCanvas(app, memos, this.config);
}
// 6. Cleanup Workspace

View file

@ -13,30 +13,26 @@ const canvasSize = {
"S": [230, 280]
}
export async function generateCanvas(app: App, flomo: Flomo, config: Record<string, string>): Promise<void> {
const size: number[] = canvasSize[config["canvasSize"]];
if (flomo.stat["memo"] > 0) {
export async function generateCanvas(app: App, flomo: Flomo, config: Record<string, any>): Promise<void> {
if (flomo.memos.length > 0) {
const size: number[] = canvasSize[config["canvasSize"]];
const buffer: Record<string, string>[] = [];
const canvas_file = `${config["flomoTarget"]}/Flomo Canvas.canvas`;
const canvasFile = `${config["flomoTarget"]}/Flomo Canvas.canvas`;
const memoFiles = Object.keys(flomo.files);
for (const [idx, memo] of flomo.memos().entries()) {
for (const [idx, memoFile] of memoFiles.entries()) {
const _id: string = uuidv4();
const _x: number = (idx % 8) * (size[0] + 20); // margin: 20px, length: 8n
const _y: number = (Math.floor(idx / 8)) * (size[1] + 20); // margin: 20px
const content = (() => {
const res = memo["content"].replace(/!\[\]\(file\//gi, "![](flomo/");
if (config["expOptionAllowbilink"] == true) {
return res.replace(`\\[\\[`, "[[").replace(`\\]\\]`, "]]")
}
return res;
})();
const content = flomo.files[memoFile];
const canvasNode: Record<string, any> = (() => {
if (config["optionsCanvas"] == "copy_with_link") {
return {
"type": "file",
"file": `${config["flomoTarget"]}/${config["memoTarget"]}/${memo["date"].split(" ")[0]}/memo@${memo["title"]}_${flomo.stat["memo"] - idx}.md`,
"file": memoFile,
"id": _id,
"x": _x,
"y": _y,
@ -46,7 +42,7 @@ export async function generateCanvas(app: App, flomo: Flomo, config: Record<stri
} else {
return {
"type": "text",
"text": content,
"text": content.join("\n\n"),
"id": _id,
"x": _x,
"y": _y,
@ -60,6 +56,7 @@ export async function generateCanvas(app: App, flomo: Flomo, config: Record<stri
};
const canvasJson = { "nodes": buffer, "edges": [] }
await app.vault.adapter.write(canvas_file, JSON.stringify(canvasJson));
await app.vault.adapter.write(canvasFile, JSON.stringify(canvasJson));
}
}

View file

@ -2,20 +2,21 @@ import { App } from 'obsidian';
import { Flomo } from '../flomo';
export async function generateMoments(app: App, flomo: Flomo, config: Record<string, string>): Promise<void> {
if (flomo.stat["memo"] > 0) {
export async function generateMoments(app: App, flomo: Flomo, config: Record<string, any>): Promise<void> {
if (flomo.memos.length > 0) {
const buffer: string[] = [];
const tags: string[] = [];
const index_file = `${config["flomoTarget"]}/Flomo Moments.md`;
const memoFiles = Object.keys(flomo.files);
buffer.push(`updated at: ${(new Date()).toLocaleString()}\n\n`);
for (const tag of flomo.tags()) { tags.push(`#${tag}`);};
for (const tag of flomo.tags) { tags.push(`#${tag}`);};
buffer.push(tags.join(' ') + "\n\n---\n\n");
for (const [idx, memo] of flomo.memos().entries()) {
buffer.push(`![[${config["memoTarget"]}/${memo["date"].split(" ")[0]}/memo@${memo["title"]}_${flomo.stat["memo"] - idx}]]\n\n---\n\n`);
for (const [idx, memoFile] of memoFiles.entries()) {
buffer.push(`![[${memoFile}]]\n\n---\n\n`);
};
await app.vault.adapter.write(index_file, buffer.join("\n"));

View file

@ -28,7 +28,7 @@ export class ImporterUI extends Modal {
const flomo = await (new FlomoImporter(this.app, config)).import();
new Notice(`🎉 Import Completed.\nTotal: ${flomo.stat["memo"].toString()} memos`)
new Notice(`🎉 Import Completed.\nTotal: ${flomo.memos.length} memos`)
this.rawPath = "";
@ -65,7 +65,7 @@ export class ImporterUI extends Modal {
}));
new Setting(contentEl)
.setName('Memos Location')
.setName('Memo Location')
.setDesc('set the location to store memos (under flomo root)')
.addText((text) => text
.setPlaceholder('memos')
@ -75,8 +75,8 @@ export class ImporterUI extends Modal {
}));
new Setting(contentEl)
.setName('Moments Options')
.setDesc('set moments options')
.setName('Memo Options')
.setDesc('set memo options')
.addDropdown((drp) => {
drp.addOption("copy_with_link", "Generate Moments")
.addOption("skip", "Skip Moments")
@ -86,12 +86,24 @@ export class ImporterUI extends Modal {
})
})
const momentOptionBlock: HTMLDivElement = contentEl.createEl("div", { cls: "canvasOptionBlock" });
const momentOptionLabel: HTMLLabelElement = momentOptionBlock.createEl("label");
const mergeByDate: HTMLInputElement = momentOptionLabel.createEl("input", { type: "checkbox", cls: "ckbox" })
mergeByDate.checked = this.plugin.settings.mergeByDate;
mergeByDate.onchange = (ev) => {
this.plugin.settings.mergeByDate = ev.currentTarget.checked;
};
momentOptionLabel.createEl("small", { text: "merge memos by date" });
new Setting(contentEl)
.setName('Canvas Options')
.setDesc('set canvas options')
.addDropdown((drp) => {
drp.addOption("copy_with_link", "Generate Canvas")
.addOption("copy_with_content", "Generate Canvas with content")
.addOption("copy_with_content", "Generate Canvas (with content)")
.addOption("skip", "Skip Canvas")
.setValue(this.plugin.settings.optionsCanvas)
.onChange(async (value) => {
@ -150,7 +162,7 @@ export class ImporterUI extends Modal {
this.plugin.settings.expOptionAllowbilink = ev.currentTarget.checked;
};
expOptionLabel.createEl("small", { text: "Convert bidirectonal link: [[link]]" });
expOptionLabel.createEl("small", { text: "Convert bidirectonal link. example: [[abc]]" });
new Setting(contentEl)

25356
main.js

File diff suppressed because one or more lines are too long

View file

@ -8,16 +8,18 @@ interface MyPluginSettings {
optionsMoments: string,
optionsCanvas: string,
expOptionAllowbilink: boolean,
canvasSize: string
canvasSize: string,
mergeByDate: boolean
}
const DEFAULT_SETTINGS: MyPluginSettings = {
flomoTarget: 'flomo',
memoTarget: 'memos',
optionsMoments: "copy_with_link",
optionsCanvas: "copy_with_link",
optionsCanvas: "copy_with_content",
expOptionAllowbilink: true,
canvasSize: 'M'
canvasSize: 'M',
mergeByDate: false
}
export default class FlomoImporterPlugin extends Plugin {

View file

@ -1,7 +1,7 @@
{
"id": "flomo-importer",
"name": "Flomo Importer",
"version": "1.1.1",
"version": "1.1.2",
"minAppVersion": "1.1.16",
"description": "Make Flomo Memos to Obsidian Notes",
"author": "Jialu Y",

View file

@ -12,12 +12,13 @@ If your plugin does not need CSS, delete this file.
margin: 0 0 0px;
width: 100%;
display: block;
background: #f5f5f5;
background: transparent
}
.uploadbox:hover {
background: #e0e0e0;
/*background: #e0e0e0;*/
cursor: pointer;
border: 1px dashed #915109;
}
.expOptionBlock {

View file

@ -1,5 +1,6 @@
{
"1.0.0": "0.15.0",
"1.1.0": "1.1.16",
"1.1.1": "1.1.16"
"1.1.1": "1.1.16",
"1.1.2": "1.1.16"
}