imdone-core 1.46.2 → 1.47.0
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/.imdoneignore +1 -0
- package/lib/ProjectContext.js +1 -1
- package/lib/adapters/file-gateway.js +2 -2
- package/lib/adapters/parsers/task/CardContentParser.js +42 -12
- package/lib/adapters/parsers/task/readme.md +6 -0
- package/lib/config.js +50 -2
- package/lib/default-settings.js +1 -0
- package/lib/file.js +38 -54
- package/lib/mixins/repo-fs-store.js +1 -16
- package/lib/plugins/archive-plugin.js +6 -1
- package/lib/plugins/plugin-manager.js +37 -26
- package/lib/project.js +2 -0
- package/lib/repository.js +12 -15
- package/lib/task.js +5 -11
- package/lib/usecases/get-tasks-in-file.js +27 -0
- package/package.json +3 -2
- package/tasks.md +0 -21
package/.imdoneignore
CHANGED
package/lib/ProjectContext.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const FileProjectContext = require('./domain/entities/FileProjectContext')
|
|
2
|
-
const { isNumber } = require('./task')
|
|
2
|
+
const { isNumber } = require('./adapters/parsers/task/CardContentParser')
|
|
3
3
|
|
|
4
4
|
module.exports = class ProjectContext extends FileProjectContext {
|
|
5
5
|
constructor(repo) {
|
|
@@ -5,24 +5,35 @@ const FILE_TYPES = {
|
|
|
5
5
|
MARKDOWN: 'markdown',
|
|
6
6
|
CODE: 'code',
|
|
7
7
|
}
|
|
8
|
+
const TASK_TYPES = {
|
|
9
|
+
CODE: 'CODE',
|
|
10
|
+
HASHTAG: 'HASHTAG',
|
|
11
|
+
MARKDOWN: 'MARKDOWN',
|
|
12
|
+
}
|
|
8
13
|
|
|
14
|
+
const DEFAULT_TOKEN_PREFIX = '#'
|
|
9
15
|
const START_TAG = '<card>'
|
|
10
16
|
const END_TAG = '</card>'
|
|
11
17
|
const CODE_STYLE_PATTERN = '([A-Z]+[A-Z-_]+?)((:)(-?[\\d.]+(?:e-?\\d+)?)?)?[ \\t]+(.+)$'
|
|
12
18
|
const LIST_NAME_PATTERN = '[\\p{L}0-9-_]{2,}' // [a-zA-Z-_]+?
|
|
13
|
-
const HASH_STYLE_REGEX = new XRegExp(
|
|
14
|
-
`#(${LIST_NAME_PATTERN})(:(-?[\\d.]+(?:e-?\\d+)?)?)?[ \\t]+(.+)$`,
|
|
15
|
-
'gm'
|
|
16
|
-
)
|
|
17
|
-
const HASH_STYLE_META_ORDER_REGEX = new XRegExp(
|
|
18
|
-
`#(${LIST_NAME_PATTERN})[ \\t]+(.+)$`, 'gm'
|
|
19
|
-
)
|
|
20
19
|
const LINK_STYLE_REGEX = new XRegExp(
|
|
21
20
|
`(\\[.*\\]\\s?)?(\\[(.+)\\]\\(#(${LIST_NAME_PATTERN})(:)(-?[\\d.]+(?:e-?\\d+)?)?\\))`,
|
|
22
21
|
'gm'
|
|
23
22
|
)
|
|
24
23
|
|
|
25
24
|
const CHECK_REGEX = /^(\s*- )\[([x ])\]/
|
|
25
|
+
|
|
26
|
+
function getHashStyleRegex(tokenPrefix = DEFAULT_TOKEN_PREFIX, metaOrder = false) {
|
|
27
|
+
return metaOrder ?
|
|
28
|
+
new XRegExp(
|
|
29
|
+
`${tokenPrefix}(${LIST_NAME_PATTERN})[ \\t]+(.+)$`, 'gm'
|
|
30
|
+
) :
|
|
31
|
+
new XRegExp(
|
|
32
|
+
`${tokenPrefix}(${LIST_NAME_PATTERN})(:(-?[\\d.]+(?:e-?\\d+)?)?)?[ \\t]+(.+)$`,
|
|
33
|
+
'gm'
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
function getCheckedData(content) {
|
|
27
38
|
const taskRegex = new RegExp(CHECK_REGEX)
|
|
28
39
|
const result = taskRegex.exec(content)
|
|
@@ -65,10 +76,10 @@ function isCheckBoxTask (config, line, beforeText) {
|
|
|
65
76
|
function hasTaskInText(config, text, isCodeFile) {
|
|
66
77
|
return (
|
|
67
78
|
(isCodeFile && hasCodeStyleTask(config, text)) ||
|
|
68
|
-
((new XRegExp(
|
|
69
|
-
new XRegExp(
|
|
79
|
+
((new XRegExp(getHashStyleRegex(config.tokenPrefix)).test(text) ||
|
|
80
|
+
new XRegExp(getHashStyleRegex(config.tokenPrefix, true)).test(text) ||
|
|
70
81
|
new XRegExp(LINK_STYLE_REGEX).test(text)) &&
|
|
71
|
-
config.lists.find((list) => text.includes(
|
|
82
|
+
config.lists.find((list) => text.includes(`${config.tokenPrefix}${list.name}`)))
|
|
72
83
|
)
|
|
73
84
|
}
|
|
74
85
|
|
|
@@ -276,15 +287,34 @@ function getTaskContent ({
|
|
|
276
287
|
getTextFileTaskContent({ config, content, beforeText, fileType })
|
|
277
288
|
}
|
|
278
289
|
|
|
290
|
+
function getRawTask ({tokenPrefix = DEFAULT_TOKEN_PREFIX, orderMeta, beforeText = '', hasColon = false, list, order= '', text, type}) {
|
|
291
|
+
if (type === TASK_TYPES.MARKDOWN) {
|
|
292
|
+
return `${beforeText}[${text}](${tokenPrefix}${list}:${
|
|
293
|
+
orderMeta ? '' : order
|
|
294
|
+
})`
|
|
295
|
+
}
|
|
296
|
+
const colon = hasColon || (isNumber(order) && !orderMeta) ? ':' : '';
|
|
297
|
+
return `${beforeText}${tokenPrefix}${list}${colon}${
|
|
298
|
+
orderMeta ? '' : order
|
|
299
|
+
} ${text}`
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function isNumber (value) {
|
|
303
|
+
return !isNaN(parseFloat(value)) && isFinite(value)
|
|
304
|
+
}
|
|
305
|
+
|
|
279
306
|
module.exports = {
|
|
280
307
|
FILE_TYPES,
|
|
308
|
+
TASK_TYPES,
|
|
281
309
|
getTaskContent,
|
|
310
|
+
getRawTask,
|
|
282
311
|
isBeforeTextMarkdownList,
|
|
283
312
|
padDescription,
|
|
284
313
|
getCheckedData,
|
|
314
|
+
hasTaskInText,
|
|
315
|
+
isNumber,
|
|
316
|
+
getHashStyleRegex,
|
|
285
317
|
CHECK_REGEX,
|
|
286
318
|
LIST_NAME_PATTERN,
|
|
287
|
-
HASH_STYLE_REGEX,
|
|
288
|
-
HASH_STYLE_META_ORDER_REGEX,
|
|
289
319
|
LINK_STYLE_REGEX
|
|
290
320
|
}
|
package/lib/config.js
CHANGED
|
@@ -3,7 +3,19 @@
|
|
|
3
3
|
const _cloneDeep = require('lodash.clonedeep')
|
|
4
4
|
const _assign = require('lodash.assign')
|
|
5
5
|
const _get = require('lodash.get')
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
JOURNAL_TYPE,
|
|
8
|
+
DEFAULT_CONFIG,
|
|
9
|
+
CONFIG_FILE_YML,
|
|
10
|
+
CONFIG_DIR
|
|
11
|
+
} = require('./constants')
|
|
12
|
+
const _path = require('path')
|
|
13
|
+
const findUp = require('find-up')
|
|
14
|
+
const { loadYAML } = require('./adapters/yaml')
|
|
15
|
+
const {
|
|
16
|
+
exists,
|
|
17
|
+
readFile,
|
|
18
|
+
} = require('./adapters/file-gateway')
|
|
7
19
|
|
|
8
20
|
/**
|
|
9
21
|
* Description
|
|
@@ -187,6 +199,10 @@ class Config {
|
|
|
187
199
|
return _get(this, 'settings.cards.archiveCompleted', false)
|
|
188
200
|
}
|
|
189
201
|
|
|
202
|
+
get tokenPrefix() {
|
|
203
|
+
return _get(this, 'settings.cards.tokenPrefix', '#')
|
|
204
|
+
}
|
|
205
|
+
|
|
190
206
|
get doneList() {
|
|
191
207
|
return this.getDoneList()
|
|
192
208
|
}
|
|
@@ -209,5 +225,37 @@ class Config {
|
|
|
209
225
|
}
|
|
210
226
|
}
|
|
211
227
|
|
|
212
|
-
Config.newDefaultConfig = (config = {}) => new Config(
|
|
228
|
+
Config.newDefaultConfig = (config = {}) => new Config(
|
|
229
|
+
{
|
|
230
|
+
...DEFAULT_CONFIG,
|
|
231
|
+
lists: [
|
|
232
|
+
...DEFAULT_CONFIG.lists
|
|
233
|
+
],
|
|
234
|
+
...config
|
|
235
|
+
}
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
Config.findImdonePath = async (cwd) => {
|
|
239
|
+
const configDir = await findUp(CONFIG_DIR, { cwd, type: 'directory' })
|
|
240
|
+
return _path.dirname(configDir)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
Config.getYamlConfig = async (filePath) => {
|
|
244
|
+
if (!(await exists(filePath))) return
|
|
245
|
+
const configData = await readFile(filePath, 'utf-8')
|
|
246
|
+
let configLike = {}
|
|
247
|
+
try {
|
|
248
|
+
configLike = loadYAML(configData.toString())
|
|
249
|
+
} catch (e) {
|
|
250
|
+
/* noop */
|
|
251
|
+
}
|
|
252
|
+
return configLike
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
Config.load = async (imdonePath) => {
|
|
256
|
+
const configPath = _path.join(imdonePath, CONFIG_FILE_YML)
|
|
257
|
+
const configLike = await Config.getYamlConfig(configPath)
|
|
258
|
+
return new Config(configLike)
|
|
259
|
+
}
|
|
260
|
+
|
|
213
261
|
module.exports = Config
|
package/lib/default-settings.js
CHANGED
package/lib/file.js
CHANGED
|
@@ -24,14 +24,14 @@ var _clone = require('lodash.clone'),
|
|
|
24
24
|
{
|
|
25
25
|
FILE_TYPES,
|
|
26
26
|
getTaskContent,
|
|
27
|
+
getRawTask,
|
|
28
|
+
getHashStyleRegex,
|
|
29
|
+
hasTaskInText,
|
|
27
30
|
LIST_NAME_PATTERN,
|
|
28
|
-
HASH_STYLE_REGEX,
|
|
29
|
-
HASH_STYLE_META_ORDER_REGEX,
|
|
30
31
|
LINK_STYLE_REGEX,
|
|
31
32
|
} = require('./adapters/parsers/task/CardContentParser')
|
|
32
33
|
|
|
33
34
|
const appContext = require('./context/ApplicationContext')
|
|
34
|
-
const { isNumber } = require('./task')
|
|
35
35
|
const { hasBlankLines } = require('./tools')
|
|
36
36
|
|
|
37
37
|
const ERRORS = {
|
|
@@ -296,6 +296,11 @@ File.prototype.transformTasks = function (config, modify) {
|
|
|
296
296
|
.forEach(task => this.transformTask({config, modify, task}))
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
// TODO Blank lines should be allowed in code tasks
|
|
300
|
+
// #imdone-1.47.0
|
|
301
|
+
// <!--
|
|
302
|
+
// order:-120
|
|
303
|
+
// -->
|
|
299
304
|
File.prototype.extractCodeStyleTasks = function (config, pos, content) {
|
|
300
305
|
var self = this
|
|
301
306
|
var codeStyleRegex = new RegExp(CODE_STYLE_PATTERN, 'gm')
|
|
@@ -346,7 +351,7 @@ File.prototype.extractCodeStyleTasks = function (config, pos, content) {
|
|
|
346
351
|
}
|
|
347
352
|
|
|
348
353
|
File.prototype.extractHashStyleTasks = function (config, pos, content) {
|
|
349
|
-
var hashStyleRegex =
|
|
354
|
+
var hashStyleRegex = getHashStyleRegex(config.tokenPrefix)
|
|
350
355
|
var lang = this.getLang()
|
|
351
356
|
var result
|
|
352
357
|
while ((result = hashStyleRegex.exec(content)) !== null) {
|
|
@@ -449,7 +454,7 @@ File.prototype.extractCheckboxTasks = function (config, pos, content) {
|
|
|
449
454
|
content: content.substring(result.index),
|
|
450
455
|
pos: posInContent,
|
|
451
456
|
})
|
|
452
|
-
task.rawTask =
|
|
457
|
+
task.rawTask = getRawTask({tokenPrefix: config.tokenPrefix, orderMeta: config.orderMeta, list, text, type})
|
|
453
458
|
tasks.push(task)
|
|
454
459
|
}
|
|
455
460
|
if (tasks) {
|
|
@@ -484,17 +489,6 @@ File.prototype.extractCheckboxTasks = function (config, pos, content) {
|
|
|
484
489
|
}
|
|
485
490
|
}
|
|
486
491
|
|
|
487
|
-
File.getRawTask = function (type, text, list, order) {
|
|
488
|
-
const TYPES = Task.Types
|
|
489
|
-
if (type === TYPES.MARKDOWN) {
|
|
490
|
-
return `[${text}](#${list}:${order})`
|
|
491
|
-
} else if (appContext().repo.config.orderMeta) {
|
|
492
|
-
return `#${list} ${text}`
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
return `#${list}:${order} ${text}`
|
|
496
|
-
}
|
|
497
|
-
|
|
498
492
|
File.prototype.extractTasks = function (config) {
|
|
499
493
|
this.tasks = []
|
|
500
494
|
if (this.isMarkDownFile()) {
|
|
@@ -628,7 +622,7 @@ File.prototype.deleteTask = function (task, config) {
|
|
|
628
622
|
config
|
|
629
623
|
)
|
|
630
624
|
} else if (task.type === Task.Types.HASHTAG) {
|
|
631
|
-
this.deleteCodeOrHashTask(
|
|
625
|
+
this.deleteCodeOrHashTask(getHashStyleRegex(config.tokenPrefix), task, config)
|
|
632
626
|
}
|
|
633
627
|
} else {
|
|
634
628
|
const fileContent = this.getContentLines()
|
|
@@ -643,19 +637,6 @@ File.prototype.deleteTask = function (task, config) {
|
|
|
643
637
|
}
|
|
644
638
|
}
|
|
645
639
|
|
|
646
|
-
File.TASK_TYPE_TEMPLATES = {
|
|
647
|
-
HASHTAG: (t, config) => {
|
|
648
|
-
const colon = t.hasColon || (isNumber(t.order) && !config.orderMeta) ? ':' : '';
|
|
649
|
-
return `${t.beforeText || ''}#${t.list}${colon}${
|
|
650
|
-
config.orderMeta ? '' : t.order
|
|
651
|
-
} ${t.text}`;
|
|
652
|
-
},
|
|
653
|
-
MARKDOWN: (t, config) =>
|
|
654
|
-
`${t.beforeText || ''}[${t.text}](#${t.list}:${
|
|
655
|
-
config.orderMeta ? '' : t.order
|
|
656
|
-
})`,
|
|
657
|
-
}
|
|
658
|
-
|
|
659
640
|
File.prototype.modifyTask = function (task, config, noEmit) {
|
|
660
641
|
task.orderModified = true
|
|
661
642
|
task.updateOrderMeta(config)
|
|
@@ -669,7 +650,16 @@ File.prototype.modifyTask = function (task, config, noEmit) {
|
|
|
669
650
|
} else {
|
|
670
651
|
task.updateContent()
|
|
671
652
|
const fileContent = this.getContentLines()
|
|
672
|
-
let text =
|
|
653
|
+
let text = getRawTask({
|
|
654
|
+
tokenPrefix: config.tokenPrefix,
|
|
655
|
+
orderMeta: config.orderMeta,
|
|
656
|
+
beforeText: task.beforeText,
|
|
657
|
+
hasColon: task.hasColon,
|
|
658
|
+
list: task.list,
|
|
659
|
+
order: task.order,
|
|
660
|
+
text: task.text,
|
|
661
|
+
type: task.type,
|
|
662
|
+
})
|
|
673
663
|
const linesBefore = fileContent.slice(0, task.line - 1)
|
|
674
664
|
if (this.isCodeFile()) {
|
|
675
665
|
const linesBeforeLength = linesBefore.join(lineEnd).length
|
|
@@ -741,9 +731,8 @@ File.prototype.modifyCodeOrHashTask = function (re, task, config, noEmit) {
|
|
|
741
731
|
} else text = task.text
|
|
742
732
|
} else text = task.text
|
|
743
733
|
if (/[a-z]/.test(task.list)) task.type = Task.Types.HASHTAG
|
|
744
|
-
const
|
|
745
|
-
|
|
746
|
-
var taskContent = `${task.beforeText || ''}${hash}${task.list}${inLineOrder} ${text}`
|
|
734
|
+
const tokenPrefix = task.type === Task.Types.HASHTAG ? config.tokenPrefix : ''
|
|
735
|
+
var taskContent = getRawTask({tokenPrefix, orderMeta: config.orderMeta, list: task.list, order: task.order, text, type: task.type})
|
|
747
736
|
task.line = this.getLineNumber(index)
|
|
748
737
|
task.id = getTaskId(self.getPath(), task.line, task.text)
|
|
749
738
|
this.setContent(beforeContent + taskContent + afterContent)
|
|
@@ -1111,19 +1100,20 @@ File.prototype.removeTask = function (task) {
|
|
|
1111
1100
|
|
|
1112
1101
|
File.prototype.ignoreCodeBlocks = function () {
|
|
1113
1102
|
// BACKLOG:-100 This is not used, but we need a way to ignore tasks in code blocks. Maybe save position ranges
|
|
1114
|
-
|
|
1115
|
-
var
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
if (this.isMarkDownFile()) {
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
}
|
|
1126
|
-
return cleanContent
|
|
1103
|
+
// ```javascript
|
|
1104
|
+
// var cleanContent = this.content
|
|
1105
|
+
// var replacer = function (block) {
|
|
1106
|
+
// block = block.replace(new XRegExp(LINK_STYLE_REGEX), '**TASK**')
|
|
1107
|
+
// block = block.replace(getHashStyleRegex(config.tokenPrefix), '**TASK**')
|
|
1108
|
+
// return block
|
|
1109
|
+
// }
|
|
1110
|
+
// if (this.isMarkDownFile()) {
|
|
1111
|
+
// cleanContent = this.content
|
|
1112
|
+
// .replace(new RegExp(CODE_BLOCK_REGEX), replacer)
|
|
1113
|
+
// .replace(new RegExp(INLINE_CODE_REGEX), replacer)
|
|
1114
|
+
// }
|
|
1115
|
+
// return cleanContent
|
|
1116
|
+
// ```
|
|
1127
1117
|
}
|
|
1128
1118
|
|
|
1129
1119
|
File.prototype.isMarkDownFile = function () {
|
|
@@ -1261,13 +1251,7 @@ File.prototype.hasCodeStyleTask = function (config, text) {
|
|
|
1261
1251
|
}
|
|
1262
1252
|
|
|
1263
1253
|
File.prototype.hasTaskInText = function (config, text) {
|
|
1264
|
-
return (
|
|
1265
|
-
this.hasCodeStyleTask(config, text) ||
|
|
1266
|
-
((new XRegExp(HASH_STYLE_REGEX).test(text) ||
|
|
1267
|
-
new XRegExp(HASH_STYLE_META_ORDER_REGEX).test(text) ||
|
|
1268
|
-
new XRegExp(LINK_STYLE_REGEX).test(text)) &&
|
|
1269
|
-
config.lists.find((list) => text.includes(`#${list.name}`)))
|
|
1270
|
-
)
|
|
1254
|
+
return hasTaskInText(config, text, this.isCodeFile())
|
|
1271
1255
|
}
|
|
1272
1256
|
|
|
1273
1257
|
File.prototype.isInBlockComment = function (content) {
|
|
@@ -255,7 +255,7 @@ function mixin(repo, fs = require('fs')) {
|
|
|
255
255
|
cb = tools.cb(cb)
|
|
256
256
|
repo.loadIgnore()
|
|
257
257
|
// new
|
|
258
|
-
let configData = this.getYamlConfig() ||
|
|
258
|
+
let configData = this.getYamlConfig() || {}
|
|
259
259
|
repo.updateConfig(configData, cb)
|
|
260
260
|
}
|
|
261
261
|
|
|
@@ -263,21 +263,6 @@ function mixin(repo, fs = require('fs')) {
|
|
|
263
263
|
return repo.getFullPath(CONFIG_FILE)
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
repo.getJsonConfig = function () {
|
|
267
|
-
const filePath = repo.getFullPath(CONFIG_FILE)
|
|
268
|
-
if (!fs.existsSync(filePath)) return
|
|
269
|
-
const configData = fs.readFileSync(filePath)
|
|
270
|
-
let configLike = {}
|
|
271
|
-
try {
|
|
272
|
-
configLike = JSON.parse(configData.toString())
|
|
273
|
-
if (configLike.exclude) delete configLike.exclude
|
|
274
|
-
if (configLike.watcher) delete configLike.watcher
|
|
275
|
-
} catch (e) {
|
|
276
|
-
/* noop */
|
|
277
|
-
}
|
|
278
|
-
return configLike
|
|
279
|
-
}
|
|
280
|
-
|
|
281
266
|
repo.getYamlConfig = function () {
|
|
282
267
|
const filePath = repo.getFullPath(CONFIG_FILE_YML)
|
|
283
268
|
if (!fs.existsSync(filePath)) return
|
|
@@ -52,7 +52,12 @@ module.exports = class ArchivePlugin extends Plugin {
|
|
|
52
52
|
],
|
|
53
53
|
task.content
|
|
54
54
|
)
|
|
55
|
-
|
|
55
|
+
// TODO This should use the CardContentParser to get the raw task
|
|
56
|
+
// <!--
|
|
57
|
+
// #imdone-1.47.0
|
|
58
|
+
// order:-110
|
|
59
|
+
// -->
|
|
60
|
+
const taskContent = `${task.beforeText}${config.tokenPrefix}${task.list} ${content}\n\n\n`
|
|
56
61
|
|
|
57
62
|
this.fileGateway.preparePathForWriting(newPath)
|
|
58
63
|
this.fileGateway.appendFileSync(newPath, taskContent)
|
|
@@ -95,48 +95,47 @@ module.exports = class PluginManager extends Emitter {
|
|
|
95
95
|
const installPath = _path.join(this.pluginPath, name)
|
|
96
96
|
await downloadRepo(version, installPath)
|
|
97
97
|
console.log(`Done installing ${name}`)
|
|
98
|
-
this.loadPlugin(installPath)
|
|
98
|
+
await this.loadPlugin(installPath)
|
|
99
99
|
this.emit('plugin-installed', name)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
async loadPlugins() {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.exists(this.pluginPath).then((path) => {
|
|
107
|
-
if (!path) return resolve()
|
|
108
|
-
fs.readdir(this.pluginPath, { withFileTypes: true }, (err, paths) => {
|
|
109
|
-
if (err) return reject(err)
|
|
110
|
-
paths
|
|
111
|
-
.filter(
|
|
112
|
-
(entry) =>
|
|
113
|
-
entry.name !== 'node_modules' &&
|
|
114
|
-
(entry.isDirectory() || entry.isSymbolicLink())
|
|
115
|
-
)
|
|
116
|
-
.map((entry) => _path.join(this.pluginPath, entry.name))
|
|
117
|
-
.forEach((path) => {
|
|
118
|
-
this.loadPlugin(path)
|
|
119
|
-
})
|
|
120
|
-
resolve()
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
})
|
|
124
|
-
}
|
|
103
|
+
for (const pluginPath of this.defaultPlugins) {
|
|
104
|
+
await this.loadPlugin(pluginPath)
|
|
105
|
+
}
|
|
125
106
|
|
|
126
|
-
|
|
107
|
+
const path = await this.exists(this.pluginPath)
|
|
108
|
+
if (!path) return
|
|
109
|
+
const paths = await fs.promises.readdir(this.pluginPath, { withFileTypes: true })
|
|
110
|
+
const pluginPaths = paths
|
|
111
|
+
.filter(
|
|
112
|
+
(entry) =>
|
|
113
|
+
entry.name !== 'node_modules' &&
|
|
114
|
+
(entry.isDirectory() || entry.isSymbolicLink())
|
|
115
|
+
)
|
|
116
|
+
.map((entry) => _path.join(this.pluginPath, entry.name))
|
|
117
|
+
|
|
118
|
+
for (const path of pluginPaths) {
|
|
119
|
+
await this.loadPlugin(path)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async loadPlugin(path) {
|
|
127
125
|
console.log('Loading plugin: ', path)
|
|
128
126
|
try {
|
|
129
127
|
// eslint-disable-next-line
|
|
130
128
|
delete require.cache[require.resolve(path)]
|
|
131
129
|
// eslint-disable-next-line
|
|
132
130
|
const pluginClass = require(path)
|
|
133
|
-
this.createPlugin(pluginClass, path)
|
|
131
|
+
const pluginInstance = await this.createPlugin(pluginClass, path)
|
|
132
|
+
if (pluginInstance.init) await pluginInstance.init()
|
|
134
133
|
} catch (e) {
|
|
135
134
|
console.error(`Error loading plugin at: ${path}`, e)
|
|
136
135
|
}
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
createPlugin(pluginClass, path) {
|
|
138
|
+
async createPlugin(pluginClass, path) {
|
|
140
139
|
if (!this.isPlugin(pluginClass))
|
|
141
140
|
throw new Error(`${pluginClass.name} is not a plugin`)
|
|
142
141
|
const name = pluginClass.name.toString()
|
|
@@ -164,6 +163,8 @@ module.exports = class PluginManager extends Emitter {
|
|
|
164
163
|
pluginClass,
|
|
165
164
|
info,
|
|
166
165
|
}
|
|
166
|
+
|
|
167
|
+
return pluginInstance
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
destroyPlugins() {
|
|
@@ -268,6 +269,16 @@ module.exports = class PluginManager extends Emitter {
|
|
|
268
269
|
})
|
|
269
270
|
}
|
|
270
271
|
|
|
272
|
+
async onTaskFound(task) {
|
|
273
|
+
await this.eachPluginAsync(async ({ pluginInstance }) => {
|
|
274
|
+
try {
|
|
275
|
+
if (pluginInstance.onTaskFound) await pluginInstance.onTaskFound(task)
|
|
276
|
+
} catch (e) {
|
|
277
|
+
this.pluginError('onTaskFound', pluginInstance, e)
|
|
278
|
+
}
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
|
|
271
282
|
async onBeforeAddTask({path, list, content, tags, contexts, meta, useCardTemplate}) {
|
|
272
283
|
await this.eachPluginAsync(async ({ pluginInstance }) => {
|
|
273
284
|
try {
|
package/lib/project.js
CHANGED
|
@@ -62,6 +62,8 @@ module.exports = class WorkerProject extends Project {
|
|
|
62
62
|
this.repo.on(event, (data) => onChange(this, event, data))
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
+
this.repo.on('task.found', (task) => this.pluginManager.onTaskFound(task))
|
|
66
|
+
|
|
65
67
|
const promise = new Promise((resolve, reject) => {
|
|
66
68
|
this.repo.init((err, files) => {
|
|
67
69
|
if (err) {
|
package/lib/repository.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { isNumber } = require('./task')
|
|
4
|
-
|
|
5
3
|
var _get = require('lodash.get'),
|
|
6
4
|
_isObject = require('lodash.isobject'),
|
|
7
5
|
_isFunction = require('lodash.isfunction'),
|
|
@@ -37,9 +35,12 @@ var _get = require('lodash.get'),
|
|
|
37
35
|
functionRegex = require('function-regex'),
|
|
38
36
|
Task = require('./task'),
|
|
39
37
|
newCard = require('./card'),
|
|
40
|
-
{ replaceDateLanguage } = require('./adapters/parsers/DateLanguageParser')
|
|
38
|
+
{ replaceDateLanguage } = require('./adapters/parsers/DateLanguageParser'),
|
|
39
|
+
{ getRawTask, isNumber } = require('./adapters/parsers/task/CardContentParser')
|
|
40
|
+
|
|
41
41
|
|
|
42
42
|
const appContext = require('./context/ApplicationContext')
|
|
43
|
+
const get = require('lodash.get')
|
|
43
44
|
|
|
44
45
|
var ERRORS = constants.ERRORS,
|
|
45
46
|
DEFAULT_FILE_PATTERN = constants.DEFAULT_FILE_PATTERN,
|
|
@@ -1100,8 +1101,8 @@ Repository.prototype.appendTask = function({file, content, list}, cb) {
|
|
|
1100
1101
|
const description =
|
|
1101
1102
|
lines.length > 1 ? Task.padDescription(lines.slice(1), taskPrefix) : []
|
|
1102
1103
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1104
|
+
const rawTask = getRawTask({tokenPrefix: config.tokenPrefix, orderMeta: config.orderMeta, list, order, text, type: taskSyntax})
|
|
1105
|
+
const taskContent = config.orderMeta
|
|
1105
1106
|
? this.getTaskContent({
|
|
1106
1107
|
description,
|
|
1107
1108
|
order,
|
|
@@ -1111,18 +1112,14 @@ Repository.prototype.appendTask = function({file, content, list}, cb) {
|
|
|
1111
1112
|
})
|
|
1112
1113
|
: description.join(eol.lf)
|
|
1113
1114
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
} else {
|
|
1119
|
-
const inLineOrder = config.orderMeta ? '' : `:${orderString}`
|
|
1120
|
-
appendContent = `${taskPrefix}#${list}${inLineOrder} ${text}${eol.lf}${taskContent}`
|
|
1121
|
-
}
|
|
1122
|
-
appendContent = File.trimBlankLines(appendContent)
|
|
1115
|
+
let appendContent = File.trimBlankLines(
|
|
1116
|
+
`${taskPrefix}${rawTask}${eol.lf}${taskContent}`
|
|
1117
|
+
)
|
|
1118
|
+
|
|
1123
1119
|
fileContent = `${fileContent}${sep}`
|
|
1124
1120
|
const cardTerminator = "\n".repeat(2)
|
|
1125
1121
|
file.setContent(`${fileContent}${appendContent}${cardTerminator}`)
|
|
1122
|
+
|
|
1126
1123
|
this.writeAndExtract(file, true, (err, file) => {
|
|
1127
1124
|
if (err) return cb(err)
|
|
1128
1125
|
const task = file.getTasks().find(task => task.text === text && task.list === list)
|
|
@@ -1541,7 +1538,7 @@ Repository.prototype.getTasksInList = function (name, offset, limit) {
|
|
|
1541
1538
|
var tasks = _where(this.getTasks(), { list: name })
|
|
1542
1539
|
if (tasks.length === 0) return []
|
|
1543
1540
|
var allTasks = fastSort(tasks).by(DEFAULT_SORT)
|
|
1544
|
-
if (
|
|
1541
|
+
if (isNumber(offset) && isNumber(limit))
|
|
1545
1542
|
return allTasks.slice(offset, offset + limit)
|
|
1546
1543
|
return allTasks
|
|
1547
1544
|
}
|
package/lib/task.js
CHANGED
|
@@ -16,8 +16,10 @@ var _clone = require('lodash.clone'),
|
|
|
16
16
|
|
|
17
17
|
const {
|
|
18
18
|
CHECK_REGEX,
|
|
19
|
+
TASK_TYPES,
|
|
19
20
|
getCheckedData,
|
|
20
|
-
isBeforeTextMarkdownList
|
|
21
|
+
isBeforeTextMarkdownList,
|
|
22
|
+
isNumber
|
|
21
23
|
} = require('./adapters/parsers/task/CardContentParser.js')
|
|
22
24
|
|
|
23
25
|
/**
|
|
@@ -234,11 +236,7 @@ Task.prototype.getCheckedData = function () {
|
|
|
234
236
|
return getCheckedData(this.beforeText)
|
|
235
237
|
}
|
|
236
238
|
|
|
237
|
-
Task.Types =
|
|
238
|
-
CODE: 'CODE',
|
|
239
|
-
HASHTAG: 'HASHTAG',
|
|
240
|
-
MARKDOWN: 'MARKDOWN',
|
|
241
|
-
}
|
|
239
|
+
Task.Types = TASK_TYPES
|
|
242
240
|
|
|
243
241
|
Task.AnyLanguageGroup =
|
|
244
242
|
'#\\w:%/.$-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6E5\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC'
|
|
@@ -422,7 +420,7 @@ Task.getMetaOrderRegex = function (config) {
|
|
|
422
420
|
|
|
423
421
|
Task.prototype.updateOrderMeta = function (config, descContent = this.description.join(lineEnd)) {
|
|
424
422
|
if (config.orderMeta) {
|
|
425
|
-
if (!
|
|
423
|
+
if (!isNumber(this.order)) return this.order = ''
|
|
426
424
|
const addNewLine = config.isMetaNewLine()
|
|
427
425
|
const metaSep = config.getMetaSep()
|
|
428
426
|
if (this.meta.order) {
|
|
@@ -778,8 +776,4 @@ Task.prototype.equals = function (task) {
|
|
|
778
776
|
)
|
|
779
777
|
}
|
|
780
778
|
|
|
781
|
-
Task.isNumber = function(n) {
|
|
782
|
-
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
783
|
-
}
|
|
784
|
-
|
|
785
779
|
module.exports = Task
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const languages = require('../languages')
|
|
2
|
+
const Config = require('../config')
|
|
3
|
+
const File = require('../file')
|
|
4
|
+
const pluginManager = {
|
|
5
|
+
onTaskUpdate: () => {},
|
|
6
|
+
getCardProperties: () => { return {} },
|
|
7
|
+
getCardActions: () => [],
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// DOING Use task line parsers for vs code extension and obsidian plugin
|
|
11
|
+
// <!--
|
|
12
|
+
// order:-10000030
|
|
13
|
+
// -->
|
|
14
|
+
export async function getTasks({filePath, content}) {
|
|
15
|
+
const projectPath = await Config.findImdonePath(filePath)
|
|
16
|
+
const config = await Config.load(projectPath)
|
|
17
|
+
const project = { path: projectPath, config, pluginManager }
|
|
18
|
+
// var file = new File({
|
|
19
|
+
// repoId: projectPath,
|
|
20
|
+
// filePath,
|
|
21
|
+
// content,
|
|
22
|
+
// languages,
|
|
23
|
+
// project,
|
|
24
|
+
// })
|
|
25
|
+
|
|
26
|
+
// return file.extractTasks(config).getTasks()
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imdone-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"description": "imdone-core",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -56,10 +56,11 @@
|
|
|
56
56
|
"eol": "^0.9.1",
|
|
57
57
|
"escape-string-regexp": "^1.0.5",
|
|
58
58
|
"fast-sort": "^2.2.0",
|
|
59
|
+
"find-up": "^5.0.0",
|
|
59
60
|
"function-regex": "^1.0.2",
|
|
60
61
|
"gray-matter": "^4.0.2",
|
|
61
62
|
"ignore": "^5.2.0",
|
|
62
|
-
"imdone-api": "^
|
|
63
|
+
"imdone-api": "^1.47.0",
|
|
63
64
|
"isbinaryfile": "^3.0.2",
|
|
64
65
|
"js-yaml": "^3.14.1",
|
|
65
66
|
"json-fns": "^1.0.0",
|
package/tasks.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
backlog
|
|
2
|
-
====
|
|
3
|
-
|
|
4
|
-
## Ungrouped Tasks
|
|
5
|
-
|
|
6
|
-
## Phase 1
|
|
7
|
-
|
|
8
|
-
### TODO
|
|
9
|
-
|
|
10
|
-
- [ ] Another new task in a new file
|
|
11
|
-
<!-- +urgent +important @piascikj group:"Phase 1" -->
|
|
12
|
-
<!-- created:2023-09-02T03:48:18.338Z sid: -->
|
|
13
|
-
|
|
14
|
-
## Phase 2
|
|
15
|
-
|
|
16
|
-
### DOING
|
|
17
|
-
|
|
18
|
-
- [ ] Another new task in a new files
|
|
19
|
-
<!-- +urgent +important @piascikj group:"Phase 2" -->
|
|
20
|
-
<!-- created:2023-09-02T04:02:09.680Z sid: -->
|
|
21
|
-
|