-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.js
162 lines (129 loc) · 5.73 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
function manageSettings(logseq) {
//Default settings - Extracts highlights and bold items
const highlightsRegEx = "(==[^=]+==)";
const boldRegEx = "(\\*\\*[^\\*]+\\*\\*)";
//CHANGE THIS WHEN ADDING NEW SETTINGS
const settingsVersion = "v2";
//Use only for saving these first time in the plugin settings file
let defaultSettings = {
expr: `${highlightsRegEx}|${boldRegEx}`,
summaryTitle: "Summary",
keepRefs: true, //Keeps a reference to the source block in this format [*](((uuid)))
nested: true, //Extract from current block and all the child blocks
keepMeta: false, //Remove highlights and bold
keepSummaryAbove: false, //Keep summary above the current block
settingsVersion: settingsVersion,
};
//Load plugin settings
let pluginSettings = logseq.settings;
//This is to ensure that in future if new settings are added they are written over to settings file.
//This will overwrite user's existing settings though.
const shouldUpdateSettings =
pluginSettings.settingsVersion != defaultSettings.settingsVersion;
//If first time, then save default settings
if (shouldUpdateSettings) {
pluginSettings = defaultSettings;
logseq.updateSettings(pluginSettings);
}
}
function main() {
manageSettings(logseq);
const pluginSettings = logseq.settings;
//targetBlock is the block under which the summary will be created.
//For block extract this will be immediately below the current block.
//For page extract it'll be the last block in the page.
//If keepSummaryAbove is true then it'll be the first block in the page for pagePipeline.
//If keepSummaryAbove is false then summary will appear above the summarized block for blockPipeline.
var summarizeExtracts = async (extracts, targetBlock, keepSummaryAbove) => {
//Create a summary block below the current block (sibling) - you can change content of this block
//from Summary to something else by changing the summaryTitle property in settings
var summaryBlock = await logseq.Editor.insertBlock(
targetBlock.uuid,
pluginSettings.summaryTitle,
{ sibling: true, before: keepSummaryAbove }
);
//Create the extracts as children blocks of summary block
extracts.forEach((i) => {
let content = i.content;
//Remove == or ** from start and end if keepMeta is false
content = pluginSettings.keepMeta ? content : content.slice(2, -2);
//Keep reference of source block
content = pluginSettings.keepRefs
? `${content} [*](((${i.source.uuid})))`
: content;
if (!i.source.properties?.id) {
logseq.Editor.upsertBlockProperty(i.source.uuid, "id", i.source.uuid);
}
logseq.Editor.insertBlock(summaryBlock.uuid, content, { sibling: false });
});
logseq.App.showMsg("✔️ Extraction completed successfully!");
};
var processBlock = async (currentBlock) => {
//Get current block content
const block = await logseq.Editor.getBlock(currentBlock.uuid, {
includeChildren: pluginSettings.nested,
});
const regEx = new RegExp(pluginSettings.expr, "g");
//Get all extracts that match regex
//const extracts = [...block.content.matchAll(regEx)];
let extracts = [];
getExtracts(block, regEx, extracts);
//if extracts is empty then return
return extracts;
};
//blockPipeline is the entry point when we extract at block level.
var blockPipeline = async (currentBlock) => {
let extracts = await processBlock(currentBlock);
//EXIT if no extracts found
if (!extracts || !extracts.length) {
logseq.App.showMsg("❗ Nothing to extract!");
return;
}
summarizeExtracts(extracts, currentBlock, pluginSettings.keepSummaryAbove);
};
//blockPipeline is the entry point when we extract at page level.
var pagePipeline = async (context) => {
let pageBlocks = await logseq.Editor.getPageBlocksTree(context.page);
let summaryPosition = pluginSettings.keepSummaryAbove ? 0 : pageBlocks.length-1;
let extracts = [];
for (const block of pageBlocks) {
let result = await processBlock(block);
!!result && extracts.push(result);
}
extracts = extracts.flat();
//EXIT if no extracts found
if (!extracts || !extracts.length) {
logseq.App.showMsg("❗ Nothing to extract!");
return;
}
summarizeExtracts(extracts, pageBlocks[summaryPosition], pluginSettings.keepSummaryAbove);
};
//Extraction function which registers Extract as a context menu for a block
logseq.Editor.registerBlockContextMenuItem("Extract", blockPipeline);
//Extraction function which registers Extract as a context menu for a block
logseq.App.registerPageMenuItem("Extract", pagePipeline);
// logseq.App.registerPageMenuItem(
// 'Extract', async (context) => {
// let pageBlocks = await logseq.Editor.getPageBlocksTree(context.page);
// pageBlocks.forEach((block) => processBlock(block));
// }
// );
}
function getExtracts(currentBlock, regEx, extracts) {
//Get children of the current block
let children = currentBlock.children;
//Find the extracts from the current block
let currentBlockExtracts = [...currentBlock.content.matchAll(regEx)];
//Create a map from current block's extracts
let currentBlockExtractsWithBlockRef = currentBlockExtracts.map((e) => {
return { content: e[0], source: currentBlock };
});
//Push the extracts map from current block into main extracts array
!!currentBlockExtracts.length &&
extracts.push(...currentBlockExtractsWithBlockRef);
//If there are children then call this method recursively (filling the main extracts array which is passed as argument)
!!children.length && children.forEach((c) => getExtracts(c, regEx, extracts));
return;
}
// bootstrap
logseq.ready(main).catch(console.error);