imdone-core 1.40.1 → 1.41.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/lib/adapters/date-time.js +11 -0
- package/lib/adapters/markdown.js +1 -1
- package/lib/adapters/parsers/task/CardContentParser.js +54 -28
- package/lib/card.js +13 -5
- package/lib/config.js +4 -6
- package/lib/default-settings.js +1 -0
- package/lib/file.js +6 -5
- package/lib/project.js +94 -23
- package/lib/repository.js +26 -0
- package/lib/task.js +18 -18
- package/package.json +2 -2
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const moment = require('moment');
|
|
2
|
+
module.exports = {
|
|
3
|
+
getIsoDateWithOffset: function ({date, config}) {
|
|
4
|
+
const momentDate = moment(date);
|
|
5
|
+
if (momentDate.isDST() && config && config.noDST) {
|
|
6
|
+
const offset = momentDate.utcOffset();
|
|
7
|
+
momentDate.utcOffset(offset - 60);
|
|
8
|
+
}
|
|
9
|
+
return momentDate.format();
|
|
10
|
+
}
|
|
11
|
+
}
|
package/lib/adapters/markdown.js
CHANGED
|
@@ -14,7 +14,7 @@ md.use(checkbox)
|
|
|
14
14
|
.use(imageSize)
|
|
15
15
|
.use(wikilinks(
|
|
16
16
|
{
|
|
17
|
-
linkPattern: /\[\[([\w\s\d-/]+)(\|([\w\s\d-/]+))?\]\]/,
|
|
17
|
+
linkPattern: /\[\[([\w\u00C0-\u017F\s\d-/]+)(\|([\w\u00C0-\u017F\s\d-/]+))?\]\]/,
|
|
18
18
|
uriSuffix: '.md',
|
|
19
19
|
postProcessPageName (pagename) {
|
|
20
20
|
return pagename.trim()
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const eol = require('eol')
|
|
2
|
-
const Task = require('../../../task')
|
|
3
2
|
const XRegExp = require('xregexp')
|
|
4
3
|
|
|
5
4
|
const FILE_TYPES = {
|
|
@@ -23,6 +22,18 @@ const LINK_STYLE_REGEX = new XRegExp(
|
|
|
23
22
|
'gm'
|
|
24
23
|
)
|
|
25
24
|
|
|
25
|
+
const CHECK_REGEX = /^(\s*- )\[([x ])\]/
|
|
26
|
+
function getCheckedData(content) {
|
|
27
|
+
const taskRegex = new RegExp(CHECK_REGEX)
|
|
28
|
+
const result = taskRegex.exec(content)
|
|
29
|
+
return result
|
|
30
|
+
? {
|
|
31
|
+
pad: result[1].length,
|
|
32
|
+
checked: result[2].trim() !== '',
|
|
33
|
+
}
|
|
34
|
+
: null
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
function getContentLines(content) {
|
|
27
38
|
let foundContent = false
|
|
28
39
|
return eol.split(content).filter((line) => {
|
|
@@ -35,10 +46,10 @@ function getContentLines(content) {
|
|
|
35
46
|
function isCheckBoxTask (config, line, beforeText) {
|
|
36
47
|
if (!config.isAddCheckBoxTasks()) return
|
|
37
48
|
|
|
38
|
-
const beforeTextCheckData =
|
|
49
|
+
const beforeTextCheckData = getCheckedData(beforeText)
|
|
39
50
|
if (!beforeTextCheckData) return
|
|
40
51
|
|
|
41
|
-
const lineCheckData =
|
|
52
|
+
const lineCheckData = getCheckedData(line)
|
|
42
53
|
if (!lineCheckData) return
|
|
43
54
|
|
|
44
55
|
return lineCheckData.pad <= beforeTextCheckData.pad
|
|
@@ -54,7 +65,28 @@ function hasTaskInText(config, text, isCodeFile) {
|
|
|
54
65
|
)
|
|
55
66
|
}
|
|
56
67
|
|
|
57
|
-
function
|
|
68
|
+
function isBeforeTextMarkdownList(beforeText) {
|
|
69
|
+
return /^\s*(\*|-|- \[[x| ]\]|\d+\.|[a-zA-Z]\.)\s$/.test(beforeText)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isMarkdownListItem(line) {
|
|
73
|
+
return /^\s*(\*|-|- \[[x| ]\]|\d+\.|[a-zA-Z]\.)\s/.test(line)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function padDescription(description = [], beforeText = '') {
|
|
77
|
+
if (!isBeforeTextMarkdownList(beforeText)) return description
|
|
78
|
+
return description.map((line) => {
|
|
79
|
+
return line.padStart(line.length + beforeText.length)
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isLineOutsideMarkdownList(line, beforeText) {
|
|
84
|
+
return isBeforeTextMarkdownList(beforeText) &&
|
|
85
|
+
isMarkdownListItem(line) &&
|
|
86
|
+
line.search(/\S/) <= beforeText.search(/\S/)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function hasCodeStyleTask(config, text) {
|
|
58
90
|
let result = new RegExp(CODE_STYLE_PATTERN).exec(text)
|
|
59
91
|
if (!result) return false
|
|
60
92
|
return config.includeList(result[1])
|
|
@@ -165,31 +197,23 @@ function getTextFileTaskContent ({
|
|
|
165
197
|
if (hasCardStartTag) return
|
|
166
198
|
|
|
167
199
|
const isMarkDownFile = fileType === FILE_TYPES.MARKDOWN
|
|
200
|
+
const isTaskInList = isMarkDownFile && isBeforeTextMarkdownList(beforeText)
|
|
168
201
|
let openBlockCommentTokens = 0
|
|
169
202
|
let closeBlockCommentTokens = 0
|
|
170
203
|
let lastLineBlank = false
|
|
171
204
|
let endsWithDoubleBlank = false
|
|
172
205
|
let trailingBlankLines = 0
|
|
173
206
|
const rawTaskContentLines = []
|
|
207
|
+
const taskContentLines = []
|
|
174
208
|
|
|
175
209
|
for (let i = 1; i < lines.length; i++) {
|
|
176
210
|
let line = lines[i]
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (hasTaskInText(config, line, isCodeFile)) break
|
|
211
|
+
let taskContentLine = `${line}`
|
|
212
|
+
if (hasTaskInText(config, line)) break
|
|
180
213
|
if (isCheckBoxTask(config, line, beforeText)) break
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// #urgent
|
|
185
|
-
// <!-- order:-65 -->
|
|
186
|
-
if (
|
|
187
|
-
isMarkDownFile &&
|
|
188
|
-
beforeText &&
|
|
189
|
-
/^\s*(\*|-|\d+\.|[a-zA-Z]\.)\s$/.test(beforeText) &&
|
|
190
|
-
line.search(/\S/) <= beforeText.search(/\S/)
|
|
191
|
-
) break
|
|
192
|
-
|
|
214
|
+
if (isTaskInList && isLineOutsideMarkdownList(line, beforeText)) break
|
|
215
|
+
|
|
216
|
+
taskContentLines.push(taskContentLine)
|
|
193
217
|
rawTaskContentLines.push(line)
|
|
194
218
|
|
|
195
219
|
// Check for matching block comments in markdown files
|
|
@@ -217,17 +241,17 @@ function getTextFileTaskContent ({
|
|
|
217
241
|
rawTaskContentLines.length &&
|
|
218
242
|
rawTaskContentLines[rawTaskContentLines.length - 1].trim() === '-->' &&
|
|
219
243
|
openBlockCommentTokens !== closeBlockCommentTokens
|
|
220
|
-
)
|
|
244
|
+
) {
|
|
221
245
|
rawTaskContentLines.pop()
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
? rawTaskContentLines.slice(0, -trailingBlankLines)
|
|
225
|
-
: rawTaskContentLines;
|
|
246
|
+
taskContentLines.pop()
|
|
247
|
+
}
|
|
226
248
|
|
|
227
249
|
return {
|
|
228
250
|
rawTaskContentLines,
|
|
229
|
-
taskContentLines
|
|
230
|
-
|
|
251
|
+
taskContentLines: trailingBlankLines
|
|
252
|
+
? taskContentLines.slice(0, -trailingBlankLines)
|
|
253
|
+
: taskContentLines,
|
|
254
|
+
trailingBlankLines,
|
|
231
255
|
}
|
|
232
256
|
}
|
|
233
257
|
|
|
@@ -247,8 +271,10 @@ function getTaskContent ({
|
|
|
247
271
|
module.exports = {
|
|
248
272
|
FILE_TYPES,
|
|
249
273
|
getTaskContent,
|
|
250
|
-
|
|
251
|
-
|
|
274
|
+
isBeforeTextMarkdownList,
|
|
275
|
+
padDescription,
|
|
276
|
+
getCheckedData,
|
|
277
|
+
CHECK_REGEX,
|
|
252
278
|
LIST_NAME_PATTERN,
|
|
253
279
|
HASH_STYLE_REGEX,
|
|
254
280
|
HASH_STYLE_META_ORDER_REGEX,
|
package/lib/card.js
CHANGED
|
@@ -3,11 +3,12 @@ const _path = require('path')
|
|
|
3
3
|
const template = require('lodash.template')
|
|
4
4
|
const _pick = require('lodash.pick')
|
|
5
5
|
const _isFunction = require('lodash.isfunction')
|
|
6
|
+
const _isObject = require('lodash.isobject')
|
|
6
7
|
const _isEmpty = require('lodash.isempty')
|
|
7
8
|
const _get = require('lodash.get')
|
|
8
9
|
const eol = require('eol')
|
|
9
|
-
const moment = require('moment')
|
|
10
10
|
const allEmoji = require('markdown-it-emoji/lib/data/full.json')
|
|
11
|
+
const { getIsoDateWithOffset } = require('./adapters/date-time')
|
|
11
12
|
|
|
12
13
|
const { removeMD, renderMarkdown } = require('./adapters/markdown')
|
|
13
14
|
|
|
@@ -116,7 +117,7 @@ module.exports = function newCard(task, _project, dontParse) {
|
|
|
116
117
|
|
|
117
118
|
get defaultData() {
|
|
118
119
|
return {
|
|
119
|
-
timestamp:
|
|
120
|
+
timestamp: getIsoDateWithOffset({config: project.config}),
|
|
120
121
|
..._pick(
|
|
121
122
|
this,
|
|
122
123
|
...['beforeText',
|
|
@@ -194,6 +195,16 @@ module.exports = function newCard(task, _project, dontParse) {
|
|
|
194
195
|
...defaultData
|
|
195
196
|
}
|
|
196
197
|
|
|
198
|
+
const keys = Object.keys(data)
|
|
199
|
+
keys.forEach((key) => {
|
|
200
|
+
const value = data[key]
|
|
201
|
+
if (_isObject(value) && !Array.isArray(value)) {
|
|
202
|
+
|
|
203
|
+
keys.push(...Object.keys(value).map((k) => `${key}.${k}`))
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
this.dataKeys = keys
|
|
207
|
+
|
|
197
208
|
this.data = { ...data }
|
|
198
209
|
this.desc = this.getDescriptionData()
|
|
199
210
|
this.data = { ...data, ...this.desc }
|
|
@@ -244,9 +255,6 @@ module.exports = function newCard(task, _project, dontParse) {
|
|
|
244
255
|
content = content.replace(opts.interpolate, `~~{{${e}}}~~`)
|
|
245
256
|
}
|
|
246
257
|
}
|
|
247
|
-
// Fix list endings
|
|
248
|
-
// const listEndingRegex = /(\n\s*([-+*]{1}|\d+.)\s.*[\n\r])([^1-9-+* \t])/gm
|
|
249
|
-
// description = description.replace(listEndingRegex, '$1\n$3')
|
|
250
258
|
|
|
251
259
|
return content
|
|
252
260
|
}
|
package/lib/config.js
CHANGED
|
@@ -56,12 +56,6 @@ class Config {
|
|
|
56
56
|
return this.lists.findIndex((list) => list.name === name) > -1
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
getDateString(date = new Date()) {
|
|
60
|
-
return _get(this, 'settings.cards.useLocalDate')
|
|
61
|
-
? moment(date).utcOffset(0, true).format()
|
|
62
|
-
: date.toISOString()
|
|
63
|
-
}
|
|
64
|
-
|
|
65
59
|
getDefaultList() {
|
|
66
60
|
return _get(this, 'settings.cards.defaultList', this.lists[0].name)
|
|
67
61
|
}
|
|
@@ -100,6 +94,10 @@ class Config {
|
|
|
100
94
|
return _get(this, 'settings.cards.addCompletedMeta', false)
|
|
101
95
|
}
|
|
102
96
|
|
|
97
|
+
get noDST() {
|
|
98
|
+
return _get(this, 'settings.noDST', false)
|
|
99
|
+
}
|
|
100
|
+
|
|
103
101
|
get markdownOnly() {
|
|
104
102
|
return this.settings.markdownOnly
|
|
105
103
|
}
|
package/lib/default-settings.js
CHANGED
package/lib/file.js
CHANGED
|
@@ -20,7 +20,7 @@ var _clone = require('lodash.clone'),
|
|
|
20
20
|
newCard = require('./card'),
|
|
21
21
|
fastSort = require('fast-sort/dist/sort'),
|
|
22
22
|
XRegExp = require('xregexp'),
|
|
23
|
-
|
|
23
|
+
{ getIsoDateWithOffset } = require('./adapters/date-time'),
|
|
24
24
|
{
|
|
25
25
|
FILE_TYPES,
|
|
26
26
|
getTaskContent,
|
|
@@ -149,7 +149,7 @@ File.addCompleted = function ({ task, content, config }) {
|
|
|
149
149
|
if (task.list !== doneList) return content
|
|
150
150
|
if (task.completed || task.meta.completed) return content
|
|
151
151
|
if (content.includes(`completed${config.getMetaSep()}`)) return content
|
|
152
|
-
const now =
|
|
152
|
+
const now = getIsoDateWithOffset({ config })
|
|
153
153
|
content = task.addToLastCommentInContent(
|
|
154
154
|
content,
|
|
155
155
|
`completed${config.getMetaSep()}${now}`,
|
|
@@ -166,10 +166,11 @@ File.parseDueDate = function (config, text) {
|
|
|
166
166
|
if (dueString) return dueMatch
|
|
167
167
|
try {
|
|
168
168
|
const due = chrono.parseDate(dueMatch, new Date(), {forwardDate: true})
|
|
169
|
-
|
|
169
|
+
if (!due) return dueMatch
|
|
170
|
+
dueString = getIsoDateWithOffset({date: due, config})
|
|
170
171
|
return `${p1.toLowerCase()}${config.getMetaSep()}${dueString}`
|
|
171
172
|
} catch (e) {
|
|
172
|
-
|
|
173
|
+
console.log(`Unable to parse due date for ${text}`)
|
|
173
174
|
return dueMatch
|
|
174
175
|
}
|
|
175
176
|
})
|
|
@@ -835,7 +836,7 @@ File.prototype.modifyDescription = function (task, config) {
|
|
|
835
836
|
description.length > 0 &&
|
|
836
837
|
(hasBlankLines(description) || isWrappedWithCardTag || trailingBlankLines)
|
|
837
838
|
) {
|
|
838
|
-
task.isWrappedWithCardTag = isWrappedWithCardTag //
|
|
839
|
+
task.isWrappedWithCardTag = isWrappedWithCardTag // FIXME Find out where this is used and stop using it
|
|
839
840
|
// <!-- order:-30 -->
|
|
840
841
|
const blankLinesToAdd = isWrappedWithCardTag ? 2 : trailingBlankLines
|
|
841
842
|
description = `${description}${lineEnd.repeat(blankLinesToAdd)}`
|
package/lib/project.js
CHANGED
|
@@ -102,10 +102,14 @@ module.exports = class WorkerProject extends Project {
|
|
|
102
102
|
files: this.files,
|
|
103
103
|
totals,
|
|
104
104
|
tags: this.getTags(),
|
|
105
|
+
allMeta: this.repo.allMeta,
|
|
106
|
+
allContexts: [...this.repo.allContexts],
|
|
107
|
+
allTags: [...this.repo.allTags],
|
|
105
108
|
filter: this.filter,
|
|
106
109
|
defaultFilter: this.defaultFilter,
|
|
107
110
|
actions: this.boardActions,
|
|
108
111
|
plugins: this.pluginManager.getPlugins(),
|
|
112
|
+
queryProps: this.getQueryProps(cards),
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
115
|
|
|
@@ -177,8 +181,42 @@ module.exports = class WorkerProject extends Project {
|
|
|
177
181
|
getLists(opts) {
|
|
178
182
|
const {tasks = this.getDefaultFilteredCards(), populateFiltered = false} = opts || {}
|
|
179
183
|
return Repository.getTasksByList(this.repo, tasks, true, populateFiltered)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
getTaskQueryProps(task) {
|
|
187
|
+
const queryProps = []
|
|
188
|
+
if (task) {
|
|
189
|
+
// add all properties of the task to the queryProps array
|
|
190
|
+
Object.keys(task).forEach((key) => {
|
|
191
|
+
if (key === 'data') return
|
|
192
|
+
if (queryProps.includes(key)) return
|
|
193
|
+
|
|
194
|
+
queryProps.push(key)
|
|
195
|
+
|
|
196
|
+
if (_isObject(task[key])) {
|
|
197
|
+
Object.keys(task[key]).forEach((subKey) => {
|
|
198
|
+
if (!queryProps.includes(`${key}.${subKey}`))
|
|
199
|
+
queryProps.push(`${key}.${subKey}`)
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
return queryProps
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
getQueryProps(cards) {
|
|
208
|
+
if (!cards) return []
|
|
209
|
+
const queryProps = this.getTaskQueryProps(cards[0])
|
|
210
|
+
return [
|
|
211
|
+
...new Set(queryProps),
|
|
212
|
+
...[...this.repo.metaKeys].map(key => `allMeta.${key}`),
|
|
213
|
+
...[...this.repo.metaKeys].map(key => `meta.${key}`),
|
|
214
|
+
...this.repo.allTags,
|
|
215
|
+
...this.repo.allContexts,
|
|
216
|
+
]
|
|
180
217
|
}
|
|
181
218
|
|
|
219
|
+
|
|
182
220
|
getTags(cards = this.getDefaultFilteredCards()) {
|
|
183
221
|
const tags = []
|
|
184
222
|
cards.forEach((card) => {
|
|
@@ -208,7 +246,8 @@ module.exports = class WorkerProject extends Project {
|
|
|
208
246
|
}
|
|
209
247
|
|
|
210
248
|
getCards(filter, tasks = this.getDefaultFilteredCards()) {
|
|
211
|
-
|
|
249
|
+
tasks = filter ? Repository.query(tasks, filter) : tasks
|
|
250
|
+
return tasks
|
|
212
251
|
}
|
|
213
252
|
|
|
214
253
|
get files() {
|
|
@@ -404,27 +443,38 @@ module.exports = class WorkerProject extends Project {
|
|
|
404
443
|
const filePath = cardData.path
|
|
405
444
|
if (addTemplate) content += cardData.template
|
|
406
445
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
if (contexts && contexts.length > 0) {
|
|
417
|
-
let contextContent = ''
|
|
418
|
-
contexts.forEach(context => {
|
|
419
|
-
const contextWithPrefix = `@${context}`
|
|
420
|
-
if (content.includes(contextWithPrefix)) return
|
|
421
|
-
contextContent = `${contextContent} @${context}`
|
|
446
|
+
content = this.addOrderMetaToContent(content, list)
|
|
447
|
+
content = this.addTagsToContent(tags, content)
|
|
448
|
+
content = this.addContextsToContent(contexts, content)
|
|
449
|
+
content = this.addMetaToContent(meta, content)
|
|
450
|
+
|
|
451
|
+
return new Promise((resolve, reject) => {
|
|
452
|
+
this.repo.addTaskToFile(filePath, list, content, (err, file) => {
|
|
453
|
+
if (err) return reject(err)
|
|
454
|
+
resolve(file)
|
|
422
455
|
})
|
|
423
|
-
|
|
456
|
+
})
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
addOrderMetaToContent(content, _list) {
|
|
460
|
+
const list = this.lists.find(l => l.name === _list)
|
|
461
|
+
let order
|
|
462
|
+
if (this.config.isAddNewCardsToTop()) {
|
|
463
|
+
order = list.tasks.length
|
|
464
|
+
? list.tasks[0].order - 1
|
|
465
|
+
: 0
|
|
466
|
+
} else {
|
|
467
|
+
order = list.tasks.length
|
|
468
|
+
? list.tasks[list.tasks.length - 1].order + 1
|
|
469
|
+
: 0
|
|
424
470
|
}
|
|
471
|
+
return Task.addToLastCommentInContent(content, `order${this.config.getMetaSep()}${order}`, this.config.isMetaNewLine())
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
addMetaToContent(meta, content) {
|
|
425
475
|
if (meta && meta.length > 0) {
|
|
426
476
|
let metaContent = ''
|
|
427
|
-
meta.forEach(({key, value}) => {
|
|
477
|
+
meta.forEach(({ key, value }) => {
|
|
428
478
|
if (!/^['"]/.test(value) && /\s/.test(value)) value = `"${value}"`
|
|
429
479
|
const metaData = `${key}${this.repo.config.getMetaSep()}${value}`
|
|
430
480
|
if (content.includes(metaData)) return
|
|
@@ -442,12 +492,33 @@ module.exports = class WorkerProject extends Project {
|
|
|
442
492
|
})
|
|
443
493
|
content = Task.addToLastCommentInContent(content, metaContent.trim(), this.config.isMetaNewLine())
|
|
444
494
|
}
|
|
445
|
-
return
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
495
|
+
return content
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
addContextsToContent(contexts, content) {
|
|
499
|
+
if (contexts && contexts.length > 0) {
|
|
500
|
+
let contextContent = ''
|
|
501
|
+
contexts.forEach(context => {
|
|
502
|
+
const contextWithPrefix = `@${context}`
|
|
503
|
+
if (content.includes(contextWithPrefix)) return
|
|
504
|
+
contextContent = `${contextContent} @${context}`
|
|
449
505
|
})
|
|
450
|
-
|
|
506
|
+
content = Task.addToLastCommentInContent(content, contextContent.trim(), this.config.isMetaNewLine())
|
|
507
|
+
}
|
|
508
|
+
return content
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
addTagsToContent(tags, content) {
|
|
512
|
+
if (tags && tags.length > 0) {
|
|
513
|
+
let tagContent = ''
|
|
514
|
+
tags.forEach(tag => {
|
|
515
|
+
const tagWithPrefix = `${this.config.getTagPrefix()}${tag}`
|
|
516
|
+
if (content.includes(tagWithPrefix)) return
|
|
517
|
+
tagContent = `${tagContent} ${tagWithPrefix}`
|
|
518
|
+
})
|
|
519
|
+
content = Task.addToLastCommentInContent(content, tagContent.trim(), this.config.isMetaNewLine())
|
|
520
|
+
}
|
|
521
|
+
return content
|
|
451
522
|
}
|
|
452
523
|
|
|
453
524
|
async deleteTask(task) {
|
package/lib/repository.js
CHANGED
|
@@ -15,6 +15,7 @@ var _get = require('lodash.get'),
|
|
|
15
15
|
_groupBy = require('lodash.groupby'),
|
|
16
16
|
_where = require('lodash.where'),
|
|
17
17
|
_template = require('lodash.template'),
|
|
18
|
+
_union = require('lodash.union'),
|
|
18
19
|
events = require('events'),
|
|
19
20
|
languages = require('./languages'),
|
|
20
21
|
util = require('util'),
|
|
@@ -65,6 +66,10 @@ function Repository(_path, config) {
|
|
|
65
66
|
this.path = _path
|
|
66
67
|
this.files = []
|
|
67
68
|
this.languages = languages
|
|
69
|
+
this.allMeta = {}
|
|
70
|
+
this.metaKeys = new Set()
|
|
71
|
+
this.allTags = new Set()
|
|
72
|
+
this.allContexts = new Set()
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
util.inherits(Repository, events.EventEmitter)
|
|
@@ -165,6 +170,10 @@ Repository.prototype.createListeners = function () {
|
|
|
165
170
|
self.emit('list.found', list)
|
|
166
171
|
self.saveConfig()
|
|
167
172
|
}
|
|
173
|
+
Object.keys(task.allMeta).forEach(key => self.metaKeys.add(key))
|
|
174
|
+
task.allTags.forEach(tag => self.allTags.add(tag))
|
|
175
|
+
task.allContext.forEach(context => self.allContexts.add(context))
|
|
176
|
+
self.allMeta = self.addAllMeta(task.allMeta)
|
|
168
177
|
self.emit(event, task)
|
|
169
178
|
}
|
|
170
179
|
|
|
@@ -177,6 +186,18 @@ Repository.prototype.createListeners = function () {
|
|
|
177
186
|
}
|
|
178
187
|
}
|
|
179
188
|
|
|
189
|
+
Repository.prototype.addAllMeta = function (meta) {
|
|
190
|
+
const allMeta = Object.assign({}, this.allMeta)
|
|
191
|
+
Object.keys(meta).forEach((key) => {
|
|
192
|
+
if (!allMeta[key]) {
|
|
193
|
+
allMeta[key] = meta[key]
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
allMeta[key] = _union(allMeta[key], meta[key])
|
|
197
|
+
})
|
|
198
|
+
return allMeta
|
|
199
|
+
}
|
|
200
|
+
|
|
180
201
|
/**
|
|
181
202
|
* Description
|
|
182
203
|
* @method addList
|
|
@@ -645,6 +666,11 @@ Repository.prototype.readFiles = function (files, cb) {
|
|
|
645
666
|
|
|
646
667
|
var self = this
|
|
647
668
|
|
|
669
|
+
this.allMeta = {}
|
|
670
|
+
this.metaKeys = new Set()
|
|
671
|
+
this.allTags = new Set()
|
|
672
|
+
this.allContexts = new Set()
|
|
673
|
+
|
|
648
674
|
var exec = function (files) {
|
|
649
675
|
var completed = 0
|
|
650
676
|
if (files.length < 1) return cb(null, [])
|
package/lib/task.js
CHANGED
|
@@ -12,7 +12,13 @@ var _clone = require('lodash.clone'),
|
|
|
12
12
|
lineEnd = String(eol.auto),
|
|
13
13
|
fastSort = require('fast-sort/dist/sort.js'),
|
|
14
14
|
{ escapeRegExp } = require('./tools'),
|
|
15
|
-
cheerio = require('cheerio')
|
|
15
|
+
cheerio = require('cheerio');
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
CHECK_REGEX,
|
|
19
|
+
getCheckedData,
|
|
20
|
+
isBeforeTextMarkdownList
|
|
21
|
+
} = require('./adapters/parsers/task/CardContentParser.js')
|
|
16
22
|
|
|
17
23
|
/**
|
|
18
24
|
* Description
|
|
@@ -180,7 +186,7 @@ class Task {
|
|
|
180
186
|
// replace all occurrences of two empty lines in a row with a single empty line
|
|
181
187
|
content = content.replace(/\n\s*\n\s*\n/g, '\n\n')
|
|
182
188
|
let lines = eol.split(content)
|
|
183
|
-
this.text = lines.shift().
|
|
189
|
+
this.text = lines.shift().trimStart()
|
|
184
190
|
if (lines && lines.length > 1 && lines[lines.length - 1].trim() === '') lines.pop()
|
|
185
191
|
this.description = lines
|
|
186
192
|
this.parse()
|
|
@@ -197,24 +203,12 @@ class Task {
|
|
|
197
203
|
}
|
|
198
204
|
}
|
|
199
205
|
|
|
200
|
-
Task.CHECK_REGEX = /^(\s*- )\[([x ])\]/
|
|
201
|
-
Task.getCheckedData = function (content) {
|
|
202
|
-
const taskRegex = new RegExp(Task.CHECK_REGEX)
|
|
203
|
-
const result = taskRegex.exec(content)
|
|
204
|
-
return result
|
|
205
|
-
? {
|
|
206
|
-
pad: result[1].length,
|
|
207
|
-
checked: result[2].trim() !== '',
|
|
208
|
-
}
|
|
209
|
-
: null
|
|
210
|
-
}
|
|
211
|
-
|
|
212
206
|
Task.hasCheckPrefix = function (content) {
|
|
213
|
-
return new RegExp(
|
|
207
|
+
return new RegExp(CHECK_REGEX).test(content)
|
|
214
208
|
}
|
|
215
209
|
|
|
216
210
|
Task.padDescription = function (description = [], beforeText = '') {
|
|
217
|
-
const checkedData =
|
|
211
|
+
const checkedData = getCheckedData(beforeText)
|
|
218
212
|
if (checkedData) {
|
|
219
213
|
return description.map((line) => {
|
|
220
214
|
const paddedLine = line.padStart(line.length + checkedData.pad)
|
|
@@ -225,7 +219,7 @@ Task.padDescription = function (description = [], beforeText = '') {
|
|
|
225
219
|
}
|
|
226
220
|
|
|
227
221
|
Task.trimDescription = function (rawTaskContentLines, beforeText) {
|
|
228
|
-
const checkedData =
|
|
222
|
+
const checkedData = getCheckedData(beforeText)
|
|
229
223
|
if (checkedData) {
|
|
230
224
|
rawTaskContentLines = rawTaskContentLines.map((line) => {
|
|
231
225
|
const lineLength = line.length
|
|
@@ -237,7 +231,7 @@ Task.trimDescription = function (rawTaskContentLines, beforeText) {
|
|
|
237
231
|
}
|
|
238
232
|
|
|
239
233
|
Task.prototype.getCheckedData = function () {
|
|
240
|
-
return
|
|
234
|
+
return getCheckedData(this.beforeText)
|
|
241
235
|
}
|
|
242
236
|
|
|
243
237
|
Task.Types = {
|
|
@@ -417,6 +411,12 @@ Task.prototype.addToLastCommentInContent = Task.addToLastCommentInContent = func
|
|
|
417
411
|
return `${before}${prefix}${toAdd}${prefix}${after}`
|
|
418
412
|
}
|
|
419
413
|
if (!content.endsWith(lf) && content !== '') content = content + lineEnd
|
|
414
|
+
if (isBeforeTextMarkdownList(this.beforeText)) {
|
|
415
|
+
const spaces = this.beforeText.search(/\S|$/)
|
|
416
|
+
content = content.padEnd(content.length + spaces)
|
|
417
|
+
prefix = prefix.padEnd(prefix.length + spaces)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
420
|
return `${content}<!--${prefix}${toAdd}${prefix}-->`
|
|
421
421
|
}
|
|
422
422
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imdone-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"description": "imdone-core",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"lodash.isundefined": "^3.0.1",
|
|
82
82
|
"lodash.noop": "^3.0.1",
|
|
83
83
|
"lodash.omit": "^4.5.0",
|
|
84
|
-
"lodash.pick": "^
|
|
84
|
+
"lodash.pick": "^3.1.0",
|
|
85
85
|
"lodash.reject": "^4.6.0",
|
|
86
86
|
"lodash.remove": "^4.7.0",
|
|
87
87
|
"lodash.some": "^4.6.0",
|