imdone-core 1.54.12 → 1.54.13

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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm test:*)",
5
+ "Bash(node test-debug.js:*)"
6
+ ]
7
+ }
8
+ }
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 1.54.13
2
+
3
+ - **Enhancement**: `customCardTerminator` now accepts numeric values to specify the number of consecutive blank lines needed to terminate a card (e.g., `customCardTerminator: 3` requires 3 blank lines)
4
+ - **Enhancement**: `repo.resume()` now automatically calls `refresh()` to pick up file changes that occurred while the repository was paused
5
+ - **Enhancement**: `File.trimBlankLines()` now respects the `customCardTerminator` config setting, preserving the appropriate number of blank lines in card content
6
+ - **Fix**: `Task.updateFromContent()` now respects the `customCardTerminator` config setting when collapsing consecutive blank lines, ensuring consistency across all content operations
7
+ - **Tests**: Added comprehensive test coverage for numeric `customCardTerminator` values, `trimBlankLines` behavior, `updateFromContent` behavior, and `resume()` refresh functionality
8
+ - **Refactor**: Improved code readability by replacing comments with self-documenting function names and descriptive constants
9
+
1
10
  ## 1.28.8
2
11
  - Allow Card and Board actions to return a value
3
12
 
@@ -55,10 +55,28 @@ function getContentLines(content) {
55
55
  }
56
56
 
57
57
  function isCustomCardTerminator(config, line) {
58
- return config.customCardTerminator
59
- && config.customCardTerminator.trim()
60
- && line
61
- && line.trim() === config.customCardTerminator
58
+ if (!config.customCardTerminator) return false
59
+
60
+ const isStringTerminator = typeof config.customCardTerminator === 'string'
61
+ && config.customCardTerminator.trim()
62
+
63
+ if (isStringTerminator) {
64
+ const terminatorMatches = line && line.trim() === config.customCardTerminator.trim()
65
+ return terminatorMatches
66
+ }
67
+
68
+ return false
69
+ }
70
+
71
+ const DEFAULT_BLANK_LINE_TERMINATOR_COUNT = 2
72
+
73
+ function getBlankLineTerminatorCount(config) {
74
+ const hasNumericTerminator = typeof config.customCardTerminator === 'number'
75
+ && config.customCardTerminator > 0
76
+
77
+ return hasNumericTerminator
78
+ ? config.customCardTerminator
79
+ : DEFAULT_BLANK_LINE_TERMINATOR_COUNT
62
80
  }
63
81
 
