imdone-core 1.53.6 → 1.53.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/adapters/file-gateway.js +4 -4
- package/lib/adapters/parsers/function-parser.js +29 -0
- package/lib/adapters/parsers/task/CardContentParser.js +19 -1
- package/lib/card.js +4 -2
- package/lib/config.js +4 -2
- package/lib/constants.js +1 -0
- package/lib/file.js +4 -4
- package/lib/list.js +1 -1
- package/lib/migrate-config.js +6 -3
- package/lib/plugins/default-board-properties-plugin.js +54 -0
- package/lib/plugins/epic-plugin.js +1 -1
- package/lib/plugins/extension-plugin.js +12 -1
- package/lib/plugins/plugin-manager.js +19 -6
- package/lib/project.js +60 -21
- package/package.json +2 -2
- package/lib/plugins/default-card-properties-plugin.js +0 -25
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[](https://badge.fury.io/js/imdone-core)
|
|
2
2
|
[](https://npmjs.org/package/imdone-core)
|
|
3
|
-
|
|
3
|
+

|
|
4
4
|
|
|
5
5
|
Imdone is text based kanban processor with a simple syntax that uses [comment tags like TODO and FIXME](https://en.wikipedia.org/wiki/Comment_%28computer_programming%29#Tags) and [todo.txt format](https://github.com/todotxt/todo.txt#todotxt-format). This model allows the user to create and modify tasks using the keyboard and automatically establishes a link between their tasks and work. Get [imdone](https://imdone.io) or use the cli to see your projects board and this library in action.
|
|
6
6
|
|
|
@@ -4,7 +4,7 @@ let fs = require('fs')
|
|
|
4
4
|
const sanitize = require('sanitize-filename')
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
module.exports = {
|
|
7
|
+
module.exports = gateway = {
|
|
8
8
|
init(fileSystem = fs) {
|
|
9
9
|
fs = fileSystem
|
|
10
10
|
},
|
|
@@ -94,14 +94,14 @@ module.exports = {
|
|
|
94
94
|
},
|
|
95
95
|
|
|
96
96
|
preparePathForWriting(path) {
|
|
97
|
-
let stat =
|
|
97
|
+
let stat = gateway.statSync(path)
|
|
98
98
|
if (!stat) {
|
|
99
99
|
let { dir, ext } = _path.parse(path)
|
|
100
100
|
if (!ext) {
|
|
101
101
|
dir = path
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
stat =
|
|
103
|
+
gateway.mkdirpSync(dir)
|
|
104
|
+
stat = gateway.statSync(path)
|
|
105
105
|
}
|
|
106
106
|
return {
|
|
107
107
|
isFile: stat && stat.isFile(),
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
getFunctionSignature
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
function getFunctionSignature(fn) {
|
|
6
|
+
if (typeof fn !== "function") {
|
|
7
|
+
throw new TypeError("Expected a function");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const fnString = fn.toString().trim();
|
|
11
|
+
let name = fn.name || "anonymous";
|
|
12
|
+
let params = "";
|
|
13
|
+
|
|
14
|
+
// Match function parameters
|
|
15
|
+
const paramMatch = fnString.match(/\(([^)]*)\)/);
|
|
16
|
+
if (paramMatch) {
|
|
17
|
+
params = paramMatch[1].trim();
|
|
18
|
+
} else {
|
|
19
|
+
// Handle arrow functions without parentheses
|
|
20
|
+
const arrowMatch = fnString.match(/^(?:\S+\s+)?(\w+)?\s*=?\s*(?:async\s*)?\(?([^)=]*)\)?\s*=>/);
|
|
21
|
+
if (arrowMatch) {
|
|
22
|
+
name = name || arrowMatch[1] || "anonymous";
|
|
23
|
+
params = arrowMatch[2].trim();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return `${name}(${params})`;
|
|
28
|
+
}
|
|
29
|
+
|
|
@@ -225,9 +225,27 @@ function getTextFileTaskContent ({
|
|
|
225
225
|
const rawTaskContentLines = []
|
|
226
226
|
const taskContentLines = []
|
|
227
227
|
|
|
228
|
+
let inCodeBlock = false
|
|
229
|
+
let inCodeSpan = false
|
|
230
|
+
|
|
228
231
|
for (let i = 1; i < lines.length; i++) {
|
|
229
232
|
let line = lines[i]
|
|
230
|
-
|
|
233
|
+
|
|
234
|
+
// Check for markdown code blocks
|
|
235
|
+
if (isMarkDownFile && line.trim().startsWith('```')) {
|
|
236
|
+
inCodeBlock = !inCodeBlock
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Check for markdown code spans
|
|
240
|
+
if (isMarkDownFile && line.includes('`')) {
|
|
241
|
+
const codeSpanMatches = line.match(/`+/g)
|
|
242
|
+
if (codeSpanMatches && codeSpanMatches.length % 2 !== 0) {
|
|
243
|
+
inCodeSpan = !inCodeSpan
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Only break if the task is not in a markdown code block or code span
|
|
248
|
+
if (!inCodeBlock && !inCodeSpan && hasTaskInText(config, line)) break
|
|
231
249
|
if (isCheckBoxTask(config, line, beforeText)) break
|
|
232
250
|
if (isTaskInList && isLineOutsideMarkdownList(line, beforeText)) break
|
|
233
251
|
if (isCustomCardTerminator(config, line)) break
|
package/lib/card.js
CHANGED
|
@@ -8,6 +8,7 @@ const _isEmpty = require('lodash.isempty')
|
|
|
8
8
|
const _get = require('lodash.get')
|
|
9
9
|
const eol = require('eol')
|
|
10
10
|
const allEmoji = require('markdown-it-emoji/lib/data/full.json')
|
|
11
|
+
const { getFunctionSignature } = require('./adapters/parsers/function-parser')
|
|
11
12
|
|
|
12
13
|
const { removeMD } = require('./adapters/markdown')
|
|
13
14
|
|
|
@@ -190,7 +191,7 @@ module.exports = function newCard(task, _project, dontParse) {
|
|
|
190
191
|
const keys = Object.keys(data).map((key) => {
|
|
191
192
|
const value = data[key]
|
|
192
193
|
if (_isFunction(value)) {
|
|
193
|
-
key =
|
|
194
|
+
key = getFunctionSignature(value)
|
|
194
195
|
}
|
|
195
196
|
return key
|
|
196
197
|
})
|
|
@@ -237,7 +238,8 @@ module.exports = function newCard(task, _project, dontParse) {
|
|
|
237
238
|
}
|
|
238
239
|
|
|
239
240
|
format(content, mustache) {
|
|
240
|
-
const
|
|
241
|
+
const projectData = project ? { ...project.data } : {}
|
|
242
|
+
const data = { ...this.data, ...projectData }
|
|
241
243
|
|
|
242
244
|
const opts = { interpolate: /(?<![`\\])\${([\s\S]+?)}/g }
|
|
243
245
|
|
package/lib/config.js
CHANGED
|
@@ -71,8 +71,10 @@ class Config {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
getDoingList() {
|
|
74
|
-
const lists = _cloneDeep(this.lists).
|
|
75
|
-
|
|
74
|
+
const lists = _cloneDeep(this.lists).filter((list) => !list.filter)
|
|
75
|
+
.reverse().map(list => list.name)
|
|
76
|
+
const defaultValue = lists ? lists.find(list => /doing|progress/i.test(list.name)) :
|
|
77
|
+
lists[1].name || '';
|
|
76
78
|
return _get(this, 'settings.cards.doingList', defaultValue)
|
|
77
79
|
}
|
|
78
80
|
|
package/lib/constants.js
CHANGED
package/lib/file.js
CHANGED
|
@@ -381,7 +381,7 @@ File.prototype.extractHashStyleTasks = function (config, pos, content) {
|
|
|
381
381
|
if (!config.listExists(list)) continue
|
|
382
382
|
|
|
383
383
|
const posInContent = result.index + pos
|
|
384
|
-
if (this.isWithinCodeSpanOrBlock(
|
|
384
|
+
if (this.isWithinCodeSpanOrBlock(result.index, content)) continue
|
|
385
385
|
|
|
386
386
|
const line = this.getLineNumber(posInContent)
|
|
387
387
|
if (this.hasTaskAtLine(line)) continue
|
|
@@ -416,7 +416,7 @@ File.prototype.extractLinkStyleTasks = function (config, pos, content) {
|
|
|
416
416
|
let [match, before, rawTask, text, list, colon, order] = result
|
|
417
417
|
const beforeLength = before ? before.length : 0
|
|
418
418
|
const posInContent = result.index + pos + beforeLength
|
|
419
|
-
if (this.isWithinCodeSpanOrBlock(
|
|
419
|
+
if (this.isWithinCodeSpanOrBlock(result.index, content)) continue
|
|
420
420
|
var line = this.getLineNumber(posInContent)
|
|
421
421
|
if (self.hasTaskAtLine(line)) continue
|
|
422
422
|
if (!config.listExists(list)) continue
|
|
@@ -1192,13 +1192,13 @@ File.prototype.getCodeCommentRegex = function () {
|
|
|
1192
1192
|
// #BACKLOG:-460 Allow languages to have multiple block comment styles, like html gh:13 id:5
|
|
1193
1193
|
var lang = this.getLang()
|
|
1194
1194
|
var symbol = lang.symbol
|
|
1195
|
-
var reString = escapeRegExp(symbol) + '[^{].*$'
|
|
1195
|
+
var reString = '(?<!["\'`])' + escapeRegExp(symbol) + '[^{].*$'
|
|
1196
1196
|
|
|
1197
1197
|
if (lang.block) {
|
|
1198
1198
|
var start = escapeRegExp(lang.block.start)
|
|
1199
1199
|
var end = escapeRegExp(lang.block.end)
|
|
1200
1200
|
//
|
|
1201
|
-
reString = reString + '|' + start + '(.|[\\r\\n])*?' + end
|
|
1201
|
+
reString = reString + '|(?<!["\'`])' + start + '(.|[\\r\\n])*?' + end
|
|
1202
1202
|
}
|
|
1203
1203
|
|
|
1204
1204
|
return new RegExp(reString, 'gmi')
|
package/lib/list.js
CHANGED
|
@@ -13,7 +13,7 @@ const uniqid = require('uniqid')
|
|
|
13
13
|
* @param {} hidden
|
|
14
14
|
* @return
|
|
15
15
|
*/
|
|
16
|
-
function List({name, hidden, ignore, filter, id
|
|
16
|
+
function List({ name, hidden, ignore, filter, id }) {
|
|
17
17
|
this.name = name;
|
|
18
18
|
this.hidden = hidden || false
|
|
19
19
|
this.ignore = ignore || false
|
package/lib/migrate-config.js
CHANGED
|
@@ -51,7 +51,8 @@ module.exports = function (repo, defaultSettings = defaultSettingsObject) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if (config.settings.cards.defaultList === undefined) {
|
|
54
|
-
config.settings.cards.defaultList = lists ? lists
|
|
54
|
+
config.settings.cards.defaultList = lists ? lists.find(list => /todo/i.test(list)) :
|
|
55
|
+
lists[0] || '';
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
// archiveCompleted
|
|
@@ -107,11 +108,13 @@ module.exports = function (repo, defaultSettings = defaultSettingsObject) {
|
|
|
107
108
|
}
|
|
108
109
|
// Set up default doneList
|
|
109
110
|
if (config.settings.cards.doneList === undefined) {
|
|
110
|
-
config.settings.cards.doneList = lists ? lists
|
|
111
|
+
config.settings.cards.doneList = lists ? lists.find(list => /done/i.test(list)) :
|
|
112
|
+
lists[lists.length - 1] || '';
|
|
111
113
|
}
|
|
112
114
|
// Set up default doingList
|
|
113
115
|
if (config.settings.cards.doingList === undefined) {
|
|
114
|
-
config.settings.cards.doingList = lists ? lists
|
|
116
|
+
config.settings.cards.doingList = lists ? lists.find(list => /doing|progress/i.test(list)) :
|
|
117
|
+
lists[lists.length - 2] || '';
|
|
115
118
|
}
|
|
116
119
|
// Add name
|
|
117
120
|
if (config.settings.name === undefined) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const Plugin = require('imdone-api')
|
|
2
|
+
const {getIsoDateWithOffset} = require('../adapters/date-time')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const simpleTemplate = '\n<!--\ncreated:${timestamp}\n-->\n'
|
|
5
|
+
|
|
6
|
+
module.exports = class DefaultBoardPropertiesPlugin extends Plugin {
|
|
7
|
+
constructor(project) {
|
|
8
|
+
super(project)
|
|
9
|
+
this.templates = {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async onBeforeBoardUpdate() {
|
|
13
|
+
this.templates = await this.getTemplates()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getBoardProperties() {
|
|
17
|
+
const self = this;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
date: `${getIsoDateWithOffset(new Date()).substring(0, 10)}`,
|
|
21
|
+
timestamp: getIsoDateWithOffset(new Date()),
|
|
22
|
+
clearFilterURL: self.getFilterURL(''),
|
|
23
|
+
templates: this.templates,
|
|
24
|
+
getFilterURL: (filter) => self.getFilterURL(filter),
|
|
25
|
+
getFilterLink: (filter) => `[Filter By: ${filter}](${self.getFilterURL(filter)})`
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getFilterURL(filter) {
|
|
30
|
+
return `imdone://${this.project.path}?filter=${filter}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async getTemplates() {
|
|
34
|
+
const { preparePathForWriting, readdir, readFile } = this.project.fileGateway
|
|
35
|
+
const templateDir = path.join(this.project.configDir, 'templates');
|
|
36
|
+
preparePathForWriting(templateDir);
|
|
37
|
+
const files = await readdir(templateDir);
|
|
38
|
+
const readFilePromises = files.map((file) => {
|
|
39
|
+
return new Promise(async (resolve) => {
|
|
40
|
+
const data = await readFile(path.join(templateDir, file), 'utf-8');
|
|
41
|
+
const templateName = file.replace('.md', '').replace(/[^a-zA-Z0-9]/g, '_');
|
|
42
|
+
resolve({ [templateName]: data });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const allTemplates = await Promise.all(readFilePromises);
|
|
47
|
+
|
|
48
|
+
const templates = allTemplates.reduce((acc, template) => {
|
|
49
|
+
return { ...acc, ...template };
|
|
50
|
+
}, {});
|
|
51
|
+
|
|
52
|
+
return { simple: simpleTemplate, ...templates };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -25,10 +25,21 @@ module.exports = class ExtensionPlugin extends Plugin {
|
|
|
25
25
|
'properties',
|
|
26
26
|
'card'
|
|
27
27
|
)
|
|
28
|
+
this.boardPropertiesFunction = this.loadExtensionModule(
|
|
29
|
+
() => {
|
|
30
|
+
return {}
|
|
31
|
+
},
|
|
32
|
+
'properties',
|
|
33
|
+
'board'
|
|
34
|
+
)
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
getCardProperties(task) {
|
|
31
|
-
return this.cardPropertiesFunction(task
|
|
38
|
+
return this.cardPropertiesFunction(task)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getBoardProperties() {
|
|
42
|
+
return this.boardPropertiesFunction()
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
getCardActions(task) {
|
|
@@ -13,7 +13,7 @@ module.exports = class PluginManager extends Emitter {
|
|
|
13
13
|
this.project = project
|
|
14
14
|
this.defaultPlugins = [
|
|
15
15
|
'./persist-tags-plugin',
|
|
16
|
-
'./default-
|
|
16
|
+
'./default-board-properties-plugin',
|
|
17
17
|
'./default-board-actions-plugin',
|
|
18
18
|
'./archive-plugin',
|
|
19
19
|
'./epic-plugin',
|
|
@@ -229,7 +229,7 @@ module.exports = class PluginManager extends Emitter {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
pluginError(method, pluginInstance, error) {
|
|
232
|
-
console.
|
|
232
|
+
console.warn(
|
|
233
233
|
`Plugin: ${this.getPluginName(
|
|
234
234
|
pluginInstance
|
|
235
235
|
)} threw an error on ${method}: `,
|
|
@@ -239,7 +239,7 @@ module.exports = class PluginManager extends Emitter {
|
|
|
239
239
|
|
|
240
240
|
async onBoardUpdate(lists) {
|
|
241
241
|
if (!lists || lists.length == 0) return
|
|
242
|
-
this.eachPluginAsync(async ({ pluginInstance }) => {
|
|
242
|
+
await this.eachPluginAsync(async ({ pluginInstance }) => {
|
|
243
243
|
// const timeLabel = `${this.getPluginName(pluginInstance)} onBoardUpdate time`
|
|
244
244
|
// console.time(timeLabel)
|
|
245
245
|
try {
|
|
@@ -252,10 +252,10 @@ module.exports = class PluginManager extends Emitter {
|
|
|
252
252
|
return lists
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
onBeforeBoardUpdate() {
|
|
256
|
-
this.
|
|
255
|
+
async onBeforeBoardUpdate() {
|
|
256
|
+
await this.eachPluginAsync(async ({ pluginInstance }) => {
|
|
257
257
|
try {
|
|
258
|
-
pluginInstance.onBeforeBoardUpdate()
|
|
258
|
+
await pluginInstance.onBeforeBoardUpdate()
|
|
259
259
|
} catch (e) {
|
|
260
260
|
this.pluginError('onBeforeBoardUpdate', pluginInstance, e)
|
|
261
261
|
}
|
|
@@ -320,6 +320,19 @@ module.exports = class PluginManager extends Emitter {
|
|
|
320
320
|
return cardProps
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
getBoardProperties() {
|
|
324
|
+
let boardProps = {}
|
|
325
|
+
this.eachPlugin(({ pluginInstance }) => {
|
|
326
|
+
try {
|
|
327
|
+
const pluginProps = pluginInstance.getBoardProperties ? pluginInstance.getBoardProperties() : {}
|
|
328
|
+
boardProps = { ...boardProps, ...pluginProps }
|
|
329
|
+
} catch (e) {
|
|
330
|
+
this.pluginError('getBoardProperties', pluginInstance, e)
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
return boardProps
|
|
334
|
+
}
|
|
335
|
+
|
|
323
336
|
getCardActions(task) {
|
|
324
337
|
let cardLinks = []
|
|
325
338
|
this.eachPlugin(({ pluginInstance }) => {
|
package/lib/project.js
CHANGED
|
@@ -3,7 +3,7 @@ const PluginManager = require('./plugins/plugin-manager')
|
|
|
3
3
|
const Repository = require('./repository')
|
|
4
4
|
const _cloneDeep = require('lodash.clonedeep')
|
|
5
5
|
const newCard = require('./card')
|
|
6
|
-
const { JOURNAL_TYPE } = require('./constants')
|
|
6
|
+
const { JOURNAL_TYPE, CONFIG_DIR } = require('./constants')
|
|
7
7
|
const _path = require('path')
|
|
8
8
|
const moment = require('moment')
|
|
9
9
|
const { getIsoDateWithOffset } = require('./adapters/date-time')
|
|
@@ -11,11 +11,13 @@ const fileGateway = require('./adapters/file-gateway')
|
|
|
11
11
|
const matter = require('gray-matter')
|
|
12
12
|
const _isObject = require('lodash.isobject')
|
|
13
13
|
const _isString = require('lodash.isstring')
|
|
14
|
+
const _isFunction = require('lodash.isfunction')
|
|
14
15
|
const exec = require('child_process').exec
|
|
15
16
|
const fastSort = require('fast-sort/dist/sort.js')
|
|
16
17
|
const Task = require('./task')
|
|
17
18
|
const eol = require('eol')
|
|
18
19
|
const { renderMarkdown, extractWikilinkTopics } = require('./adapters/markdown')
|
|
20
|
+
const { getFunctionSignature } = require('./adapters/parsers/function-parser')
|
|
19
21
|
|
|
20
22
|
function calculateTotals(lists) {
|
|
21
23
|
const totals = {}
|
|
@@ -97,6 +99,28 @@ module.exports = class WorkerProject extends Project {
|
|
|
97
99
|
return { path: this.path }
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
getListsForImdoneJSON(totals) {
|
|
103
|
+
return this.allLists.map((list) => {
|
|
104
|
+
list = { ...list }
|
|
105
|
+
list.tasks = list.tasks.map((card, index) => {
|
|
106
|
+
card.interpretedContent = ''
|
|
107
|
+
card.totals = totals
|
|
108
|
+
card.index = index
|
|
109
|
+
return card
|
|
110
|
+
})
|
|
111
|
+
return list
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getInitializedCards(allLists, totals) {
|
|
116
|
+
return allLists
|
|
117
|
+
.map((list) => list.tasks)
|
|
118
|
+
.flat()
|
|
119
|
+
.map(
|
|
120
|
+
(card) => card.init(totals)
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
async toImdoneJSON() {
|
|
101
125
|
this.pluginManager.initDevMode()
|
|
102
126
|
console.time('toJSON time')
|
|
@@ -106,26 +130,17 @@ module.exports = class WorkerProject extends Project {
|
|
|
106
130
|
populateFiltered: true,
|
|
107
131
|
})
|
|
108
132
|
)
|
|
109
|
-
|
|
110
|
-
allLists = allLists.map((list) => {
|
|
111
|
-
list.tasks = list.tasks.map((card, index) => {
|
|
112
|
-
card.interpretedContent = ''
|
|
113
|
-
card.totals = totals
|
|
114
|
-
card.index = index
|
|
115
|
-
return card
|
|
116
|
-
})
|
|
117
|
-
return list
|
|
118
|
-
})
|
|
133
|
+
const allLists = this.getListsForImdoneJSON(totals)
|
|
119
134
|
|
|
120
135
|
console.time('plugin onBeforeBoardUpdate')
|
|
121
|
-
this.pluginManager.onBeforeBoardUpdate()
|
|
136
|
+
await this.pluginManager.onBeforeBoardUpdate()
|
|
122
137
|
console.timeEnd('plugin onBeforeBoardUpdate')
|
|
123
138
|
|
|
139
|
+
const data = this.data = this.pluginManager.getBoardProperties()
|
|
140
|
+
const dataKeys = this.dataKays = this.getDataKeys(data)
|
|
141
|
+
|
|
124
142
|
console.time('card init')
|
|
125
|
-
const cards = allLists
|
|
126
|
-
.map((list) => list.tasks)
|
|
127
|
-
.flat()
|
|
128
|
-
.map((card) => card.init(totals))
|
|
143
|
+
const cards = this.getInitializedCards(allLists, totals)
|
|
129
144
|
console.timeEnd('card init')
|
|
130
145
|
|
|
131
146
|
console.time('plugin onBoardUpdate')
|
|
@@ -140,6 +155,7 @@ module.exports = class WorkerProject extends Project {
|
|
|
140
155
|
tasks: this.getCards(this.filter, cards),
|
|
141
156
|
populateFiltered: true,
|
|
142
157
|
})
|
|
158
|
+
|
|
143
159
|
console.timeEnd('toJSON time')
|
|
144
160
|
return {
|
|
145
161
|
path: this.path,
|
|
@@ -156,6 +172,8 @@ module.exports = class WorkerProject extends Project {
|
|
|
156
172
|
defaultFilter: this.defaultFilter,
|
|
157
173
|
actions: this.boardActions,
|
|
158
174
|
plugins: this.pluginManager.getPlugins(),
|
|
175
|
+
data,
|
|
176
|
+
dataKeys,
|
|
159
177
|
queryProps: this.getQueryProps(cards),
|
|
160
178
|
}
|
|
161
179
|
}
|
|
@@ -171,6 +189,10 @@ module.exports = class WorkerProject extends Project {
|
|
|
171
189
|
if (this.pluginManager) this.pluginManager.destroyPlugins()
|
|
172
190
|
}
|
|
173
191
|
|
|
192
|
+
get configDir() {
|
|
193
|
+
return _path.join(this.path, CONFIG_DIR)
|
|
194
|
+
}
|
|
195
|
+
|
|
174
196
|
get allTopics() {
|
|
175
197
|
return [...this.repo.allTopics]
|
|
176
198
|
}
|
|
@@ -209,6 +231,23 @@ module.exports = class WorkerProject extends Project {
|
|
|
209
231
|
return this._updatedAt
|
|
210
232
|
}
|
|
211
233
|
|
|
234
|
+
getDataKeys(data) {
|
|
235
|
+
const keys = Object.keys(data).map((key) => {
|
|
236
|
+
const value = data[key]
|
|
237
|
+
if (_isFunction(value)) {
|
|
238
|
+
key = getFunctionSignature(value)
|
|
239
|
+
}
|
|
240
|
+
return key
|
|
241
|
+
})
|
|
242
|
+
keys.forEach((key) => {
|
|
243
|
+
const value = data[key]
|
|
244
|
+
if (_isObject(value) && !Array.isArray(value)) {
|
|
245
|
+
keys.push(...Object.keys(value).map((k) => `${key}.${k}`))
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
return keys
|
|
249
|
+
}
|
|
250
|
+
|
|
212
251
|
removeList(list) {
|
|
213
252
|
this.repo.removeList(list)
|
|
214
253
|
}
|
|
@@ -218,18 +257,18 @@ module.exports = class WorkerProject extends Project {
|
|
|
218
257
|
return Repository.getTasksByList(this.repo, tasks, true, populateFiltered)
|
|
219
258
|
}
|
|
220
259
|
|
|
221
|
-
getTaskQueryProps(
|
|
260
|
+
getTaskQueryProps(props) {
|
|
222
261
|
const queryProps = []
|
|
223
|
-
if (
|
|
262
|
+
if (props) {
|
|
224
263
|
// add all properties of the task to the queryProps array
|
|
225
|
-
Object.keys(
|
|
264
|
+
Object.keys(props).forEach((key) => {
|
|
226
265
|
if (key === 'data') return
|
|
227
266
|
if (queryProps.includes(key)) return
|
|
228
267
|
|
|
229
268
|
queryProps.push(key)
|
|
230
269
|
|
|
231
|
-
if (_isObject(
|
|
232
|
-
Object.keys(
|
|
270
|
+
if (_isObject(props[key])) {
|
|
271
|
+
Object.keys(props[key]).forEach((subKey) => {
|
|
233
272
|
if (!queryProps.includes(`${key}.${subKey}`))
|
|
234
273
|
queryProps.push(`${key}.${subKey}`)
|
|
235
274
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imdone-core",
|
|
3
|
-
"version": "1.53.
|
|
3
|
+
"version": "1.53.8",
|
|
4
4
|
"description": "imdone-core",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"find-up": "^5.0.0",
|
|
58
58
|
"gray-matter": "^4.0.2",
|
|
59
59
|
"ignore": "^5.2.0",
|
|
60
|
-
"imdone-api": "^1.
|
|
60
|
+
"imdone-api": "^1.53.0",
|
|
61
61
|
"isbinaryfile": "^3.0.2",
|
|
62
62
|
"js-yaml": "^3.14.1",
|
|
63
63
|
"json-fns": "^1.0.0",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
const {getIsoDateWithOffset} = require('../adapters/date-time')
|
|
3
|
-
|
|
4
|
-
module.exports = class DefaultCardPropertiesPlugin extends Plugin {
|
|
5
|
-
constructor(project) {
|
|
6
|
-
super(project)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
getCardProperties() {
|
|
10
|
-
const self = this;
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
date: `${getIsoDateWithOffset(new Date()).substring(0, 10)}`,
|
|
14
|
-
timestamp: getIsoDateWithOffset(new Date()),
|
|
15
|
-
clearFilterURL: self.getFilterURL(''),
|
|
16
|
-
getFilterURL: (filter) => self.getFilterURL(filter),
|
|
17
|
-
getFilterLink: (filter) => `[Filter By: ${filter}](${self.getFilterURL(filter)})`
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getFilterURL(filter) {
|
|
22
|
-
return `imdone://${this.project.path}?filter=${filter}`
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
}
|