imdone-core 1.47.0 → 1.47.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.
@@ -2,7 +2,6 @@ const { createReadStream } = require('fs')
2
2
  const ReadStreamMarkdownParser = require('./ReadStreamMarkdownParser')
3
3
  const path = require('path')
4
4
  const languages = require('../../../languages')
5
- const appContext = require('../../../context/ApplicationContext')
6
5
  const ReadStreamCodeParser = require('./ReadStreamCodeParser')
7
6
 
8
7
  function getLang(languages, filePath) {
@@ -15,21 +14,27 @@ function getLanguages(config) {
15
14
  return { ...languages, ...configLanguages }
16
15
  }
17
16
 
18
- module.exports = {
19
- async getFileParser(filePath) {
20
- const { config } = appContext()
21
- const languages = getLanguages(config)
22
- const lang = getLang(languages, filePath)
23
- if (lang.name === 'text') {
24
- return new ReadStreamMarkdownParser(createReadStream(filePath))
25
- } else {
26
- const parser = new ReadStreamCodeParser(
27
- createReadStream(filePath),
28
- filePath,
29
- lang
30
- )
31
- await parser.init()
32
- return parser
33
- }
34
- },
17
+ // DOING Use task line parsers for vs code extension and obsidian plugin
18
+ // <!--
19
+ // order:-10000030
20
+ // -->
21
+
22
+ module.exports.getFileParser = async function getFileParser (filePath, config, readStream) {
23
+ if (!readStream) {
24
+ readStream = createReadStream(filePath)
25
+ }
26
+ const languages = getLanguages(config)
27
+ const lang = getLang(languages, filePath)
28
+ if (lang.name === 'text') {
29
+ return new ReadStreamMarkdownParser(readStream, config)
30
+ } else {
31
+ const parser = new ReadStreamCodeParser(
32
+ readStream,
33
+ filePath,
34
+ lang,
35
+ config.lists
36
+ )
37
+ await parser.init()
38
+ return parser
39
+ }
35
40
  }
@@ -1,121 +1,114 @@
1
1
  const path = require('path')
2
2
  const ReadStreamTaskParser = require('./ReadStreamTaskParser')
3
3
  const CodeStyleTaskParser = require('../task/CodeStyleTaskParser')
4
+ const languages = require('../../../languages')
4
5
  const extractComments = require('multilang-extract-comments')
5
6
  const eol = require('eol')
6
- const ReadLine = require('readline')
7
7
  const { Readable } = require('stream')
8
8
 
9
- async function streamToString(stream) {
10
- const chunks = []
11
-
12
- for await (const chunk of stream) {
13
- chunks.push(Buffer.from(chunk))
14
- }
15
-
16
- return Buffer.concat(chunks).toString('utf-8')
17
- }
18
-
19
- function stringToStream(string) {
20
- const lines = eol.split(string).map((line) => line + String(eol.auto))
21
- return Readable.from(lines)
22
- }
23
-
24
9
  module.exports = class ReadStreamCodeParser extends ReadStreamTaskParser {
25
- constructor(readStream, filePath, lang) {
10
+ constructor(readStream, filePath, lang, lists) {
26
11
  super(readStream)
12
+ this.lists = lists
27
13
  this.filePath = filePath
28
14
  this.lang = lang
29
15
  this.taskParsers = [new CodeStyleTaskParser()]
30
16
  }
31
17
 
32
18
  async init() {
33
- const content = await streamToString(this.readStream)
34
- this.comments = await this.extractComments(content)
35
- this.readStream = stringToStream(content)
36
- this.readInterface = this.getReadInterface()
37
-
38
- let line = null
39
- let lines = []
40
- let lineNo = 1
41
- let comment = null
42
- do {
43
- const { value, done } = await this.readLine()
44
- line = done ? null : value
45
- comment = this.getCommentAtLine(lineNo)
46
- let lineInComment = ''
47
- if (comment) {
48
- lineInComment = comment.lines[lineNo - comment.begin]
49
- }
50
- lines.push(lineInComment)
51
- lineNo += 1
52
- } while (line !== null)
53
- this.readInterface.close()
54
- this.readStream = Readable.from(
55
- lines.map((line) => line + String(eol.auto))
56
- )
57
- this.readInterface = this.getReadInterface()
19
+ const code = await streamToString(this.readStream)
20
+ // TODO Getting tokens from lists should be done higher up in the controller
21
+ const tokens = this.lists.filter(list => !list.filter).map(list => list.name)
22
+ this.cards = this.parseCards(code, tokens)
58
23
  }
59
24
 
60
25
  async readTask() {
61
- const task = await super.readTask()
62
- task.multiLineComment =
63
- this.getCommentAtLine(task.line).info.type === 'multiline'
64
- task.descriptionStartsWith = task.multiLineComment
65
- ? this.lang.block.ignore
66
- : this.lang.symbol
67
-
68
- return task
26
+ return this.cards.shift()
69
27
  }
70
28
 
71
- getCommentAtLine(lineNo) {
72
- return this.comments.find(
73
- (comment) => lineNo >= comment.begin && lineNo <= comment.end
74
- )
29
+ parseCards(code, tokens = ['TODO']) {
30
+ const comments = this.parseComments(code);
31
+ const cards = [];
32
+
33
+ Object.keys(comments).forEach((comment) => {
34
+ const { begin, end, content } = comments[comment];
35
+ const line = begin;
36
+ const lastLine = end - 1;
37
+ const lines = content.split('\n');
38
+
39
+ // Check if the comment contains "TODO"
40
+ lines.forEach(codeLine => {
41
+ if (tokens.find((token) => codeLine.includes(token))) {
42
+ // Get all lines from start to end
43
+
44
+ cards.push({
45
+ content,
46
+ line,
47
+ lastLine,
48
+ });
49
+ }
50
+ });
51
+ });
52
+ return cards;
75
53
  }
76
-
77
- getReadInterface() {
78
- return ReadLine.createInterface({
79
- input: this.readStream,
80
- crlfDelay: Infinity,
81
- console: false,
82
- })
54
+
55
+ parseComments(code) {
56
+ const options = getLanguageOptions(this.filePath);
57
+ const comments = extractComments(code, options);
58
+ return comments;
83
59
  }
60
+
61
+ }
84
62
 
85
- async extractComments(content) {
86
- const lang = this.lang
87
- const multiLineComment = lang.block
88
- ? [
89
- {
90
- start: lang.block.start,
91
- middle: lang.block.ignore,
92
- end: lang.block.end,
93
- },
94
- ]
95
- : []
96
- const options = {
97
- pattern: {
98
- name: lang.name,
99
- nameMatchers: [path.extname(this.filePath)],
100
- singleLineComment: [{ start: lang.symbol }],
101
- multiLineComment,
102
- },
103
- }
104
- const comments = extractComments(content, options)
105
- const contentLines = eol.split(content)
106
- return Object.values(comments).map((comment) => {
107
- const lines = eol.split(comment.content)
108
- const linesInContent = contentLines.slice(comment.begin - 1, comment.end)
109
- let contentStartIndex = linesInContent.findIndex((line) =>
110
- line.includes(lines[0])
111
- )
112
- for (let i = 0; i < contentStartIndex; i++) {
113
- lines.unshift('')
114
- }
115
- return {
116
- ...comment,
117
- lines,
63
+
64
+ function getLanguageOptions(filePath) {
65
+ const extension = path.extname(filePath)
66
+ const language = languages[extension]
67
+
68
+
69
+ const {
70
+ name,
71
+ symbol,
72
+ block,
73
+ } = language ||
74
+ {
75
+ name: 'text',
76
+ symbol: '',
77
+ block: {
78
+ start: undefined,
79
+ end: undefined,
80
+ ignore: undefined,
118
81
  }
119
- })
82
+ };
83
+ // Use lang to get comment patterns
84
+
85
+ const {
86
+ start,
87
+ ignore: middle,
88
+ end
89
+ } = block || {};
90
+
91
+ return language && {
92
+ pattern: {
93
+ name,
94
+ nameMatchers: extension && [extension] || [],
95
+ singleLineComment: symbol && [{ start: symbol }] || [],
96
+ multiLineComment: start && end && [{ start, middle, end }] || [],
97
+ },
98
+ };
99
+ }
100
+
101
+ async function streamToString(stream) {
102
+ const chunks = []
103
+
104
+ for await (const chunk of stream) {
105
+ chunks.push(Buffer.from(chunk))
120
106
  }
107
+
108
+ return Buffer.concat(chunks).toString('utf-8')
109
+ }
110
+
111
+ function stringToStream(string) {
112
+ const lines = eol.split(string).map((line) => line + String(eol.auto))
113
+ return Readable.from(lines)
121
114
  }
@@ -1,19 +1,17 @@
1
1
  const ReadStreamTaskParser = require('./ReadStreamTaskParser')
2
2
  const HashStyleTaskParser = require('../task/HashStyleTaskParser')
3
3
  const MarkdownStyleTaskParser = require('../task/MarkdownStyleTaskParser')
4
- const CheckStyleTaskParser = require('../task/CheckStyleTaskParser')
5
- const appContext = require('../../../context/ApplicationContext')
4
+ // const CheckStyleTaskParser = require('../task/CheckStyleTaskParser')
6
5
 
7
6
  module.exports = class ReadStreamMarkdownParser extends ReadStreamTaskParser {
8
- constructor(readStream) {
9
- super(readStream)
10
- const { config } = appContext()
7
+ constructor(readStream, config) {
8
+ super(readStream, config)
11
9
  this.taskParsers = [
12
- new HashStyleTaskParser(),
13
- new MarkdownStyleTaskParser(),
10
+ new HashStyleTaskParser(config),
11
+ new MarkdownStyleTaskParser(config),
14
12
  ]
15
- if (config.isAddCheckBoxTasks()) {
16
- this.taskParsers.push(new CheckStyleTaskParser())
17
- }
13
+ // if (config.isAddCheckBoxTasks()) {
14
+ // this.taskParsers.push(new CheckStyleTaskParser())
15
+ // }
18
16
  }
19
17
  }
@@ -1,19 +1,14 @@
1
- const appContext = require('../../../context/ApplicationContext')
2
- const Config = require('../../../config')
3
1
  const ReadLine = require('readline')
4
- const START_TAG = '<card>'
5
- const END_TAG = '</card>'
2
+ const blankLinesToEndTask = 2
6
3
 
7
4
  module.exports = class ReadStreamTaskParser {
8
5
  constructor(readStream) {
9
- this.config = appContext().config
10
6
  this.readStream = readStream
11
7
  this.task = null
12
8
  this.line = null
13
9
  this.taskParsers = []
14
10
  this.lineNo = 0
15
11
  this.blankLines = 0
16
- this.blankLinesToEndTask = this.config.blankLinesToEndTask
17
12
  this.readInterface = ReadLine.createInterface({
18
13
  input: this.readStream,
19
14
  crlfDelay: Infinity,
@@ -23,9 +18,8 @@ module.exports = class ReadStreamTaskParser {
23
18
 
24
19
  async readTask() {
25
20
  let taskOrStreamDone = false
26
- this.task = null
21
+ this.task = this.nextTask || null
27
22
  this.blankLines = 0
28
- this.hasStartTag = false
29
23
 
30
24
  try {
31
25
  while (!taskOrStreamDone) {
@@ -50,7 +44,7 @@ module.exports = class ReadStreamTaskParser {
50
44
  throw error
51
45
  }
52
46
 
53
- this.trimBlankLinesToEndTask()
47
+ this.trimLinesToEndTask()
54
48
  return this.task
55
49
  }
56
50
 
@@ -59,19 +53,24 @@ module.exports = class ReadStreamTaskParser {
59
53
  }
60
54
 
61
55
  isEndOfTask(line) {
62
- if (this.task && this.task.hasCardTags) return true
63
- if (this.hasStartTag) return false
64
-
65
56
  if (line.trim() === '') {
66
57
  this.blankLines++
67
58
  } else {
68
59
  this.blankLines = 0
69
60
  }
70
61
 
71
- return (
72
- this.getTaskFromLine(this.line.value) ||
73
- this.blankLines > this.blankLinesToEndTask - 1
74
- )
62
+ this.nextTask = this.getTaskFromLine(line)
63
+
64
+ if (this.blankLines > blankLinesToEndTask - 1) {
65
+ this.nextTask = undefined
66
+ return true
67
+ }
68
+
69
+ if (this.nextTask) {
70
+ return true
71
+ }
72
+
73
+ return false
75
74
  }
76
75
 
77
76
  getTaskFromLine(line) {
@@ -84,30 +83,23 @@ module.exports = class ReadStreamTaskParser {
84
83
  }
85
84
 
86
85
  addLineToTask(line) {
87
- if (line.trim() === START_TAG && this.task.description.length == 0) {
88
- this.hasStartTag = true
89
- } else if (line.trim() === END_TAG && this.hasStartTag) {
90
- this.task.hasCardTags = true
91
- } else {
92
- this.task.description.push(line)
93
- }
94
-
86
+ this.task.description.push(line)
95
87
  this.task.lastLine = this.lineNo
96
88
  }
97
89
 
98
- trimBlankLinesToEndTask() {
90
+ trimLinesToEndTask() {
99
91
  if (!this.task) return
100
92
  if (
101
- this.blankLines == this.blankLinesToEndTask &&
102
- this.blankLinesToEndTask > 1 &&
103
- !this.task.hasCardTags
93
+ this.blankLines == blankLinesToEndTask
104
94
  ) {
105
- this.task.description.splice(
106
- this.task.description.length - this.blankLines + 1,
107
- this.blankLinesToEndTask - 1
108
- )
109
- this.task.lastLine = this.task.lastLine - this.blankLines
95
+ this.task.description.length = this.task.description.length - (this.blankLines - 1)
96
+ } else if (this.nextTask){
97
+ this.task.description.length = this.task.description.length - (this.blankLines + 1)
98
+ } else {
99
+ this.task.description.length = this.task.description.length - this.blankLines
110
100
  }
101
+
102
+ this.task.lastLine = this.task.line + this.task.description.length - 1
111
103
  }
112
104
 
113
105
  close() {
@@ -23,8 +23,8 @@ const LINK_STYLE_REGEX = new XRegExp(
23
23
 
24
24
  const CHECK_REGEX = /^(\s*- )\[([x ])\]/
25
25
 
26
- function getHashStyleRegex(tokenPrefix = DEFAULT_TOKEN_PREFIX, metaOrder = false) {
27
- return metaOrder ?
26
+ function getHashStyleRegex(tokenPrefix = DEFAULT_TOKEN_PREFIX, orderMeta = false) {
27
+ return orderMeta ?
28
28
  new XRegExp(
29
29
  `${tokenPrefix}(${LIST_NAME_PATTERN})[ \\t]+(.+)$`, 'gm'
30
30
  ) :
@@ -1,8 +1,8 @@
1
1
  const TaskParser = require('./TaskParser')
2
2
 
3
3
  module.exports = class CodeStyleTaskParser extends TaskParser {
4
- constructor() {
5
- super('CODE')
4
+ constructor(config) {
5
+ super('CODE', config)
6
6
  }
7
7
 
8
8
  get pattern() {
@@ -1,23 +1,26 @@
1
1
  const TaskParser = require('./TaskParser')
2
+ const { getHashStyleRegex } = require('./CardContentParser')
2
3
 
3
4
  module.exports = class HashStyleTaskParser extends TaskParser {
4
- constructor() {
5
- super('HASHTAG')
5
+ constructor(config) {
6
+ super('HASHTAG', config)
6
7
  }
7
8
 
8
9
  get pattern() {
9
- return /^(.*?)#([a-zA-Z-_]+?)((:)(-?[\d.]+(?:e-?\d+)?)?)?[ \t]+(.+)$/gm
10
+ const config = this.config
11
+ return getHashStyleRegex(config.tokenPrefix, config.orderMeta)
10
12
  }
11
13
 
12
14
  parse(lineContent, line, matchResult) {
13
- const [match, beforeText, list, orderGroup, colon, order, text] = matchResult
15
+ const [rawTask, list, orderGroup, order, text] = matchResult
16
+
14
17
  return {
15
- beforeText,
18
+ // beforeText,
16
19
  text,
17
20
  order,
18
21
  list,
19
22
  line,
20
- colon,
23
+ colon: orderGroup && orderGroup.startsWith(':'),
21
24
  type: this.type,
22
25
  }
23
26
  }
@@ -1,8 +1,8 @@
1
1
  const TaskParser = require('./TaskParser')
2
2
 
3
3
  module.exports = class MarkdownStyleTaskParser extends TaskParser {
4
- constructor() {
5
- super('MARKDOWN')
4
+ constructor(config) {
5
+ super('MARKDOWN', config)
6
6
  }
7
7
 
8
8
  get pattern() {
@@ -1,5 +1,3 @@
1
- const Config = require('../../../config')
2
- const appContext = require('../../../context/ApplicationContext')
3
1
 
4
2
  class Task {
5
3
  constructor({ beforeText, text, list, line, order, checked, colon, type }) {
@@ -17,8 +15,8 @@ class Task {
17
15
  }
18
16
 
19
17
  module.exports = class TaskParser {
20
- constructor(type) {
21
- this.config = appContext().config
18
+ constructor(type, config) {
19
+ this.config = config
22
20
  this.type = type
23
21
  }
24
22
 
package/lib/config.js CHANGED
@@ -207,18 +207,6 @@ class Config {
207
207
  return this.getDoneList()
208
208
  }
209
209
 
210
- get blankLinesToEndTask() {
211
- let blankLinesToEndTask = Math.round(
212
- _get(this, 'settings.cards.blankLinesToEndTask', 1)
213
- )
214
- if (blankLinesToEndTask > 2) {
215
- blankLinesToEndTask = 2
216
- } else if (blankLinesToEndTask < 1) {
217
- blankLinesToEndTask = 1
218
- }
219
- return blankLinesToEndTask
220
- }
221
-
222
210
  getMetaSep() {
223
211
  const metaSep = _get(this, 'settings.cards.metaSep', COLON)
224
212
  return META_SEPS.includes(metaSep) ? metaSep : COLON
@@ -0,0 +1,31 @@
1
+ const Config = require('../config')
2
+
3
+ class ApplicationContext {
4
+ constructor({
5
+ project,
6
+ repo,
7
+ projectContext,
8
+ projectReader,
9
+ projectPresenter,
10
+ }) {
11
+ this.project = project;
12
+ this.repo = repo;
13
+ this.projectContext = projectContext;
14
+ this.projectReader = projectReader;
15
+ this.projectPresenter = projectPresenter;
16
+ this.innerConfig = Config.newDefaultConfig()
17
+ }
18
+
19
+ set config(config) {
20
+ this.innerConfig = config
21
+ this.repo && (this.repo.config = config)
22
+ }
23
+
24
+ get config() {
25
+ return (this.repo && this.repo.config) || this.innerConfig
26
+ }
27
+
28
+ }
29
+ const context = new ApplicationContext({})
30
+
31
+ module.exports = () => context
@@ -1,11 +1,6 @@
1
- const languages = require('../languages')
2
1
  const Config = require('../config')
3
- const File = require('../file')
4
- const pluginManager = {
5
- onTaskUpdate: () => {},
6
- getCardProperties: () => { return {} },
7
- getCardActions: () => [],
8
- }
2
+ const { getFileParser } = require('../adapters/parsers/file/LocalFileParserFactory')
3
+ const { Readable } = require('stream');
9
4
 
10
5
  // DOING Use task line parsers for vs code extension and obsidian plugin
11
6
  // <!--
@@ -14,14 +9,23 @@ const pluginManager = {
14
9
  export async function getTasks({filePath, content}) {
15
10
  const projectPath = await Config.findImdonePath(filePath)
16
11
  const config = await Config.load(projectPath)
17
- const project = { path: projectPath, config, pluginManager }
18
- // var file = new File({
19
- // repoId: projectPath,
20
- // filePath,
21
- // content,
22
- // languages,
23
- // project,
24
- // })
25
12
 
26
- // return file.extractTasks(config).getTasks()
13
+ // create a readstream from the content and pass it to getFileParser
14
+ const readStream = new Readable({
15
+ read() {
16
+ this.push(content);
17
+ this.push(null); // Signals the end of the stream
18
+ }
19
+ });
20
+
21
+ const parser = await getFileParser(filePath, config, readStream)
22
+
23
+ const tasks = []
24
+ let task = true
25
+ while (task) {
26
+ task = await parser.readTask()
27
+ if (task) tasks.push(task)
28
+ }
29
+ parser.close()
30
+ return tasks
27
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imdone-core",
3
- "version": "1.47.0",
3
+ "version": "1.47.1",
4
4
  "description": "imdone-core",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -99,6 +99,7 @@
99
99
  "multilang-extract-comments": "^0.4.0",
100
100
  "open": "^9.1.0",
101
101
  "ora": "^5.4.1",
102
+ "parse-code-context": "^1.0.0",
102
103
  "prompts": "^2.4.2",
103
104
  "readdirp": "^3.6.0",
104
105
  "remove-markdown": "^0.3.0",
@@ -1,6 +0,0 @@
1
- # Tasks
2
-
3
- - [ ] ## #DOING Use task line parsers for vs code extension and obsidian plugin
4
- <!--
5
- order:-10000030
6
- -->