imdone-core 2.0.0 → 2.0.1

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 (160) hide show
  1. package/.dependency-cruiser.cjs +412 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  3. package/.github/workflows/ci.yml +24 -0
  4. package/.imdoneignore +13 -0
  5. package/.mocharc.json +10 -0
  6. package/.prettierrc +6 -0
  7. package/CHANGELOG.md +160 -0
  8. package/_index.md +7 -0
  9. package/_navbar.md +1 -0
  10. package/build.js +57 -0
  11. package/esm-migration.md +446 -0
  12. package/index.html +184 -0
  13. package/lib/FileProjectContext.js +13 -0
  14. package/lib/ProjectContext.js +43 -0
  15. package/lib/adapters/date-time.js +15 -0
  16. package/lib/adapters/environment.js +3 -0
  17. package/lib/adapters/file-gateway.js +154 -0
  18. package/lib/adapters/git-download.js +55 -0
  19. package/lib/adapters/index.js +9 -0
  20. package/lib/adapters/logger.js +136 -0
  21. package/lib/adapters/markdown.js +180 -0
  22. package/lib/adapters/parsers/DateLanguageParser.js +12 -0
  23. package/lib/adapters/parsers/content-transformer.js +116 -0
  24. package/lib/adapters/parsers/file/LocalFileParserFactory.js +36 -0
  25. package/lib/adapters/parsers/file/ReadStreamCodeParser.js +126 -0
  26. package/lib/adapters/parsers/file/ReadStreamMarkdownParser.js +17 -0
  27. package/lib/adapters/parsers/file/ReadStreamTaskParser.js +106 -0
  28. package/lib/adapters/parsers/file/index.js +4 -0
  29. package/lib/adapters/parsers/function-parser.js +25 -0
  30. package/lib/adapters/parsers/index.js +5 -0
  31. package/lib/adapters/parsers/task/CardContentParser.js +367 -0
  32. package/lib/adapters/parsers/task/CheckStyleTaskParser.js +28 -0
  33. package/lib/adapters/parsers/task/CodeStyleTaskParser.js +24 -0
  34. package/lib/adapters/parsers/task/HashStyleTaskParser.js +27 -0
  35. package/lib/adapters/parsers/task/MarkdownStyleTaskParser.js +24 -0
  36. package/lib/adapters/parsers/task/TaskParser.js +38 -0
  37. package/lib/adapters/parsers/task/index.js +6 -0
  38. package/lib/adapters/storage/config.js +44 -0
  39. package/lib/adapters/storage/index.js +2 -0
  40. package/lib/adapters/storage/tags.js +29 -0
  41. package/lib/adapters/yaml.js +9 -0
  42. package/lib/card.js +299 -0
  43. package/lib/checksum.js +22 -0
  44. package/lib/config.js +249 -0
  45. package/lib/constants.js +68 -0
  46. package/lib/context/ApplicationContext.js +35 -0
  47. package/lib/context/index.js +1 -0
  48. package/lib/default-settings.js +37 -0
  49. package/lib/domain/entities/View.js +23 -0
  50. package/lib/domain/entities/index.js +1 -0
  51. package/lib/domain/index.js +2 -0
  52. package/lib/domain/usecases/GetViewsUsecase.js +44 -0
  53. package/lib/domain/usecases/SaveViewUsecase.js +51 -0
  54. package/lib/domain/usecases/index.js +2 -0
  55. package/lib/file.js +1391 -0
  56. package/lib/get-tasks-to-modify.js +117 -0
  57. package/lib/languages.js +113 -0
  58. package/lib/list.js +56 -0
  59. package/lib/migrate-config.js +165 -0
  60. package/lib/mixins/index.js +2 -0
  61. package/lib/mixins/repo-fs-store.js +359 -0
  62. package/lib/mixins/repo-watched-fs-store.js +206 -0
  63. package/lib/plugins/archive-plugin.js +72 -0
  64. package/lib/plugins/default-board-actions-plugin.js +56 -0
  65. package/lib/plugins/default-board-properties-plugin.js +101 -0
  66. package/lib/plugins/default-plugins.js +7 -0
  67. package/lib/plugins/epic-plugin.js +177 -0
  68. package/lib/plugins/extension-plugin.js +94 -0
  69. package/lib/plugins/index.js +9 -0
  70. package/lib/plugins/persist-tags-plugin.js +14 -0
  71. package/lib/plugins/plugin-manager.js +458 -0
  72. package/lib/plugins/plugin-registry.js +57 -0
  73. package/lib/project-factory.js +42 -0
  74. package/lib/project.js +864 -0
  75. package/lib/repository.js +1514 -0
  76. package/lib/task.js +780 -0
  77. package/lib/tools.js +176 -0
  78. package/lib/usecases/actions.js +32 -0
  79. package/lib/usecases/get-imdone-url.js +6 -0
  80. package/lib/usecases/get-project-tags.js +7 -0
  81. package/lib/usecases/get-tasks-in-file.js +26 -0
  82. package/lib/usecases/index.js +4 -0
  83. package/package.json +2 -6
  84. package/scripts/delete-markdown-indexes.js +87 -0
  85. package/scripts/generate-index.js +35 -0
  86. package/scripts/index-markdown.js +55 -0
  87. package/tsconfig.json +15 -0
  88. package/types/FileProjectContext.d.ts +4 -0
  89. package/types/ProjectContext.d.ts +9 -0
  90. package/types/adapters/date-time.d.ts +2 -0
  91. package/types/adapters/environment.d.ts +1 -0
  92. package/types/adapters/file-gateway.d.ts +51 -0
  93. package/types/adapters/git-download.d.ts +1 -0
  94. package/types/adapters/index.d.ts +9 -0
  95. package/types/adapters/logger.d.ts +24 -0
  96. package/types/adapters/markdown.d.ts +13 -0
  97. package/types/adapters/parsers/DateLanguageParser.d.ts +1 -0
  98. package/types/adapters/parsers/content-transformer.d.ts +10 -0
  99. package/types/adapters/parsers/file/LocalFileParserFactory.d.ts +5 -0
  100. package/types/adapters/parsers/file/ReadStreamCodeParser.d.ts +13 -0
  101. package/types/adapters/parsers/file/ReadStreamMarkdownParser.d.ts +7 -0
  102. package/types/adapters/parsers/file/ReadStreamTaskParser.d.ts +19 -0
  103. package/types/adapters/parsers/file/index.d.ts +4 -0
  104. package/types/adapters/parsers/function-parser.d.ts +1 -0
  105. package/types/adapters/parsers/index.d.ts +5 -0
  106. package/types/adapters/parsers/task/CardContentParser.d.ts +45 -0
  107. package/types/adapters/parsers/task/CheckStyleTaskParser.d.ts +12 -0
  108. package/types/adapters/parsers/task/CodeStyleTaskParser.d.ts +14 -0
  109. package/types/adapters/parsers/task/HashStyleTaskParser.d.ts +13 -0
  110. package/types/adapters/parsers/task/MarkdownStyleTaskParser.d.ts +14 -0
  111. package/types/adapters/parsers/task/TaskParser.d.ts +7 -0
  112. package/types/adapters/parsers/task/index.d.ts +6 -0
  113. package/types/adapters/storage/config.d.ts +6 -0
  114. package/types/adapters/storage/index.d.ts +2 -0
  115. package/types/adapters/storage/tags.d.ts +3 -0
  116. package/types/adapters/yaml.d.ts +2 -0
  117. package/types/card.d.ts +166 -0
  118. package/types/checksum.d.ts +8 -0
  119. package/types/config.d.ts +61 -0
  120. package/types/constants.d.ts +46 -0
  121. package/types/context/ApplicationContext.d.ts +24 -0
  122. package/types/context/index.d.ts +1 -0
  123. package/types/default-settings.d.ts +2 -0
  124. package/types/domain/entities/FileProjectContext.d.ts +5 -0
  125. package/types/domain/entities/View.d.ts +17 -0
  126. package/types/domain/entities/index.d.ts +1 -0
  127. package/types/domain/index.d.ts +2 -0
  128. package/types/domain/usecases/GetViewsUsecase.d.ts +4 -0
  129. package/types/domain/usecases/SaveViewUsecase.d.ts +8 -0
  130. package/types/domain/usecases/index.d.ts +2 -0
  131. package/types/file.d.ts +344 -0
  132. package/types/get-tasks-to-modify.d.ts +3 -0
  133. package/types/index.d.ts +23 -0
  134. package/types/languages.d.ts +649 -0
  135. package/types/list.d.ts +30 -0
  136. package/types/migrate-config.d.ts +1 -0
  137. package/types/mixins/index.d.ts +2 -0
  138. package/types/mixins/repo-fs-store.d.ts +2 -0
  139. package/types/mixins/repo-watched-fs-store.d.ts +2 -0
  140. package/types/plugins/archive-plugin.d.ts +8 -0
  141. package/types/plugins/default-board-actions-plugin.d.ts +9 -0
  142. package/types/plugins/default-board-properties-plugin.d.ts +16 -0
  143. package/types/plugins/default-plugins.d.ts +6 -0
  144. package/types/plugins/epic-plugin.d.ts +19 -0
  145. package/types/plugins/extension-plugin.d.ts +15 -0
  146. package/types/plugins/index.d.ts +9 -0
  147. package/types/plugins/persist-tags-plugin.d.ts +4 -0
  148. package/types/plugins/plugin-manager.d.ts +68 -0
  149. package/types/plugins/plugin-registry.d.ts +1 -0
  150. package/types/project-factory.d.ts +14 -0
  151. package/types/project.d.ts +158 -0
  152. package/types/repository.d.ts +996 -0
  153. package/types/task.d.ts +202 -0
  154. package/types/tools.d.ts +29 -0
  155. package/types/usecases/actions.d.ts +7 -0
  156. package/types/usecases/get-imdone-url.d.ts +1 -0
  157. package/types/usecases/get-project-tags.d.ts +1 -0
  158. package/types/usecases/get-tasks-in-file.d.ts +4 -0
  159. package/types/usecases/index.d.ts +4 -0
  160. package/vitest.config.js +13 -0
