imdone-core 2.0.12 → 2.0.14

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 CHANGED
@@ -11,3 +11,4 @@ imdone-export.json
11
11
  .imdone/templates
12
12
  .imdone
13
13
  notes/archive
14
+ _lib
package/lib/config.js CHANGED
@@ -141,6 +141,10 @@ export class Config {
141
141
  return this?.cards?.tagPrefix ?? '+'
142
142
  }
143
143
 
144
+ getCommentTagsOnly() {
145
+ return this?.cards?.commentTagsOnly ?? false
146
+ }
147
+
144
148
  getTaskPrefix() {
145
149
  return this?.cards?.taskPrefix ?? '##'
146
150
  }
@@ -20,11 +20,10 @@ import _ignore from 'ignore'
20
20
  import { sort } from 'fast-sort'
21
21
  import { buildMigrateConfig } from '../migrate-config.js'
22
22
  import { loadYAML, dumpYAML } from '../adapters/yaml.js';
23
- import realFs, { readFileSync } from 'fs'
23
+ import realFs from 'fs'
24
24
  import { preparePathForWriting, readFile, writeFile, stat, lstat, unlink } from '../adapters/file-gateway.js'
25
25
 
26
26
  const {
27
- CONFIG_FILE,
28
27
  CONFIG_FILE_YML,
29
28
  ASYNC_LIMIT,
30
29
  DEFAULT_IGNORE_PATHS,
@@ -198,11 +197,6 @@ export function fileSystemStoreMixin(repo, fs = realFs) {
198
197
  return repo.config
199
198
  }
200
199
 
201
- // READY Refactor loadConfig to use async/await
202
- // #esm-migration
203
- // <!--
204
- // order:-255
205
- // -->
206
200
  repo.loadConfig = async function (cb) {
207
201
  // BACKLOG If a config is bad move it to config.json.bak and save a new one with defaults gh:2 id:9 +enhancement +standup +chore
208
202
  // <!--
@@ -217,7 +211,7 @@ export function fileSystemStoreMixin(repo, fs = realFs) {
217
211
  }
218
212
 
219
213
  repo.getConfigFile = function () {
220
- return repo.getFullPath(CONFIG_FILE)
214
+ return repo.getFullPath(CONFIG_FILE_YML)
221
215
  }
222
216
 
223
217
  repo.getYamlConfig = async function () {
@@ -18,6 +18,7 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
18
18
  const _init = repo.init
19
19
  let initializing = false
20
20
  let refreshing = false
21
+ let watcherPaused = false
21
22
 
22
23
  function ready() {
23
24
  return !initializing && !refreshing
@@ -30,6 +31,30 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
30
31
  }
31
32
  }
32
33
 
34
+ // Add function to pause the watcher
35
+ repo.pauseWatcher = async function() {
36
+ if (repo.watcher && !watcherPaused) {
37
+ logger.info('Pausing file watcher for:', repo.path)
38
+ await repo.watcher.close()
39
+ watcherPaused = true
40
+ repo.emit('watcher.paused')
41
+ return true
42
+ }
43
+ return false
44
+ }
45
+
46
+ // Add function to unpause the watcher
47
+ repo.unpauseWatcher = async function() {
48
+ if (watcherPaused) {
49
+ logger.info('Unpausing file watcher for:', repo.path)
50
+ await repo.initWatcher()
51
+ watcherPaused = false
52
+ repo.emit('watcher.resumed')
53
+ return true
54
+ }
55
+ return false
56
+ }
57
+
33
58
  // READY Refactor init to async/await
34
59
  // #esm-migration #important
35
60
  // <!--
@@ -69,7 +94,10 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
69
94
  refreshing = true
70
95
  try {
71
96
  const files = await _refresh.call(repo)
72
- await repo.initWatcher()
97
+ // Only initialize watcher if it's not paused
98
+ if (!watcherPaused) {
99
+ await repo.initWatcher()
100
+ }
73
101
  refreshing = false
74
102
  return files
75
103
  } catch (err) {
@@ -108,6 +136,11 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
108
136
  // defer:2025-03-18
109
137
  // -->
110
138
  repo.initWatcher = async () => {
139
+ // Close existing watcher if it exists
140
+ if (repo.watcher) {
141
+ await repo.watcher.close()
142
+ }
143
+
111
144
  return new Promise(async (resolve, reject) => {
112
145
  logger.log('initializing watcher for:', repo.path)
113
146
  repo.watcher = chokidar.watch(repo.path, {
@@ -118,8 +151,11 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
118
151
  atomic: true,
119
152
  ignoreInitial: true,
120
153
  ignored: (file) => {
121
- const ignored = !repo.shouldInclude(file)
122
- if (ignored) logger.log('Ignoring file:', file)
154
+ if (file === repo.path) return false
155
+ const relPath = repo.getRelativePath(file)
156
+ const ignored = !repo.shouldInclude(relPath)
157
+ if (ignored) logger.log('Ignoring file:', relPath)
158
+
123
159
  return ignored
124
160
  }
125
161
  }).on('error', (err) => {
@@ -163,6 +199,11 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
163
199
  stat.mtime
164
200
  )
165
201
  if (!path || stat.isDirectory()) return
202
+
203
+ const relPath = repo.getRelativePath(path)
204
+ if (!initializing && _isImdoneConfig(relPath)) onConfigChange(relPath)
205
+ if (!initializing && _isImdoneIgnore(relPath)) onIgnoreChange(relPath)
206
+
166
207
  var file = repo.getFile(path) || path
167
208
  const isFile = File.isFile(file)
168
209
  // BACKLOG ## Handle the case where the file is not in the repo
@@ -174,8 +215,6 @@ export function watchedFileSystemStoreMixin(repo, fs = realFs) {
174
215
  // logger.log("File update already applied. Change ignored.")
175
216
  return
176
217
  }
177
- if (_isImdoneConfig(path)) return onConfigChange(path)
178
- if (_isImdoneIgnore(path)) return onIgnoreChange(path)
179
218
 
180
219
  const ok = await repo.fileOK((file && file.path) || path)
181
220
  if (!ok) return
package/lib/repository.js CHANGED
@@ -634,12 +634,12 @@ export class Repository extends Emitter {
634
634
  shouldInclude (relPath) {
635
635
  relPath = this.getRelativePath(relPath)
636
636
  let include = true
637
- if (this.config.markdownOnly && relPath) {
638
- include = File.isMarkdown(relPath)
639
- }
640
637
  if (this.ignore) {
641
638
  try {
642
- include = include && (relPath === '' || !this.ignore.ignores(relPath))
639
+ include = relPath && !this.ignore.ignores(relPath)
640
+ if (this.config.markdownOnly && include && relPath) {
641
+ include = File.isMarkdown(relPath)
642
+ }
643
643
  } catch (e) {
644
644
  logger.error(
645
645
  `Failed to check ignore status for dir: [${relPath}] in: [${this.path}]. It will be included.`,
package/lib/task.js CHANGED
@@ -188,6 +188,10 @@ export class Task {
188
188
  getTagPrefix () {
189
189
  return this.config?.getTagPrefix()
190
190
  }
191
+
192
+ getCommentTagsOnly () {
193
+ return this.config?.getCommentTagsOnly()
194
+ }
191
195
 
192
196
  static addToLastCommentInContent (content, toAdd, newLine) {
193
197
  // BACKLOG respect padding of task prefix for list items
@@ -315,14 +319,16 @@ export class Task {
315
319
  'gmiu'
316
320
  )
317
321
  }
318
- static getTags (text, prefix = '+') {
322
+ static getTags (text, prefix = '+', commentTagsOnly = false) {
319
323
  const tags = [];
320
324
  const codePositions = Task.getMarkdownCodePositions(text);
321
325
  const linkLabelPositions = Task.getMarkdownLinkLabelPositions(text);
326
+ const commentPositions = Task.getCommentPositions(text);
322
327
  let result;
323
328
  const re = Task.getTagRegexp(prefix);
324
329
 
325
330
  while ((result = re.exec(text)) !== null) {
331
+ if (commentTagsOnly && !Task.isResultInComment(commentPositions, result.index)) continue;
326
332
  if (Task.isResultInMarkdownCode(codePositions, result.index)) continue;
327
333
  if (Task.isResultInMarkdownLinkLabel(linkLabelPositions, result.index)) continue;
328
334
  const tag = result[2];
@@ -349,6 +355,22 @@ export class Task {
349
355
  return linkLabelPositions.some(pos => index >= pos.start && index < pos.end);
350
356
  };
351
357
 
358
+ static getCommentPositions (text) {
359
+ const positions = [];
360
+ const re = /<!--[\s\S]*?-->/g;
361
+ let match;
362
+
363
+ while ((match = re.exec(text)) !== null) {
364
+ positions.push({ start: match.index, end: re.lastIndex });
365
+ }
366
+
367
+ return positions;
368
+ }
369
+
370
+ static isResultInComment (commentPositions, index) {
371
+ return commentPositions.some(pos => index >= pos.start && index < pos.end);
372
+ }
373
+
352
374
  static ContextRegExp = new RegExp(
353
375
  `(^|\\s)@([${Task.AnyLanguageGroup}${Task.EmojiGroup}]+)`,
354
376
  'gmiu'
@@ -567,7 +589,7 @@ export class Task {
567
589
  }
568
590
 
569
591
  parseTodoTxt () {
570
- this.tags = Task.getTags(this.getRawTextAndDescription(), this.getTagPrefix())
592
+ this.tags = Task.getTags(this.getRawTextAndDescription(), this.getTagPrefix(), this.getCommentTagsOnly())
571
593
  this.context = Task.getContext(this.getRawTextAndDescription())
572
594
  this.meta = Task.getMetaData(this.config, this)
573
595
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imdone-core",
3
- "version": "2.0.12",
3
+ "version": "2.0.14",
4
4
  "description": "imdone-core",
5
5
  "repository": {
6
6
  "type": "git",
package/types/card.d.ts CHANGED
@@ -158,6 +158,7 @@ export function newCard(task: any, _project: any, dontParse: any): {
158
158
  expand: boolean;
159
159
  };
160
160
  getTagPrefix(): any;
161
+ getCommentTagsOnly(): any;
161
162
  addToLastCommentInContent(content: any, toAdd: any, newLine: any): string;
162
163
  getCheckedData(): {
163
164
  pad: number;
package/types/config.d.ts CHANGED
@@ -32,6 +32,7 @@ export class Config {
32
32
  getNewCardSyntax(): any;
33
33
  isMetaNewLine(): any;
34
34
  getTagPrefix(): any;
35
+ getCommentTagsOnly(): any;
35
36
  getTaskPrefix(): any;
36
37
  isAddCheckBoxTasks(): any;
37
38
  isAddCompletedMeta(): any;
package/types/file.d.ts CHANGED
@@ -256,6 +256,7 @@ export class File extends Emitter<[never]> {
256
256
  expand: boolean;
257
257
  };
258
258
  getTagPrefix(): any;
259
+ getCommentTagsOnly(): any;
259
260
  addToLastCommentInContent(content: any, toAdd: any, newLine: any): string;
260
261
  getCheckedData(): {
261
262
  pad: number;
package/types/task.d.ts CHANGED
@@ -18,12 +18,17 @@ export class Task {
18
18
  static AnyLanguageGroup: string;
19
19
  static EmojiGroup: string;
20
20
  static getTagRegexp(prefix?: string): RegExp;
21
- static getTags(text: any, prefix?: string): string[];
21
+ static getTags(text: any, prefix?: string, commentTagsOnly?: boolean): string[];
22
22
  static getMarkdownLinkLabelPositions(text: any): {
23
23
  start: number;
24
24
  end: number;
25
25
  }[];
26
26
  static isResultInMarkdownLinkLabel(linkLabelPositions: any, index: any): any;
27
+ static getCommentPositions(text: any): {
28
+ start: number;
29
+ end: number;
30
+ }[];
31
+ static isResultInComment(commentPositions: any, index: any): any;
27
32
  static ContextRegExp: RegExp;
28
33
  static getContext(text: any): string[];
29
34
  static MetaRegExp: RegExp;
@@ -124,6 +129,7 @@ export class Task {
124
129
  expand: boolean;
125
130
  };
126
131
  getTagPrefix(): any;
132
+ getCommentTagsOnly(): any;
127
133
  addToLastCommentInContent(content: any, toAdd: any, newLine: any): string;
128
134
  getCheckedData(): {
129
135
  pad: number;