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.
Files changed (71) hide show
  1. package/README.md +2 -2
  2. package/lib/cli.js +114 -0
  3. package/lib/index.js +23 -0
  4. package/package.json +48 -66
  5. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
  6. package/.github/workflows/ci.yml +0 -24
  7. package/.imdoneignore +0 -12
  8. package/.mocharc.json +0 -10
  9. package/.prettierrc +0 -6
  10. package/CHANGELOG.md +0 -160
  11. package/_navbar.md +0 -1
  12. package/cli.js +0 -74
  13. package/index-markdown.js +0 -55
  14. package/index.html +0 -184
  15. package/index.js +0 -1
  16. package/lib/ProjectContext.js +0 -42
  17. package/lib/adapters/date-time.js +0 -20
  18. package/lib/adapters/file-gateway.js +0 -127
  19. package/lib/adapters/git-download.js +0 -35
  20. package/lib/adapters/markdown.js +0 -168
  21. package/lib/adapters/parsers/DateLanguageParser.js +0 -10
  22. package/lib/adapters/parsers/content-transformer.js +0 -111
  23. package/lib/adapters/parsers/file/LocalFileParserFactory.js +0 -37
  24. package/lib/adapters/parsers/file/ReadStreamCodeParser.js +0 -126
  25. package/lib/adapters/parsers/file/ReadStreamMarkdownParser.js +0 -17
  26. package/lib/adapters/parsers/file/ReadStreamTaskParser.js +0 -104
  27. package/lib/adapters/parsers/function-parser.js +0 -29
  28. package/lib/adapters/parsers/task/CardContentParser.js +0 -376
  29. package/lib/adapters/parsers/task/CheckStyleTaskParser.js +0 -28
  30. package/lib/adapters/parsers/task/CodeStyleTaskParser.js +0 -24
  31. package/lib/adapters/parsers/task/HashStyleTaskParser.js +0 -27
  32. package/lib/adapters/parsers/task/MarkdownStyleTaskParser.js +0 -24
  33. package/lib/adapters/parsers/task/TaskParser.js +0 -38
  34. package/lib/adapters/readers/FileSystemProjectReader.js +0 -45
  35. package/lib/adapters/storage/config.js +0 -49
  36. package/lib/adapters/storage/tags.js +0 -30
  37. package/lib/adapters/yaml.js +0 -6
  38. package/lib/card.js +0 -300
  39. package/lib/config.js +0 -214
  40. package/lib/constants.js +0 -97
  41. package/lib/context/ApplicationContext.js +0 -32
  42. package/lib/context/StreamingApplicationContext.js +0 -31
  43. package/lib/controlers/SaveViewController.js +0 -10
  44. package/lib/default-settings.js +0 -37
  45. package/lib/domain/entities/FileProjectContext.js +0 -10
  46. package/lib/domain/entities/View.js +0 -30
  47. package/lib/domain/usecases/GetViewsUsecase.js +0 -50
  48. package/lib/domain/usecases/OpenProjectUsecase.js +0 -13
  49. package/lib/domain/usecases/SaveViewUsecase.js +0 -57
  50. package/lib/file.js +0 -1395
  51. package/lib/languages.js +0 -114
  52. package/lib/list.js +0 -105
  53. package/lib/migrate-config.js +0 -165
  54. package/lib/mixins/repo-fs-store.js +0 -424
  55. package/lib/mixins/repo-watched-fs-store.js +0 -195
  56. package/lib/plugins/archive-plugin.js +0 -70
  57. package/lib/plugins/default-board-actions-plugin.js +0 -56
  58. package/lib/plugins/default-board-properties-plugin.js +0 -101
  59. package/lib/plugins/epic-plugin.js +0 -176
  60. package/lib/plugins/extension-plugin.js +0 -87
  61. package/lib/plugins/persist-tags-plugin.js +0 -13
  62. package/lib/plugins/plugin-manager.js +0 -421
  63. package/lib/plugins/plugin-registry.js +0 -61
  64. package/lib/project-factory.js +0 -45
  65. package/lib/project.js +0 -911
  66. package/lib/repository.js +0 -1746
  67. package/lib/task.js +0 -798
  68. package/lib/tools.js +0 -250
  69. package/lib/usecases/get-imdone-url.js +0 -6
  70. package/lib/usecases/get-project-tags.js +0 -16
  71. 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
- }