@@ -0,0 +1,116 @@
1
+ import { Eta } from "eta"
2
+ import uniqid from 'uniqid';
3
+
4
+ function removeDisplayComments(description) {
5
+ return description.replace(/<!--\s*\[([\s\S]*?)\]\s*-->/g, '$1');
6
+ }
7
+
8
+ function escapeCodeBlocks(content) {
9
+ const codeBlockRegex = /(```[\s\S]*?```|`[^`]*`)/g;
10
+ let codeBlocks = [];
11
+
12
+ // Replace code blocks with unique keys
13
+ content = content.replace(codeBlockRegex, (match) => {
14
+ const key = `__CODE_BLOCK_${codeBlocks.length}__`;
15
+ codeBlocks.push(match); // Maintain order
16
+ return key;
17
+ });
18
+
19
+ return { content, codeBlocks };
20
+ }
21
+
22
+ function restoreCodeBlocks(content, codeBlocks) {
23
+ // Restore code blocks in order using stored array
24
+ codeBlocks.forEach((code, index) => {
25
+ content = content.replace(`__CODE_BLOCK_${index}__`, code);
26
+ });
27
+ return content;
28
+ }
29
+
30
+ /**
31
+ * Interpolates the content with the provided data.
32
+ * @param {string} content - The content to interpolate.
33
+ * @param {object} data - The data to use for interpolation.
34
+ * @param {object} opts - The options for interpolation.
35
+ * @returns {object} - The interpolated content, whether there was interpolation, and error tokens.
36
+ */
37
+ export function interpolate(content, data, opts = { tags: ['${', '}'] }) {
38
+ const errorTokens = {};
39
+ const { tags } = opts;
40
+ // /(?<![`\\])\${([\s\S]+?)}/g
41
+ const regex = new RegExp(`(?<![\`\\\\])\\${tags[0]}([\\s\\S]+?)${tags[1]}`, 'g');
42
+ let hasInterpolation = false;
43
+
44
+ content = content.replace(regex, (match, p1) => {
45
+ try {
46
+ const eta = new Eta({ tags, useWith: true, autoEscape: false });
47
+ const [startTag, endTag] = opts.tags;
48
+ const template = `${startTag}= ${p1} ${endTag}`;
49
+ const result = eta.renderString(template, data);
50
+ if (result !== match) {
51
+ hasInterpolation = true;
52
+ }
53
+ return result || '';
54
+ } catch (e) {
55
+ const token = `__ERROR_TOKEN_${uniqid()}__`;
56
+ errorTokens[token] = match;
57
+ return token || '';
58
+ }
59
+ });
60
+
61
+ return { content, hasInterpolation, errorTokens };
62
+ }
63
+
64
+ export function encodeMarkdownLinks(content) {
65
+ return content.replace(/(?<!!)\[(.*?)\]\((.*?)( ".*?")?\)/g, (match, p1, p2, p3) => {
66
+ // URI encode file links
67
+ const title = p3 || '';
68
+ const encodedUrl = p2.replace(/\s/g, '%20').replace(/\)/g, '%29').replace(/\(/g, '%28');
69
+ const link = `[${p1}](${encodedUrl}${title})`;
70
+
71
+ // If there is more than one space in the URL, assume there's no title
72
+ if ((p2.match(/\s/g) || []).length > 1) {
73
+ return `[${p1}](${encodedUrl})`;
74
+ }
75
+
76
+ return link.replace(/%20(".*?"\))$/, ' $1');
77
+ });
78
+ }
79
+
80
+ export function format(content, data, mustache) {
81
+ const errorTokens = {};
82
+
83
+ if (mustache) content = removeDisplayComments(content);
84
+
85
+ // Escape code blocks before processing interpolation
86
+ const { content: escapedContent, codeBlocks } = escapeCodeBlocks(content);
87
+
88
+ let result = escapedContent;
89
+ let hasInterpolation = true;
90
+
91
+ while (hasInterpolation) {
92
+ const interpolationResult = interpolate(result, data, { tags: ['${', '}'] });
93
+ result = interpolationResult.content;
94
+ hasInterpolation = interpolationResult.hasInterpolation;
95
+ Object.assign(errorTokens, interpolationResult.errorTokens);
96
+ }
97
+
98
+ if (mustache) {
99
+ hasInterpolation = true;
100
+ while (hasInterpolation) {
101
+ const interpolationResult = interpolate(result, data, { tags: ['{{', '}}'] });
102
+ result = interpolationResult.content;
103
+ hasInterpolation = interpolationResult.hasInterpolation;
104
+ Object.assign(errorTokens, interpolationResult.errorTokens);
105
+ }
106
+ }
107
+
108
+ result = restoreCodeBlocks(result, codeBlocks);
109
+
110
+ // Restore error tokens
111
+ Object.keys(errorTokens).forEach(token => {
112
+ result = result.replace(new RegExp(token, 'g'), errorTokens[token]);
113
+ });
114
+
115
+ return result;
116
+ }
@@ -0,0 +1,36 @@
1
+ import { createReadStream } from 'node:fs'
2
+ import { ReadStreamMarkdownParser } from './ReadStreamMarkdownParser.js'
3
+ import path from 'node:path'
4
+ import { languages } from '../../../languages.js'
5
+ import { ReadStreamCodeParser } from './ReadStreamCodeParser.js'
6
+
7
+
8
+ export function getLang(config, filePath) {
9
+ const languages = getLanguages(config)
10
+ var lang = languages[path.extname(filePath)]
11
+ return lang || { name: 'text', symbol: '' }
12
+ }
13
+
14
+ export function getLanguages(config) {
15
+ const configLanguages = config.languages || {}
16
+ return { ...languages, ...configLanguages }
17
+ }
18
+
19
+ export async function getFileParser (filePath, config, readStream) {
20
+ if (!readStream) {
21
+ readStream = createReadStream(filePath)
22
+ }
23
+ const lang = getLang(config, filePath)
24
+ if (lang.name === 'text') {
25
+ return new ReadStreamMarkdownParser(readStream, config)
26
+ } else {
27
+ const parser = new ReadStreamCodeParser(
28
+ readStream,
29
+ filePath,
30
+ lang,
31
+ config.lists
32
+ )
33
+ await parser.init()
34
+ return parser
35
+ }
36
+ }
@@ -0,0 +1,126 @@
1
+ import path from 'node:path'
2
+ import { ReadStreamTaskParser } from './ReadStreamTaskParser.js'
3
+ import { CodeStyleTaskParser } from '../task/CodeStyleTaskParser.js'
4
+ import { languages } from '../../../languages.js'
5
+ import extractComments from 'multilang-extract-comments'
6
+ import eol from 'eol'
7
+ import { Readable } from 'node:stream'
8
+
9
+ // TODO Move to readstream parsing for code to improve performance
10
+ // <!--
11
+ // #important
12
+ // #imdone-1.55.0
13
+ // order:-205
14
+ // -->
15
+ export class ReadStreamCodeParser extends ReadStreamTaskParser {
16
+ constructor(readStream, filePath, lang, lists) {
17
+ super(readStream)
18
+ this.lists = lists
19
+ this.filePath = filePath
20
+ this.lang = lang
21
+ this.taskParsers = [new CodeStyleTaskParser()]
22
+ }
23
+
24
+ async init() {
25
+ const code = await streamToString(this.readStream)
26
+ // TODO Getting tokens from lists should be done higher up in the controller
27
+ // <!--
28
+ // order:-10
29
+ // -->
30
+ const tokens = this.lists.filter(list => !list.filter).map(list => list.name)
31
+ this.cards = this.parseCards(code, tokens)
32
+ }
33
+
34
+ async readTask() {
35
+ return this.cards.shift()
36
+ }
37
+
38
+ parseCards(code, tokens = ['TODO']) {
39
+ const comments = this.parseComments(code);
40
+ const cards = [];
41
+
42
+ Object.keys(comments).forEach((comment) => {
43
+ const { begin, end, content } = comments[comment];
44
+ const line = begin;
45
+ const lastLine = end; // TODO lastLine should not be - 1
46
+ // <!--
47
+ // order:-140
48
+ // -->
49
+ const lines = content.split('\n');
50
+
51
+ // Check if the comment contains "TODO"
52
+ lines.forEach(codeLine => {
53
+ if (tokens.find((token) => codeLine.includes(token))) {
54
+ // Get all lines from start to end
55
+
56
+ cards.push({
57
+ content,
58
+ line,
59
+ lastLine,
60
+ });
61
+ }
62
+ });
63
+ });
64
+ return cards;
65
+ }
66
+
67
+ parseComments(code) {
68
+ const options = getLanguageOptions(this.filePath);
69
+ const comments = extractComments(code, options);
70
+ return comments;
71
+ }
72
+
73
+ }
74
+
75
+
76
+ function getLanguageOptions(filePath) {
77
+ const extension = path.extname(filePath)
78
+ const language = languages[extension]
79
+
80
+
81
+ const {
82
+ name,
83
+ symbol,
84
+ block,
85
+ } = language ||
86
+ {
87
+ name: 'text',
88
+ symbol: '',
89
+ block: {
90
+ start: undefined,
91
+ end: undefined,
92
+ ignore: undefined,
93
+ }
94
+ };
95
+ // Use lang to get comment patterns
96
+
97
+ const {
98
+ start,
99
+ ignore: middle,
100
+ end
101
+ } = block || {};
102
+
103
+ return language && {
104
+ pattern: {
105
+ name,
106
+ nameMatchers: extension && [extension] || [],
107
+ singleLineComment: symbol && [{ start: symbol }] || [],
108
+ multiLineComment: start && end && [{ start, middle, end }] || [],
109
+ },
110
+ };
111
+ }
112
+
113
+ async function streamToString(stream) {
114
+ const chunks = []
115
+
116
+ for await (const chunk of stream) {
117
+ chunks.push(Buffer.from(chunk))
118
+ }
119
+
120
+ return Buffer.concat(chunks).toString('utf-8')
121
+ }
122
+
123
+ function stringToStream(string) {
124
+ const lines = eol.split(string).map((line) => line + String(eol.auto))
125
+ return Readable.from(lines)
126
+ }
@@ -0,0 +1,17 @@
1
+ import { ReadStreamTaskParser } from './ReadStreamTaskParser.js'
2
+ import { HashStyleTaskParser } from '../task/HashStyleTaskParser.js'
3
+ import { MarkdownStyleTaskParser } from '../task/MarkdownStyleTaskParser.js'
4
+ // const CheckStyleTaskParser = require('../task/CheckStyleTaskParser')
5
+
6
+ export class ReadStreamMarkdownParser extends ReadStreamTaskParser {
7
+ constructor(readStream, config) {
8
+ super(readStream, config)
9
+ this.taskParsers = [
10
+ new HashStyleTaskParser(config),
11
+ new MarkdownStyleTaskParser(config),
12
+ ]
13
+ // if (config.isAddCheckBoxTasks()) {
14
+ // this.taskParsers.push(new CheckStyleTaskParser())
15
+ // }
16
+ }
17
+ }
@@ -0,0 +1,106 @@
1
+ import * as ReadLine from 'node:readline/promises';
2
+ import { logger } from '../../logger.js';
3
+
4
+ const blankLinesToEndTask = 2
5
+
6
+ export class ReadStreamTaskParser {
7
+ constructor(readStream) {
8
+ this.readStream = readStream
9
+ this.task = null
10
+ this.line = null
11
+ this.taskParsers = []
12
+ this.lineNo = 0
13
+ this.blankLines = 0
14
+ this.readInterface = ReadLine.createInterface({
15
+ input: this.readStream,
16
+ crlfDelay: Infinity,
17
+ console: false,
18
+ })
19
+ }
20
+
21
+ async readTask() {
22
+ let taskOrStreamDone = false
23
+ this.task = this.nextTask || null
24
+ this.blankLines = 0
25
+
26
+ try {
27
+ while (!taskOrStreamDone) {
28
+ this.line = await this.readLine()
29
+ let { value, done } = this.line
30
+ if (this.line && !done) {
31
+ this.lineNo++
32
+ const endOfTask = this.isEndOfTask(value)
33
+ if (this.task && endOfTask) {
34
+ taskOrStreamDone = true
35
+ } else if (this.task) {
36
+ this.addLineToTask(value)
37
+ } else {
38
+ this.task = this.getTaskFromLine(value)
39
+ }
40
+ } else {
41
+ taskOrStreamDone = true
42
+ }
43
+ }
44
+ } catch (error) {
45
+ logger.log('Error reading line')
46
+ throw error
47
+ }
48
+
49
+ this.trimLinesToEndTask()
50
+ return this.task
51
+ }
52
+
53
+ async readLine() {
54
+ return this.readInterface[Symbol.asyncIterator]().next()
55
+ }
56
+
57
+ isEndOfTask(line) {
58
+ if (line.trim() === '') {
59
+ this.blankLines++
60
+ } else {
61
+ this.blankLines = 0
62
+ }
63
+
64
+ this.nextTask = this.getTaskFromLine(line)
65
+
66
+ if (this.blankLines > blankLinesToEndTask - 1) {
67
+ this.nextTask = undefined
68
+ return true
69
+ }
70
+
71
+ if (this.nextTask) {
72
+ return true
73
+ }
74
+
75
+ return false
76
+ }
77
+
78
+ getTaskFromLine(line) {
79
+ let task
80
+ this.taskParsers.find((taskParser) => {
81
+ task = taskParser.parseLine(line, this.lineNo, this.task)
82
+ return task
83
+ })
84
+ return task
85
+ }
86
+
87
+ addLineToTask(line) {
88
+ this.task.description.push(line)
89
+ this.task.lastLine = this.lineNo
90
+ }
91
+
92
+ trimLinesToEndTask() {
93
+ if (!this.task) return
94
+
95
+ // Remove the empty strings from the end of the task description
96
+ while (this.task.description[this.task.description.length - 1] === '') {
97
+ this.task.description.pop()
98
+ }
99
+ this.task.lastLine = this.task.line + this.task.description.length
100
+ }
101
+
102
+ close() {
103
+ this.readInterface.close()
104
+ if (this.readStream.close) this.readStream.close()
105
+ }
106
+ }
@@ -0,0 +1,4 @@
1
+ export * from './LocalFileParserFactory.js';
2
+ export * from './ReadStreamCodeParser.js';
3
+ export * from './ReadStreamMarkdownParser.js';
4
+ export * from './ReadStreamTaskParser.js';
@@ -0,0 +1,25 @@
1
+ export function getFunctionSignature(fn) {
2
+ if (typeof fn !== "function") {
3
+ throw new TypeError("Expected a function");
4
+ }
5
+
6
+ const fnString = fn.toString().trim();
7
+ let name = fn.name || "anonymous";
8
+ let params = "";
9
+
10
+ // Match function parameters
11
+ const paramMatch = fnString.match(/\(([^)]*)\)/);
12
+ if (paramMatch) {
13
+ params = paramMatch[1].trim();
14
+ } else {
15
+ // Handle arrow functions without parentheses
16
+ const arrowMatch = fnString.match(/^(?:\S+\s+)?(\w+)?\s*=?\s*(?:async\s*)?\(?([^)=]*)\)?\s*=>/);
17
+ if (arrowMatch) {
18
+ name = name || arrowMatch[1] || "anonymous";
19
+ params = arrowMatch[2].trim();
20
+ }
21
+ }
22
+
23
+ return `${name}(${params})`;
24
+ }
25
+
@@ -0,0 +1,5 @@
1
+ export * from './DateLanguageParser.js';
2
+ export * from './content-transformer.js';
3
+ export * from './function-parser.js';
4
+ export * as file from './file/index.js';
5
+ export * as task from './task/index.js';