imdone-core 1.54.10 → 2.0.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/README.md +2 -2
- package/lib/cli.js +114 -0
- package/lib/index.js +23 -0
- package/package.json +48 -66
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
- package/.github/workflows/ci.yml +0 -24
- package/.imdoneignore +0 -12
- package/.mocharc.json +0 -10
- package/.prettierrc +0 -6
- package/CHANGELOG.md +0 -160
- package/_navbar.md +0 -1
- package/cli.js +0 -74
- package/index-markdown.js +0 -55
- package/index.html +0 -184
- package/index.js +0 -1
- package/lib/ProjectContext.js +0 -42
- package/lib/adapters/date-time.js +0 -20
- package/lib/adapters/file-gateway.js +0 -127
- package/lib/adapters/git-download.js +0 -35
- package/lib/adapters/markdown.js +0 -168
- package/lib/adapters/parsers/DateLanguageParser.js +0 -10
- package/lib/adapters/parsers/content-transformer.js +0 -111
- package/lib/adapters/parsers/file/LocalFileParserFactory.js +0 -37
- package/lib/adapters/parsers/file/ReadStreamCodeParser.js +0 -126
- package/lib/adapters/parsers/file/ReadStreamMarkdownParser.js +0 -17
- package/lib/adapters/parsers/file/ReadStreamTaskParser.js +0 -104
- package/lib/adapters/parsers/function-parser.js +0 -29
- package/lib/adapters/parsers/task/CardContentParser.js +0 -376
- package/lib/adapters/parsers/task/CheckStyleTaskParser.js +0 -28
- package/lib/adapters/parsers/task/CodeStyleTaskParser.js +0 -24
- package/lib/adapters/parsers/task/HashStyleTaskParser.js +0 -27
- package/lib/adapters/parsers/task/MarkdownStyleTaskParser.js +0 -24
- package/lib/adapters/parsers/task/TaskParser.js +0 -38
- package/lib/adapters/readers/FileSystemProjectReader.js +0 -45
- package/lib/adapters/storage/config.js +0 -49
- package/lib/adapters/storage/tags.js +0 -30
- package/lib/adapters/yaml.js +0 -6
- package/lib/card.js +0 -300
- package/lib/config.js +0 -214
- package/lib/constants.js +0 -97
- package/lib/context/ApplicationContext.js +0 -32
- package/lib/context/StreamingApplicationContext.js +0 -31
- package/lib/controlers/SaveViewController.js +0 -10
- package/lib/default-settings.js +0 -37
- package/lib/domain/entities/FileProjectContext.js +0 -10
- package/lib/domain/entities/View.js +0 -30
- package/lib/domain/usecases/GetViewsUsecase.js +0 -50
- package/lib/domain/usecases/OpenProjectUsecase.js +0 -13
- package/lib/domain/usecases/SaveViewUsecase.js +0 -57
- package/lib/file.js +0 -1395
- package/lib/languages.js +0 -114
- package/lib/list.js +0 -105
- package/lib/migrate-config.js +0 -165
- package/lib/mixins/repo-fs-store.js +0 -424
- package/lib/mixins/repo-watched-fs-store.js +0 -195
- package/lib/plugins/archive-plugin.js +0 -70
- package/lib/plugins/default-board-actions-plugin.js +0 -56
- package/lib/plugins/default-board-properties-plugin.js +0 -101
- package/lib/plugins/epic-plugin.js +0 -176
- package/lib/plugins/extension-plugin.js +0 -87
- package/lib/plugins/persist-tags-plugin.js +0 -13
- package/lib/plugins/plugin-manager.js +0 -421
- package/lib/plugins/plugin-registry.js +0 -61
- package/lib/project-factory.js +0 -45
- package/lib/project.js +0 -911
- package/lib/repository.js +0 -1746
- package/lib/task.js +0 -798
- package/lib/tools.js +0 -250
- package/lib/usecases/get-imdone-url.js +0 -6
- package/lib/usecases/get-project-tags.js +0 -16
- package/lib/usecases/get-tasks-in-file.js +0 -29
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
|
|
3
|
-
module.exports = class DefaultBoardActionsPlugin extends Plugin {
|
|
4
|
-
constructor(project) {
|
|
5
|
-
super(project)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
getBoardActions() {
|
|
9
|
-
const project = this.project
|
|
10
|
-
const isWindows = process.platform === 'win32'
|
|
11
|
-
const openIn = isWindows ? 'Explorer' : 'Finder'
|
|
12
|
-
|
|
13
|
-
return [
|
|
14
|
-
{
|
|
15
|
-
title: 'Duplicate card',
|
|
16
|
-
keys: ['shift+d'],
|
|
17
|
-
icon: 'clone',
|
|
18
|
-
action: async (task) => {
|
|
19
|
-
const timestamp = project.isoDateWithOffset
|
|
20
|
-
await project.newCard({
|
|
21
|
-
list: project.config.getDefaultList(),
|
|
22
|
-
path: task.relPath,
|
|
23
|
-
template: task.content.replace(/(\screated:).*(\s)/, `$1${timestamp}$2`),
|
|
24
|
-
})
|
|
25
|
-
project.toast({ message: `"${task.text}" duplicated` })
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
title: 'Copy card to clipboard',
|
|
30
|
-
keys: ['c'],
|
|
31
|
-
icon: 'clone',
|
|
32
|
-
action: (task) => {
|
|
33
|
-
return project.copyToClipboard(task.content, `"${task.text} markdown" copied to clipboard`)
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
title: 'Copy card title to clipboard',
|
|
38
|
-
keys: ['mod+t'],
|
|
39
|
-
icon: 'clone',
|
|
40
|
-
action: (task) => {
|
|
41
|
-
const title = project.renderMarkdown(task.text, task.fullPath).replaceAll(/<\/*p>/gi, '')
|
|
42
|
-
return project.copyToClipboard(title, `"${title}" copied to clipboard`)
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
title: `Open in ${openIn}`,
|
|
47
|
-
keys: ['alt+shift+o'],
|
|
48
|
-
icon: "folder",
|
|
49
|
-
async action () {
|
|
50
|
-
await project.openPath(project.path)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
const {getIsoDateWithOffset} = require('../adapters/date-time')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
|
|
5
|
-
const simpleTemplate = '\n<!--\ncreated:${timestamp}\n-->\n'
|
|
6
|
-
|
|
7
|
-
const codeSpan = (value) => '`' + value + '`';
|
|
8
|
-
const codeBlock = (value, language = '') => '```' + language + '\n' + value + '\n```';
|
|
9
|
-
|
|
10
|
-
function flattenObject(object) {
|
|
11
|
-
return Object.keys(object).reduce((acc, key) => {
|
|
12
|
-
return { ...acc, [`template_${key}`]: object[key] };
|
|
13
|
-
}, {});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = class DefaultBoardPropertiesPlugin extends Plugin {
|
|
17
|
-
constructor(project) {
|
|
18
|
-
super(project)
|
|
19
|
-
this.templates = {}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async onBeforeBoardUpdate() {
|
|
23
|
-
this.templates = await this.getTemplates()
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async getBoardProperties() {
|
|
27
|
-
const templates = flattenObject(this.templates);
|
|
28
|
-
const clearFilterURL = this.getFilterURL('');
|
|
29
|
-
const getFilterURL = (filter) => this.getFilterURL(filter);
|
|
30
|
-
const getFilterLink = (filter) => `[Filter By: ${filter}](${this.getFilterURL(filter)})`;
|
|
31
|
-
// TODO Make board properties self documenting
|
|
32
|
-
// <!--
|
|
33
|
-
// #imdone-1.53.16
|
|
34
|
-
// #feature
|
|
35
|
-
// created:2025-02-14T16:54:22-05:00
|
|
36
|
-
// order:-185
|
|
37
|
-
// -->
|
|
38
|
-
// [Feature Description]
|
|
39
|
-
// ## :ballot_box_with_check: Tasks
|
|
40
|
-
// - [ ] Add tasks here
|
|
41
|
-
// ## :white_check_mark: DoD
|
|
42
|
-
// - [ ] Code complete (No Tech Debt)
|
|
43
|
-
// - [ ] Update tests
|
|
44
|
-
// - [ ] Automate what's working
|
|
45
|
-
// - [ ] Update tutorial project
|
|
46
|
-
// - [ ] Update documentation
|
|
47
|
-
// - [ ] Run like a new user and make the experience better
|
|
48
|
-
// - [ ] Make sure the first card is expanded by default or in view mode
|
|
49
|
-
// - [ ] Make sure global and default settings isn't modified when opened for the first time
|
|
50
|
-
return {
|
|
51
|
-
date: `${getIsoDateWithOffset(new Date()).substring(0, 10)}`,
|
|
52
|
-
timestamp: getIsoDateWithOffset(new Date()),
|
|
53
|
-
codeSpan,
|
|
54
|
-
codeBlock,
|
|
55
|
-
clearFilterURL,
|
|
56
|
-
getFilterURL,
|
|
57
|
-
getFilterLink,
|
|
58
|
-
...templates
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
getFilterURL(filter) {
|
|
63
|
-
filter = filter.replace(/\(/g, '%28').replace(/\)/g, '%29');
|
|
64
|
-
return encodeURI(`imdone://${this.project.path}?filter=${filter}`)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
async getTemplates() {
|
|
69
|
-
const { preparePathForWriting, readdir, readFile, stat } = this.project.fileGateway;
|
|
70
|
-
const templateDir = path.join(this.project.configDir, 'templates');
|
|
71
|
-
const githubDir = path.join(this.project.path, '.github');
|
|
72
|
-
|
|
73
|
-
preparePathForWriting(templateDir);
|
|
74
|
-
|
|
75
|
-
const readMarkdownFiles = async (dir, prefix = '') => {
|
|
76
|
-
const files = await readdir(dir);
|
|
77
|
-
const readFilePromises = files.map(async (file) => {
|
|
78
|
-
const filePath = path.join(dir, file);
|
|
79
|
-
const fileStat = await stat(filePath);
|
|
80
|
-
if (fileStat && fileStat.isDirectory()) {
|
|
81
|
-
return readMarkdownFiles(filePath, `${prefix}${file}_`);
|
|
82
|
-
} else if (file.endsWith('.md')) {
|
|
83
|
-
const data = await readFile(filePath, 'utf-8');
|
|
84
|
-
const templateName = `${prefix}${file.replace('.md', '').replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
85
|
-
return { [templateName]: data };
|
|
86
|
-
}
|
|
87
|
-
return {};
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const allTemplates = await Promise.all(readFilePromises);
|
|
91
|
-
return allTemplates.reduce((acc, template) => ({ ...acc, ...template }), {});
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const templatesFromTemplateDir = await readMarkdownFiles(templateDir);
|
|
95
|
-
const templatesFromGithubDir = await stat(githubDir)
|
|
96
|
-
? await readMarkdownFiles(githubDir, 'github_')
|
|
97
|
-
: {};
|
|
98
|
-
|
|
99
|
-
return { simple: simpleTemplate, ...templatesFromTemplateDir, ...templatesFromGithubDir };
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
|
|
3
|
-
function getIsEpicMeta(task) {
|
|
4
|
-
return task.allMeta && task.allMeta['is-epic'] && task.allMeta['is-epic'][0]
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function getEpicMeta(task) {
|
|
8
|
-
return task.allMeta && task.allMeta['epic'] && task.allMeta['epic'][0]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
module.exports = class EpicPlugin extends Plugin {
|
|
12
|
-
constructor(project) {
|
|
13
|
-
super(project)
|
|
14
|
-
this.epics = {}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async onBeforeBoardUpdate() {
|
|
18
|
-
this.epics = {}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
onBoardUpdate(lists) {
|
|
22
|
-
// this html is getting initialized before onBoardUpdate
|
|
23
|
-
console.log(
|
|
24
|
-
`${this.project.name} epics found:`,
|
|
25
|
-
Object.keys(this.epics).length
|
|
26
|
-
)
|
|
27
|
-
console.time(`${this.project.name} Epic updates`)
|
|
28
|
-
this.updateCardMD(lists)
|
|
29
|
-
console.timeEnd(`${this.project.name} Epic updates`)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
onTaskUpdate(task) {
|
|
33
|
-
const isEpicMeta = getIsEpicMeta(task)
|
|
34
|
-
const epicMeta = getEpicMeta(task)
|
|
35
|
-
if (!isEpicMeta && !epicMeta) return
|
|
36
|
-
|
|
37
|
-
if (isEpicMeta && epicMeta) {
|
|
38
|
-
delete task.allMeta.epic
|
|
39
|
-
task.allMeta['is-epic'] = [epicMeta]
|
|
40
|
-
this.addEpic(epicMeta, task)
|
|
41
|
-
} else if (epicMeta) {
|
|
42
|
-
this.addEpicItem(epicMeta, task)
|
|
43
|
-
} else if (isEpicMeta) {
|
|
44
|
-
this.addEpic(isEpicMeta, task)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
initEpic(name) {
|
|
49
|
-
if (!this.epics[name]) {
|
|
50
|
-
this.epics[name] = {
|
|
51
|
-
items: {},
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
addEpic(name, task) {
|
|
57
|
-
this.initEpic(name)
|
|
58
|
-
this.epics[name].epic = task
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
addEpicItem(name, task) {
|
|
62
|
-
const list = task.list
|
|
63
|
-
this.initEpic(name)
|
|
64
|
-
if (!this.getEpicItemsInList(name, list)) this.epics[name].items[list] = []
|
|
65
|
-
if (this.getEpicItemsInList(name, list).find((t) => t.id === task.id)) return
|
|
66
|
-
this.epics[name].items[list].push(task)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
get epicNames() {
|
|
70
|
-
return Object.keys(this.epics)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getEpic(name) {
|
|
74
|
-
return this.epics[name].epic
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
getEpicItems(name) {
|
|
78
|
-
return this.epics[name].items
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getEpicItemsInList(name, list) {
|
|
82
|
-
return this.epics[name].items[list]
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
getEpicLists(name) {
|
|
87
|
-
return Object.keys(this.getEpicItems(name))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
isListHidden(name, lists) {
|
|
91
|
-
return lists.find((list) => list.name === name).hidden
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
isListIgnored(name, lists) {
|
|
95
|
-
return lists.find((list) => list.name === name).ignore
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
updateCardMD(lists) {
|
|
99
|
-
this.epicNames.forEach((epicId) => {
|
|
100
|
-
const epic = this.getEpic(epicId)
|
|
101
|
-
const epicLists = this.getEpicLists(epicId)
|
|
102
|
-
if (!epic) return
|
|
103
|
-
if (epicLists.length === 0) return
|
|
104
|
-
if (
|
|
105
|
-
epic.list === this.project.doneList &&
|
|
106
|
-
(this.isListHidden(epic.list, lists) ||
|
|
107
|
-
this.isListIgnored(epic.list, lists))
|
|
108
|
-
) {
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const epicText = epic.text // removeMD(epic.text)
|
|
113
|
-
const epicFilter = encodeURIComponent(
|
|
114
|
-
`(allMeta.epic="${epicId}" or allMeta.is-epic="${epicId}")`
|
|
115
|
-
)
|
|
116
|
-
const epicFilePath = encodeURI(
|
|
117
|
-
`${epic.source.repoId}/${epic.source.path}`.replace(/\\/g, '/')
|
|
118
|
-
)
|
|
119
|
-
const epicUrl = `imdone://${epicFilePath}?line=${epic.line}&filter=${epicFilter}`
|
|
120
|
-
const epicLink = `**Epic:** [${epicText}](${epicUrl})\n\n`
|
|
121
|
-
|
|
122
|
-
// Add epic link to epic tasks
|
|
123
|
-
epicLists.forEach((list) => {
|
|
124
|
-
this.getEpicItemsInList(epicId, list).forEach((task) => {
|
|
125
|
-
task.interpretedContent = epicLink + task.interpretedContent
|
|
126
|
-
task.init()
|
|
127
|
-
})
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
const taskList =
|
|
131
|
-
epicLists.length === 0
|
|
132
|
-
? '*None*\n'
|
|
133
|
-
: '\n<div class="imdone-epic-items">\n\n' +
|
|
134
|
-
this.getTaskListMD(lists, epicFilter, epicUrl, epicId) +
|
|
135
|
-
'\n\n</div>\n'
|
|
136
|
-
|
|
137
|
-
if (epic.allMeta.epic && epic.allMeta.epic.includes(epicId)) {
|
|
138
|
-
const index = epic.allMeta.epic.findIndex((value) => value === epicId)
|
|
139
|
-
epic.allMeta.epic.splice(index, 1)
|
|
140
|
-
}
|
|
141
|
-
epic.interpretedContent =
|
|
142
|
-
epic.interpretedContent +
|
|
143
|
-
`\n----\n## [Epic items](${epicUrl})\n${taskList}`
|
|
144
|
-
epic.init()
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
getTaskListMD(lists, epicFilter, epicUrl, epicId) {
|
|
149
|
-
let content = ''
|
|
150
|
-
|
|
151
|
-
lists
|
|
152
|
-
.filter((list) => this.getEpicItemsInList(epicId, list.name))
|
|
153
|
-
.reverse()
|
|
154
|
-
.forEach((list) => {
|
|
155
|
-
const tasks = this.getEpicItemsInList(epicId, list.name)
|
|
156
|
-
const listUrl = epicUrl + encodeURIComponent(` and list=${list.name}`)
|
|
157
|
-
const listLink = `[${list.name}](${listUrl})`
|
|
158
|
-
content = content + '\n\n#### ' + listLink + '\n'
|
|
159
|
-
content += '<ul style="list-style: none;">'
|
|
160
|
-
content += tasks
|
|
161
|
-
.map((task) => {
|
|
162
|
-
const taskText = this.project.renderMarkdown(task.text, task.fullPath).replaceAll(/<p>|<\/p>/ig, '') // removeMD(task.text)
|
|
163
|
-
const checked =
|
|
164
|
-
task.list === this.project.doneList ? ' checked="true"' : ''
|
|
165
|
-
const taskFilePath = encodeURI(
|
|
166
|
-
`${task.source.repoId}/${task.source.path}`.replace(/\\/g, '/')
|
|
167
|
-
)
|
|
168
|
-
return `<li style="margin-left: 1rem; list-style: none;"><input type="checkbox" disabled="true"${checked}><a href="imdone://${taskFilePath}?line=${task.line}&filter=${epicFilter}" target="_blank">${taskText}</a></li>`
|
|
169
|
-
})
|
|
170
|
-
.join('\n')
|
|
171
|
-
content += '</ul>'
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
return content
|
|
175
|
-
}
|
|
176
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
const _path = require('path')
|
|
3
|
-
const { statSync } = require('fs')
|
|
4
|
-
|
|
5
|
-
module.exports = class ExtensionPlugin extends Plugin {
|
|
6
|
-
constructor(project) {
|
|
7
|
-
super(project)
|
|
8
|
-
console.log('loading extensions')
|
|
9
|
-
this.configDir = _path.join(project.path, '.imdone')
|
|
10
|
-
|
|
11
|
-
this.cardActionsFunction = this.loadExtensionModule(
|
|
12
|
-
() => [],
|
|
13
|
-
'actions',
|
|
14
|
-
'card'
|
|
15
|
-
)
|
|
16
|
-
this.boardActionsFunction = this.loadExtensionModule(
|
|
17
|
-
() => [],
|
|
18
|
-
'actions',
|
|
19
|
-
'board'
|
|
20
|
-
)
|
|
21
|
-
this.cardPropertiesFunction = this.loadExtensionModule(
|
|
22
|
-
() => {
|
|
23
|
-
return {}
|
|
24
|
-
},
|
|
25
|
-
'properties',
|
|
26
|
-
'card'
|
|
27
|
-
)
|
|
28
|
-
this.boardPropertiesFunction = this.loadExtensionModule(
|
|
29
|
-
() => {
|
|
30
|
-
return {}
|
|
31
|
-
},
|
|
32
|
-
'properties',
|
|
33
|
-
'board'
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getCardProperties(task) {
|
|
38
|
-
return this.cardPropertiesFunction(task)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async getBoardProperties() {
|
|
42
|
-
return await this.boardPropertiesFunction()
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
getCardActions(task) {
|
|
46
|
-
return this.cardActionsFunction(task)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
getBoardActions() {
|
|
50
|
-
return this.boardActionsFunction().map(({ title, action, keys, icon }) => ({
|
|
51
|
-
title,
|
|
52
|
-
name: title,
|
|
53
|
-
action,
|
|
54
|
-
keys,
|
|
55
|
-
icon
|
|
56
|
-
}))
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
getConfigPath(relativePath) {
|
|
60
|
-
return _path.join(this.configDir, ...relativePath)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
loadExtensionModule(_default, ...path) {
|
|
64
|
-
let extension = _default
|
|
65
|
-
const extensionPath = this.getConfigPath(path)
|
|
66
|
-
try {
|
|
67
|
-
statSync(extensionPath + '.js')
|
|
68
|
-
delete require.cache[require.resolve(extensionPath)]
|
|
69
|
-
extension = require(extensionPath)
|
|
70
|
-
} catch (e) {
|
|
71
|
-
if (e.code === 'ENOENT') {
|
|
72
|
-
console.log('No extension found at:', extensionPath)
|
|
73
|
-
} else {
|
|
74
|
-
console.error(e)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (typeof extension !== 'function') {
|
|
79
|
-
console.warn(
|
|
80
|
-
`${extensionPath} does not export a function. Using default empty function. ${_default.toString()}`
|
|
81
|
-
)
|
|
82
|
-
extension = _default
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return extension
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
const { save } = require('../adapters/storage/tags.js')
|
|
3
|
-
|
|
4
|
-
module.exports = class PersistTagsPlugin extends Plugin {
|
|
5
|
-
constructor(project) {
|
|
6
|
-
super(project)
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async onBoardUpdate() {
|
|
10
|
-
await save(this.project.allTags.sort(), this.project.path)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
}
|