64
82
  function isCheckBoxTask (config, line, beforeText) {
@@ -256,8 +274,8 @@ function getTextFileTaskContent ({
256
274
  const isTaskInList = isMarkDownFile && isBeforeTextMarkdownList(beforeText)
257
275
  let openBlockCommentTokens = 0
258
276
  let closeBlockCommentTokens = 0
259
- let lastLineBlank = false
260
- let endsWithDoubleBlank = false
277
+ const blankLineTerminatorCount = getBlankLineTerminatorCount(config)
278
+ let consecutiveBlankLines = 0
261
279
  let trailingBlankLines = 0
262
280
  const rawTaskContentLines = []
263
281
  const taskContentLines = []
@@ -277,7 +295,7 @@ function getTextFileTaskContent ({
277
295
  if (isCheckBoxTask(config, line, beforeText)) break
278
296
  if (isTaskInList && isLineOutsideMarkdownList(line, beforeText)) break
279
297
  if (isCustomCardTerminator(config, line)) break
280
-
298
+
281
299
  rawTaskContentLines.push(line)
282
300
  taskContentLines.push(`${line}`)
283
301
 
@@ -285,20 +303,28 @@ function getTextFileTaskContent ({
285
303
  if (isMarkDownFile && line.trim().indexOf('<!--') > -1)
286
304
  openBlockCommentTokens++
287
305
  if (isMarkDownFile && line.trim().indexOf('-->') > -1)
288
- closeBlockCommentTokens++
306
+ closeBlockCommentTokens++
289
307
 
290
308
  const thisLineBlank = line.trim() === ''
291
309
 
292
- if (thisLineBlank && lastLineBlank) {
293
- endsWithDoubleBlank = true
294
- break
310
+ if (thisLineBlank) {
311
+ consecutiveBlankLines++
312
+ if (consecutiveBlankLines >= blankLineTerminatorCount) {
313
+ trailingBlankLines = blankLineTerminatorCount
314
+ break
315
+ }
316
+ } else {
317
+ consecutiveBlankLines = 0
295
318
  }
296
-
297
- lastLineBlank = thisLineBlank
298
319
  }
299
320
 
300
- if (endsWithDoubleBlank) trailingBlankLines = 2
301
- else if (lastLineBlank) trailingBlankLines = 1
321
+ const reachedEndNaturally = trailingBlankLines === 0
322
+ const hasTrailingBlankLines = consecutiveBlankLines > 0
323
+ const isUsingDefaultTerminator = blankLineTerminatorCount === DEFAULT_BLANK_LINE_TERMINATOR_COUNT
324
+
325
+ if (reachedEndNaturally && hasTrailingBlankLines && isUsingDefaultTerminator) {
326
+ trailingBlankLines = consecutiveBlankLines
327
+ }
302
328
 
303
329
  // Remove extra block comment tokens
304
330
  if (
package/lib/file.js CHANGED
@@ -820,17 +820,51 @@ File.prototype.modifyTaskFromHtml = function (task, html) {
820
820
  }
821
821
 
822
822
  File.prototype.modifyTaskFromContent = function (task, content, config) {
823
- content = trimBlankLines(content, this.isCodeFile())
823
+ content = trimBlankLines(content, this.isCodeFile(), config)
824
824
  task.updateFromContent(content)
825
825
  this.modifyTask(task, config)
826
826
  }
827
827
 
828
- const trimBlankLines = File.trimBlankLines = function (content, isCodeFile) {
828
+ const DEFAULT_BLANK_LINE_TERMINATOR_COUNT = 2
829
+ const CODE_FILE_BLANK_LINE_PATTERN = /\n\s*\n/g
830
+ const CODE_FILE_BLANK_LINE_REPLACEMENT = '\n'
831
+
832
+ function getBlankLineTerminatorCountFromConfig(config) {
833
+ const hasNumericTerminator = config
834
+ && typeof config.customCardTerminator === 'number'
835
+ && config.customCardTerminator > 0
836
+
837
+ return hasNumericTerminator
838
+ ? config.customCardTerminator
839
+ : DEFAULT_BLANK_LINE_TERMINATOR_COUNT
840
+ }
841
+
842
+ function buildExcessiveBlankLinePattern(terminatorCount) {
843
+ const minNewlinesToTrim = terminatorCount + 1
844
+ const patternParts = Array(minNewlinesToTrim).fill('\\n\\s*')
845
+ return new RegExp(patternParts.join(''), 'g')
846
+ }
847
+
848
+ function calculateMaxPreservedBlankLines(terminatorCount) {
849
+ return terminatorCount - 1
850
+ }
851
+
852
+ function buildBlankLineReplacement(maxBlankLines) {
853
+ const newlineCount = maxBlankLines + 1
854
+ return '\n'.repeat(newlineCount)
855
+ }
856
+
857
+ const trimBlankLines = File.trimBlankLines = function (content, isCodeFile, config) {
829
858
  if (isCodeFile) {
830
- // replace all occurrences of two empty lines in a row with a single empty line
831
- return content.replace(/\n\s*\n/g, '\n')
832
- }
833
- return content.replace(/\n\s*\n\s*\n/g, '\n\n')
859
+ return content.replace(CODE_FILE_BLANK_LINE_PATTERN, CODE_FILE_BLANK_LINE_REPLACEMENT)
860
+ }
861
+
862
+ const terminatorCount = getBlankLineTerminatorCountFromConfig(config)
863
+ const excessiveBlankLinePattern = buildExcessiveBlankLinePattern(terminatorCount)
864
+ const maxBlankLines = calculateMaxPreservedBlankLines(terminatorCount)
865
+ const replacement = buildBlankLineReplacement(maxBlankLines)
866
+
867
+ return content.replace(excessiveBlankLinePattern, replacement)
834
868
  }
835
869
 
836
870
  File.prototype.modifyDescription = function (task, config) {
package/lib/repository.js CHANGED
@@ -1156,7 +1156,9 @@ Repository.prototype.appendTask = function({file, content, list}, cb) {
1156
1156
  : description.join(eol.lf)
1157
1157
 
1158
1158
  let appendContent = File.trimBlankLines(
1159
- `${taskPrefix}${rawTask}${eol.lf}${taskContent}`
1159
+ `${taskPrefix}${rawTask}${eol.lf}${taskContent}`,
1160
+ file.isCodeFile(),
1161
+ config
1160
1162
  )
1161
1163
 
1162
1164
  fileContent = `${fileContent}${sep}`
package/lib/task.js CHANGED
@@ -14,7 +14,7 @@ var _clone = require('lodash.clone'),
14
14
  { escapeRegExp } = require('./tools'),
15
15
  { extractWikilinkTopics } = require('./adapters/markdown');
16
16
 
17
- const {
17
+ const {
18
18
  CHECK_REGEX,
19
19
  TASK_TYPES,
20
20
  getCheckedData,
@@ -22,6 +22,33 @@ const {
22
22
  isNumber
23
23
  } = require('./adapters/parsers/task/CardContentParser.js')
24
24
 
25
+ const DEFAULT_BLANK_LINE_TERMINATOR_COUNT = 2
26
+
27
+ function getBlankLineTerminatorCountFromConfig(config) {
28
+ const hasNumericTerminator = config
29
+ && typeof config.customCardTerminator === 'number'
30
+ && config.customCardTerminator > 0
31
+
32
+ return hasNumericTerminator
33
+ ? config.customCardTerminator
34
+ : DEFAULT_BLANK_LINE_TERMINATOR_COUNT
35
+ }
36
+
37
+ function buildExcessiveBlankLinePattern(terminatorCount) {
38
+ const minNewlinesToTrim = terminatorCount + 1
39
+ const patternParts = Array(minNewlinesToTrim).fill('\\n\\s*')
40
+ return new RegExp(patternParts.join(''), 'g')
41
+ }
42
+
43
+ function calculateMaxPreservedBlankLines(terminatorCount) {
44
+ return terminatorCount - 1
45
+ }
46
+
47
+ function buildBlankLineReplacement(maxBlankLines) {
48
+ const newlineCount = maxBlankLines + 1
49
+ return '\n'.repeat(newlineCount)
50
+ }
51
+
25
52
  /**
26
53
  * Description
27
54
  * @method Task
@@ -177,8 +204,12 @@ class Task {
177
204
  }
178
205
 
179
206
  updateFromContent(content) {
180
- // replace all occurrences of two empty lines in a row with a single empty line
181
- content = content.replace(/\n\s*\n\s*\n/g, '\n\n')
207
+ const terminatorCount = getBlankLineTerminatorCountFromConfig(this.config)
208
+ const excessiveBlankLinePattern = buildExcessiveBlankLinePattern(terminatorCount)
209
+ const maxBlankLines = calculateMaxPreservedBlankLines(terminatorCount)
210
+ const replacement = buildBlankLineReplacement(maxBlankLines)
211
+
212
+ content = content.replace(excessiveBlankLinePattern, replacement)
182
213
  let lines = eol.split(content)
183
214
  this.text = lines.shift().trimStart()
184
215
  if (lines && lines.length > 1 && lines[lines.length - 1].trim() === '') lines.pop()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imdone-core",
3
- "version": "1.54.12",
3
+ "version": "1.54.13",
4
4
  "description": "imdone-core",
5
5
  "main": "index.js",
6
6
  "bin": {