imdone-core 1.47.0 → 1.47.2
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/lib/adapters/parsers/file/LocalFileParserFactory.js +20 -18
- package/lib/adapters/parsers/file/ReadStreamCodeParser.js +88 -95
- package/lib/adapters/parsers/file/ReadStreamMarkdownParser.js +8 -10
- package/lib/adapters/parsers/file/ReadStreamTaskParser.js +25 -33
- package/lib/adapters/parsers/task/CardContentParser.js +18 -8
- package/lib/adapters/parsers/task/CodeStyleTaskParser.js +2 -2
- package/lib/adapters/parsers/task/HashStyleTaskParser.js +9 -6
- package/lib/adapters/parsers/task/MarkdownStyleTaskParser.js +2 -2
- package/lib/adapters/parsers/task/TaskParser.js +2 -4
- package/lib/config.js +0 -12
- package/lib/context/StreamingApplicationContext.js +31 -0
- package/lib/plugins/archive-plugin.js +15 -7
- package/lib/repository.js +5 -4
- package/lib/usecases/get-tasks-in-file.js +20 -20
- package/package.json +2 -1
- package/lib/adapters/parsers/task/readme.md +0 -6
|
@@ -2,9 +2,9 @@ const { createReadStream } = require('fs')
|
|
|
2
2
|
const ReadStreamMarkdownParser = require('./ReadStreamMarkdownParser')
|
|
3
3
|
const path = require('path')
|
|
4
4
|
const languages = require('../../../languages')
|
|
5
|
-
const appContext = require('../../../context/ApplicationContext')
|
|
6
5
|
const ReadStreamCodeParser = require('./ReadStreamCodeParser')
|
|
7
6
|
|
|
7
|
+
|
|
8
8
|
function getLang(languages, filePath) {
|
|
9
9
|
var lang = languages[path.extname(filePath)]
|
|
10
10
|
return lang || { name: 'text', symbol: '' }
|
|
@@ -15,21 +15,23 @@ function getLanguages(config) {
|
|
|
15
15
|
return { ...languages, ...configLanguages }
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
|
|
19
|
+
module.exports.getFileParser = async function getFileParser (filePath, config, readStream) {
|
|
20
|
+
if (!readStream) {
|
|
21
|
+
readStream = createReadStream(filePath)
|
|
22
|
+
}
|
|
23
|
+
const languages = getLanguages(config)
|
|
24
|
+
const lang = getLang(languages, filePath)
|
|
25
|
+
if (lang.name === 'text') {
|
|
26
|
+
return new ReadStreamMarkdownParser(readStream, config)
|
|
27
|
+
} else {
|
|
28
|
+
const parser = new ReadStreamCodeParser(
|
|
29
|
+
readStream,
|
|
30
|
+
filePath,
|
|
31
|
+
lang,
|
|
32
|
+
config.lists
|
|
33
|
+
)
|
|
34
|
+
await parser.init()
|
|
35
|
+
return parser
|
|
36
|
+
}
|
|
35
37
|
}
|
|
@@ -1,121 +1,114 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
2
|
const ReadStreamTaskParser = require('./ReadStreamTaskParser')
|
|
3
3
|
const CodeStyleTaskParser = require('../task/CodeStyleTaskParser')
|
|
4
|
+
const languages = require('../../../languages')
|
|
4
5
|
const extractComments = require('multilang-extract-comments')
|
|
5
6
|
const eol = require('eol')
|
|
6
|
-
const ReadLine = require('readline')
|
|
7
7
|
const { Readable } = require('stream')
|
|
8
8
|
|
|
9
|
-
async function streamToString(stream) {
|
|
10
|
-
const chunks = []
|
|
11
|
-
|
|
12
|
-
for await (const chunk of stream) {
|
|
13
|
-
chunks.push(Buffer.from(chunk))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return Buffer.concat(chunks).toString('utf-8')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function stringToStream(string) {
|
|
20
|
-
const lines = eol.split(string).map((line) => line + String(eol.auto))
|
|
21
|
-
return Readable.from(lines)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
9
|
module.exports = class ReadStreamCodeParser extends ReadStreamTaskParser {
|
|
25
|
-
constructor(readStream, filePath, lang) {
|
|
10
|
+
constructor(readStream, filePath, lang, lists) {
|
|
26
11
|
super(readStream)
|
|
12
|
+
this.lists = lists
|
|
27
13
|
this.filePath = filePath
|
|
28
14
|
this.lang = lang
|
|
29
15
|
this.taskParsers = [new CodeStyleTaskParser()]
|
|
30
16
|
}
|
|
31
17
|
|
|
32
18
|
async init() {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
37
|
-
|
|
38
|
-
let line = null
|
|
39
|
-
let lines = []
|
|
40
|
-
let lineNo = 1
|
|
41
|
-
let comment = null
|
|
42
|
-
do {
|
|
43
|
-
const { value, done } = await this.readLine()
|
|
44
|
-
line = done ? null : value
|
|
45
|
-
comment = this.getCommentAtLine(lineNo)
|
|
46
|
-
let lineInComment = ''
|
|
47
|
-
if (comment) {
|
|
48
|
-
lineInComment = comment.lines[lineNo - comment.begin]
|
|
49
|
-
}
|
|
50
|
-
lines.push(lineInComment)
|
|
51
|
-
lineNo += 1
|
|
52
|
-
} while (line !== null)
|
|
53
|
-
this.readInterface.close()
|
|
54
|
-
this.readStream = Readable.from(
|
|
55
|
-
lines.map((line) => line + String(eol.auto))
|
|
56
|
-
)
|
|
57
|
-
this.readInterface = this.getReadInterface()
|
|
19
|
+
const code = await streamToString(this.readStream)
|
|
20
|
+
// TODO Getting tokens from lists should be done higher up in the controller
|
|
21
|
+
const tokens = this.lists.filter(list => !list.filter).map(list => list.name)
|
|
22
|
+
this.cards = this.parseCards(code, tokens)
|
|
58
23
|
}
|
|
59
24
|
|
|
60
25
|
async readTask() {
|
|
61
|
-
|
|
62
|
-
task.multiLineComment =
|
|
63
|
-
this.getCommentAtLine(task.line).info.type === 'multiline'
|
|
64
|
-
task.descriptionStartsWith = task.multiLineComment
|
|
65
|
-
? this.lang.block.ignore
|
|
66
|
-
: this.lang.symbol
|
|
67
|
-
|
|
68
|
-
return task
|
|
26
|
+
return this.cards.shift()
|
|
69
27
|
}
|
|
70
28
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
29
|
+
parseCards(code, tokens = ['TODO']) {
|
|
30
|
+
const comments = this.parseComments(code);
|
|
31
|
+
const cards = [];
|
|
32
|
+
|
|
33
|
+
Object.keys(comments).forEach((comment) => {
|
|
34
|
+
const { begin, end, content } = comments[comment];
|
|
35
|
+
const line = begin;
|
|
36
|
+
const lastLine = end - 1;
|
|
37
|
+
const lines = content.split('\n');
|
|
38
|
+
|
|
39
|
+
// Check if the comment contains "TODO"
|
|
40
|
+
lines.forEach(codeLine => {
|
|
41
|
+
if (tokens.find((token) => codeLine.includes(token))) {
|
|
42
|
+
// Get all lines from start to end
|
|
43
|
+
|
|
44
|
+
cards.push({
|
|
45
|
+
content,
|
|
46
|
+
line,
|
|
47
|
+
lastLine,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return cards;
|
|
75
53
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
console: false,
|
|
82
|
-
})
|
|
54
|
+
|
|
55
|
+
parseComments(code) {
|
|
56
|
+
const options = getLanguageOptions(this.filePath);
|
|
57
|
+
const comments = extractComments(code, options);
|
|
58
|
+
return comments;
|
|
83
59
|
}
|
|
60
|
+
|
|
61
|
+
}
|
|
84
62
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
const comments = extractComments(content, options)
|
|
105
|
-
const contentLines = eol.split(content)
|
|
106
|
-
return Object.values(comments).map((comment) => {
|
|
107
|
-
const lines = eol.split(comment.content)
|
|
108
|
-
const linesInContent = contentLines.slice(comment.begin - 1, comment.end)
|
|
109
|
-
let contentStartIndex = linesInContent.findIndex((line) =>
|
|
110
|
-
line.includes(lines[0])
|
|
111
|
-
)
|
|
112
|
-
for (let i = 0; i < contentStartIndex; i++) {
|
|
113
|
-
lines.unshift('')
|
|
114
|
-
}
|
|
115
|
-
return {
|
|
116
|
-
...comment,
|
|
117
|
-
lines,
|
|
63
|
+
|
|
64
|
+
function getLanguageOptions(filePath) {
|
|
65
|
+
const extension = path.extname(filePath)
|
|
66
|
+
const language = languages[extension]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
const {
|
|
70
|
+
name,
|
|
71
|
+
symbol,
|
|
72
|
+
block,
|
|
73
|
+
} = language ||
|
|
74
|
+
{
|
|
75
|
+
name: 'text',
|
|
76
|
+
symbol: '',
|
|
77
|
+
block: {
|
|
78
|
+
start: undefined,
|
|
79
|
+
end: undefined,
|
|
80
|
+
ignore: undefined,
|
|
118
81
|
}
|
|
119
|
-
}
|
|
82
|
+
};
|
|
83
|
+
// Use lang to get comment patterns
|
|
84
|
+
|
|
85
|
+
const {
|
|
86
|
+
start,
|
|
87
|
+
ignore: middle,
|
|
88
|
+
end
|
|
89
|
+
} = block || {};
|
|
90
|
+
|
|
91
|
+
return language && {
|
|
92
|
+
pattern: {
|
|
93
|
+
name,
|
|
94
|
+
nameMatchers: extension && [extension] || [],
|
|
95
|
+
singleLineComment: symbol && [{ start: symbol }] || [],
|
|
96
|
+
multiLineComment: start && end && [{ start, middle, end }] || [],
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function streamToString(stream) {
|
|
102
|
+
const chunks = []
|
|
103
|
+
|
|
104
|
+
for await (const chunk of stream) {
|
|
105
|
+
chunks.push(Buffer.from(chunk))
|
|
120
106
|
}
|
|
107
|
+
|
|
108
|
+
return Buffer.concat(chunks).toString('utf-8')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function stringToStream(string) {
|
|
112
|
+
const lines = eol.split(string).map((line) => line + String(eol.auto))
|
|
113
|
+
return Readable.from(lines)
|
|
121
114
|
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
const ReadStreamTaskParser = require('./ReadStreamTaskParser')
|
|
2
2
|
const HashStyleTaskParser = require('../task/HashStyleTaskParser')
|
|
3
3
|
const MarkdownStyleTaskParser = require('../task/MarkdownStyleTaskParser')
|
|
4
|
-
const CheckStyleTaskParser = require('../task/CheckStyleTaskParser')
|
|
5
|
-
const appContext = require('../../../context/ApplicationContext')
|
|
4
|
+
// const CheckStyleTaskParser = require('../task/CheckStyleTaskParser')
|
|
6
5
|
|
|
7
6
|
module.exports = class ReadStreamMarkdownParser extends ReadStreamTaskParser {
|
|
8
|
-
constructor(readStream) {
|
|
9
|
-
super(readStream)
|
|
10
|
-
const { config } = appContext()
|
|
7
|
+
constructor(readStream, config) {
|
|
8
|
+
super(readStream, config)
|
|
11
9
|
this.taskParsers = [
|
|
12
|
-
new HashStyleTaskParser(),
|
|
13
|
-
new MarkdownStyleTaskParser(),
|
|
10
|
+
new HashStyleTaskParser(config),
|
|
11
|
+
new MarkdownStyleTaskParser(config),
|
|
14
12
|
]
|
|
15
|
-
if (config.isAddCheckBoxTasks()) {
|
|
16
|
-
|
|
17
|
-
}
|
|
13
|
+
// if (config.isAddCheckBoxTasks()) {
|
|
14
|
+
// this.taskParsers.push(new CheckStyleTaskParser())
|
|
15
|
+
// }
|
|
18
16
|
}
|
|
19
17
|
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
const appContext = require('../../../context/ApplicationContext')
|
|
2
|
-
const Config = require('../../../config')
|
|
3
1
|
const ReadLine = require('readline')
|
|
4
|
-
const
|
|
5
|
-
const END_TAG = '</card>'
|
|
2
|
+
const blankLinesToEndTask = 2
|
|
6
3
|
|
|
7
4
|
module.exports = class ReadStreamTaskParser {
|
|
8
5
|
constructor(readStream) {
|
|
9
|
-
this.config = appContext().config
|
|
10
6
|
this.readStream = readStream
|
|
11
7
|
this.task = null
|
|
12
8
|
this.line = null
|
|
13
9
|
this.taskParsers = []
|
|
14
10
|
this.lineNo = 0
|
|
15
11
|
this.blankLines = 0
|
|
16
|
-
this.blankLinesToEndTask = this.config.blankLinesToEndTask
|
|
17
12
|
this.readInterface = ReadLine.createInterface({
|
|
18
13
|
input: this.readStream,
|
|
19
14
|
crlfDelay: Infinity,
|
|
@@ -23,9 +18,8 @@ module.exports = class ReadStreamTaskParser {
|
|
|
23
18
|
|
|
24
19
|
async readTask() {
|
|
25
20
|
let taskOrStreamDone = false
|
|
26
|
-
this.task = null
|
|
21
|
+
this.task = this.nextTask || null
|
|
27
22
|
this.blankLines = 0
|
|
28
|
-
this.hasStartTag = false
|
|
29
23
|
|
|
30
24
|
try {
|
|
31
25
|
while (!taskOrStreamDone) {
|
|
@@ -50,7 +44,7 @@ module.exports = class ReadStreamTaskParser {
|
|
|
50
44
|
throw error
|
|
51
45
|
}
|
|
52
46
|
|
|
53
|
-
this.
|
|
47
|
+
this.trimLinesToEndTask()
|
|
54
48
|
return this.task
|
|
55
49
|
}
|
|
56
50
|
|
|
@@ -59,19 +53,24 @@ module.exports = class ReadStreamTaskParser {
|
|
|
59
53
|
}
|
|
60
54
|
|
|
61
55
|
isEndOfTask(line) {
|
|
62
|
-
if (this.task && this.task.hasCardTags) return true
|
|
63
|
-
if (this.hasStartTag) return false
|
|
64
|
-
|
|
65
56
|
if (line.trim() === '') {
|
|
66
57
|
this.blankLines++
|
|
67
58
|
} else {
|
|
68
59
|
this.blankLines = 0
|
|
69
60
|
}
|
|
70
61
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
62
|
+
this.nextTask = this.getTaskFromLine(line)
|
|
63
|
+
|
|
64
|
+
if (this.blankLines > blankLinesToEndTask - 1) {
|
|
65
|
+
this.nextTask = undefined
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (this.nextTask) {
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return false
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
getTaskFromLine(line) {
|
|
@@ -84,30 +83,23 @@ module.exports = class ReadStreamTaskParser {
|
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
addLineToTask(line) {
|
|
87
|
-
|
|
88
|
-
this.hasStartTag = true
|
|
89
|
-
} else if (line.trim() === END_TAG && this.hasStartTag) {
|
|
90
|
-
this.task.hasCardTags = true
|
|
91
|
-
} else {
|
|
92
|
-
this.task.description.push(line)
|
|
93
|
-
}
|
|
94
|
-
|
|
86
|
+
this.task.description.push(line)
|
|
95
87
|
this.task.lastLine = this.lineNo
|
|
96
88
|
}
|
|
97
89
|
|
|
98
|
-
|
|
90
|
+
trimLinesToEndTask() {
|
|
99
91
|
if (!this.task) return
|
|
100
92
|
if (
|
|
101
|
-
this.blankLines ==
|
|
102
|
-
this.blankLinesToEndTask > 1 &&
|
|
103
|
-
!this.task.hasCardTags
|
|
93
|
+
this.blankLines == blankLinesToEndTask
|
|
104
94
|
) {
|
|
105
|
-
this.task.description.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.task.
|
|
95
|
+
this.task.description.length = this.task.description.length - (this.blankLines - 1)
|
|
96
|
+
} else if (this.nextTask){
|
|
97
|
+
this.task.description.length = this.task.description.length - (this.blankLines + 1)
|
|
98
|
+
} else {
|
|
99
|
+
this.task.description.length = this.task.description.length - this.blankLines
|
|
110
100
|
}
|
|
101
|
+
|
|
102
|
+
this.task.lastLine = this.task.line + this.task.description.length - 1
|
|
111
103
|
}
|
|
112
104
|
|
|
113
105
|
close() {
|
|
@@ -23,8 +23,8 @@ const LINK_STYLE_REGEX = new XRegExp(
|
|
|
23
23
|
|
|
24
24
|
const CHECK_REGEX = /^(\s*- )\[([x ])\]/
|
|
25
25
|
|
|
26
|
-
function getHashStyleRegex(tokenPrefix = DEFAULT_TOKEN_PREFIX,
|
|
27
|
-
return
|
|
26
|
+
function getHashStyleRegex(tokenPrefix = DEFAULT_TOKEN_PREFIX, orderMeta = false) {
|
|
27
|
+
return orderMeta ?
|
|
28
28
|
new XRegExp(
|
|
29
29
|
`${tokenPrefix}(${LIST_NAME_PATTERN})[ \\t]+(.+)$`, 'gm'
|
|
30
30
|
) :
|
|
@@ -287,16 +287,26 @@ function getTaskContent ({
|
|
|
287
287
|
getTextFileTaskContent({ config, content, beforeText, fileType })
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
function getRawTask ({
|
|
290
|
+
function getRawTask ({
|
|
291
|
+
tokenPrefix = DEFAULT_TOKEN_PREFIX,
|
|
292
|
+
orderMeta = true,
|
|
293
|
+
beforeText = '',
|
|
294
|
+
hasColon = false,
|
|
295
|
+
list,
|
|
296
|
+
order = '',
|
|
297
|
+
text,
|
|
298
|
+
type = TASK_TYPES.HASHTAG
|
|
299
|
+
}) {
|
|
291
300
|
if (type === TASK_TYPES.MARKDOWN) {
|
|
292
|
-
return `${beforeText}[${text}](${tokenPrefix}${list}:${
|
|
301
|
+
return `${beforeText || ''}[${text}](${tokenPrefix}${list}:${
|
|
293
302
|
orderMeta ? '' : order
|
|
294
303
|
})`
|
|
304
|
+
} else {
|
|
305
|
+
const colon = hasColon || (isNumber(order) && !orderMeta) ? ':' : '';
|
|
306
|
+
return `${beforeText || ''}${tokenPrefix}${list}${colon}${
|
|
307
|
+
orderMeta ? '' : order
|
|
308
|
+
} ${text}`
|
|
295
309
|
}
|
|
296
|
-
const colon = hasColon || (isNumber(order) && !orderMeta) ? ':' : '';
|
|
297
|
-
return `${beforeText}${tokenPrefix}${list}${colon}${
|
|
298
|
-
orderMeta ? '' : order
|
|
299
|
-
} ${text}`
|
|
300
310
|
}
|
|
301
311
|
|
|
302
312
|
function isNumber (value) {
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
const TaskParser = require('./TaskParser')
|
|
2
|
+
const { getHashStyleRegex } = require('./CardContentParser')
|
|
2
3
|
|
|
3
4
|
module.exports = class HashStyleTaskParser extends TaskParser {
|
|
4
|
-
constructor() {
|
|
5
|
-
super('HASHTAG')
|
|
5
|
+
constructor(config) {
|
|
6
|
+
super('HASHTAG', config)
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
get pattern() {
|
|
9
|
-
|
|
10
|
+
const config = this.config
|
|
11
|
+
return getHashStyleRegex(config.tokenPrefix, config.orderMeta)
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
parse(lineContent, line, matchResult) {
|
|
13
|
-
const [
|
|
15
|
+
const [rawTask, list, orderGroup, order, text] = matchResult
|
|
16
|
+
|
|
14
17
|
return {
|
|
15
|
-
beforeText,
|
|
18
|
+
// beforeText,
|
|
16
19
|
text,
|
|
17
20
|
order,
|
|
18
21
|
list,
|
|
19
22
|
line,
|
|
20
|
-
colon,
|
|
23
|
+
colon: orderGroup && orderGroup.startsWith(':'),
|
|
21
24
|
type: this.type,
|
|
22
25
|
}
|
|
23
26
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const Config = require('../../../config')
|
|
2
|
-
const appContext = require('../../../context/ApplicationContext')
|
|
3
1
|
|
|
4
2
|
class Task {
|
|
5
3
|
constructor({ beforeText, text, list, line, order, checked, colon, type }) {
|
|
@@ -17,8 +15,8 @@ class Task {
|
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
module.exports = class TaskParser {
|
|
20
|
-
constructor(type) {
|
|
21
|
-
this.config =
|
|
18
|
+
constructor(type, config) {
|
|
19
|
+
this.config = config
|
|
22
20
|
this.type = type
|
|
23
21
|
}
|
|
24
22
|
|
package/lib/config.js
CHANGED
|
@@ -207,18 +207,6 @@ class Config {
|
|
|
207
207
|
return this.getDoneList()
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
get blankLinesToEndTask() {
|
|
211
|
-
let blankLinesToEndTask = Math.round(
|
|
212
|
-
_get(this, 'settings.cards.blankLinesToEndTask', 1)
|
|
213
|
-
)
|
|
214
|
-
if (blankLinesToEndTask > 2) {
|
|
215
|
-
blankLinesToEndTask = 2
|
|
216
|
-
} else if (blankLinesToEndTask < 1) {
|
|
217
|
-
blankLinesToEndTask = 1
|
|
218
|
-
}
|
|
219
|
-
return blankLinesToEndTask
|
|
220
|
-
}
|
|
221
|
-
|
|
222
210
|
getMetaSep() {
|
|
223
211
|
const metaSep = _get(this, 'settings.cards.metaSep', COLON)
|
|
224
212
|
return META_SEPS.includes(metaSep) ? metaSep : COLON
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const Config = require('../config')
|
|
2
|
+
|
|
3
|
+
class ApplicationContext {
|
|
4
|
+
constructor({
|
|
5
|
+
project,
|
|
6
|
+
repo,
|
|
7
|
+
projectContext,
|
|
8
|
+
projectReader,
|
|
9
|
+
projectPresenter,
|
|
10
|
+
}) {
|
|
11
|
+
this.project = project;
|
|
12
|
+
this.repo = repo;
|
|
13
|
+
this.projectContext = projectContext;
|
|
14
|
+
this.projectReader = projectReader;
|
|
15
|
+
this.projectPresenter = projectPresenter;
|
|
16
|
+
this.innerConfig = Config.newDefaultConfig()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
set config(config) {
|
|
20
|
+
this.innerConfig = config
|
|
21
|
+
this.repo && (this.repo.config = config)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get config() {
|
|
25
|
+
return (this.repo && this.repo.config) || this.innerConfig
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
const context = new ApplicationContext({})
|
|
30
|
+
|
|
31
|
+
module.exports = () => context
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const Plugin = require('imdone-api')
|
|
2
2
|
const path = require('path')
|
|
3
|
+
const { getRawTask } = require('../adapters/parsers/task/CardContentParser')
|
|
3
4
|
|
|
4
5
|
module.exports = class ArchivePlugin extends Plugin {
|
|
5
6
|
constructor(project) {
|
|
@@ -14,24 +15,28 @@ module.exports = class ArchivePlugin extends Plugin {
|
|
|
14
15
|
return this.project.fileGateway
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
onBeforeBoardUpdate() {
|
|
18
|
+
async onBeforeBoardUpdate() {
|
|
18
19
|
const config = this.config
|
|
19
20
|
if (!config || !config.archiveCompleted || this.archivingTasks) return
|
|
20
21
|
this.archivingTasks = true
|
|
21
22
|
const cards = this.project.getAllCards(`meta.archived != "true" and list = ${config.doneList}`)
|
|
22
23
|
const messageUser = cards.length > 1
|
|
24
|
+
|
|
23
25
|
if (!cards.length) {
|
|
24
26
|
this.archivingTasks = false
|
|
25
27
|
return
|
|
26
28
|
} else {
|
|
27
29
|
if (messageUser) this.project.snackBar({message: `Archiving ${cards.length} card(s)...`})
|
|
28
30
|
}
|
|
31
|
+
|
|
29
32
|
cards.forEach(card => this.archiveTask(card))
|
|
33
|
+
|
|
30
34
|
if (messageUser) this.project.snackBar({message: ` Done archiving ${cards.length} card(s). Deleting original(s)...`})
|
|
31
|
-
this.project.deleteTasks(cards)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
})
|
|
35
|
+
await this.project.deleteTasks(cards)
|
|
36
|
+
|
|
37
|
+
this.archivingTasks = false
|
|
38
|
+
if (messageUser) this.project.snackBar({message: `Done deleting original card(s).`})
|
|
39
|
+
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
archiveTask (task, config = this.config) {
|
|
@@ -57,8 +62,11 @@ module.exports = class ArchivePlugin extends Plugin {
|
|
|
57
62
|
// #imdone-1.47.0
|
|
58
63
|
// order:-110
|
|
59
64
|
// -->
|
|
60
|
-
const
|
|
61
|
-
|
|
65
|
+
const { tokenPrefix } = config
|
|
66
|
+
const { beforeText, list } = task
|
|
67
|
+
const taskStart = getRawTask({tokenPrefix, beforeText, list, text: ''})
|
|
68
|
+
const taskContent = `${taskStart} ${content}\n\n\n`
|
|
69
|
+
|
|
62
70
|
this.fileGateway.preparePathForWriting(newPath)
|
|
63
71
|
this.fileGateway.appendFileSync(newPath, taskContent)
|
|
64
72
|
}
|
package/lib/repository.js
CHANGED
|
@@ -465,6 +465,7 @@ Repository.prototype.addFile = function (file, cb) {
|
|
|
465
465
|
if (this.destroyed) return cb(new Error('destroyed'))
|
|
466
466
|
var self = this
|
|
467
467
|
this.fileOK(file, function (err, ok) {
|
|
468
|
+
if (err) return cb(err)
|
|
468
469
|
if (ok) {
|
|
469
470
|
var index = self.files.findIndex(({ path }) => path === file.path)
|
|
470
471
|
if (index > -1) {
|
|
@@ -945,10 +946,10 @@ Repository.prototype.writeAndExtract = function (file, emit, cb) {
|
|
|
945
946
|
if (err)
|
|
946
947
|
return cb(new Error('Unable to extract tasks for file:' + file.path))
|
|
947
948
|
this.addFile(file, (err) => {
|
|
948
|
-
if (err)
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
949
|
+
if (err) {
|
|
950
|
+
err.message = `Unable to add file after extracting tasks: #{file.path}\n${err.message}`
|
|
951
|
+
return cb(err)
|
|
952
|
+
}
|
|
952
953
|
cb(null, file)
|
|
953
954
|
})
|
|
954
955
|
})
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
const languages = require('../languages')
|
|
2
1
|
const Config = require('../config')
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
getCardProperties: () => { return {} },
|
|
7
|
-
getCardActions: () => [],
|
|
8
|
-
}
|
|
2
|
+
const { getFileParser } = require('../adapters/parsers/file/LocalFileParserFactory')
|
|
3
|
+
const { Readable } = require('stream');
|
|
4
|
+
|
|
9
5
|
|
|
10
|
-
// DOING Use task line parsers for vs code extension and obsidian plugin
|
|
11
|
-
// <!--
|
|
12
|
-
// order:-10000030
|
|
13
|
-
// -->
|
|
14
6
|
export async function getTasks({filePath, content}) {
|
|
15
7
|
const projectPath = await Config.findImdonePath(filePath)
|
|
16
8
|
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
9
|
|
|
26
|
-
|
|
10
|
+
const readStream = new Readable({
|
|
11
|
+
read() {
|
|
12
|
+
this.push(content);
|
|
13
|
+
this.push(null);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const parser = await getFileParser(filePath, config, readStream)
|
|
18
|
+
|
|
19
|
+
const tasks = []
|
|
20
|
+
let task = true
|
|
21
|
+
while (task) {
|
|
22
|
+
task = await parser.readTask()
|
|
23
|
+
if (task) tasks.push(task)
|
|
24
|
+
}
|
|
25
|
+
parser.close()
|
|
26
|
+
return tasks
|
|
27
27
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imdone-core",
|
|
3
|
-
"version": "1.47.
|
|
3
|
+
"version": "1.47.2",
|
|
4
4
|
"description": "imdone-core",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -99,6 +99,7 @@
|
|
|
99
99
|
"multilang-extract-comments": "^0.4.0",
|
|
100
100
|
"open": "^9.1.0",
|
|
101
101
|
"ora": "^5.4.1",
|
|
102
|
+
"parse-code-context": "^1.0.0",
|
|
102
103
|
"prompts": "^2.4.2",
|
|
103
104
|
"readdirp": "^3.6.0",
|
|
104
105
|
"remove-markdown": "^0.3.0",
|