comment-block-transformer 0.1.1 → 0.2.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # 0.2.0 (2025-10-25)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * exclude manual test directory from test runner ([f2e9b1a](https://github.com/DavidWells/markdown-magic/commit/f2e9b1ad0754cfd7f797ed3b09a3df622675525f)), closes [#105](https://github.com/DavidWells/markdown-magic/issues/105)
12
+
13
+
14
+ ### Features
15
+
16
+ * add comprehensive tests for block-transformer with multiple plugins and middleware ([1c7df35](https://github.com/DavidWells/markdown-magic/commit/1c7df357a41933e98d3da377277829b6b628c76b)), closes [#86](https://github.com/DavidWells/markdown-magic/issues/86)
17
+ * setup pnpm workspace with proper dependency linking ([0c8c2f9](https://github.com/DavidWells/markdown-magic/commit/0c8c2f9e10e11918f0e446e1793878825ec88c14)), closes [#88](https://github.com/DavidWells/markdown-magic/issues/88)
package/package.json CHANGED
@@ -1,11 +1,21 @@
1
1
  {
2
2
  "name": "comment-block-transformer",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Transform markdown blocks based on configured transforms",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
7
+ "scripts": {
8
+ "test": "uvu test '.test.([mc]js|[jt]sx?)$'",
9
+ "build": "pnpm run types",
10
+ "types": "tsc --emitDeclarationOnly --outDir types",
11
+ "clean": "rimraf types",
12
+ "publish": "git push origin && git push origin --tags",
13
+ "release:patch": "pnpm run build && pnpm version patch && pnpm publish",
14
+ "release:minor": "pnpm run build && pnpm version minor && pnpm publish",
15
+ "release:major": "pnpm run build && pnpm version major && pnpm publish"
16
+ },
7
17
  "dependencies": {
8
- "comment-block-parser": "1.0.7"
18
+ "comment-block-parser": "1.1.0"
9
19
  },
10
20
  "devDependencies": {
11
21
  "typescript": "^5.0.0",
@@ -14,13 +24,5 @@
14
24
  "publishConfig": {
15
25
  "access": "public"
16
26
  },
17
- "scripts": {
18
- "test": "uvu test",
19
- "build": "pnpm run types",
20
- "types": "tsc --emitDeclarationOnly --outDir types",
21
- "clean": "rimraf types",
22
- "release:patch": "pnpm run build && pnpm version patch && pnpm publish",
23
- "release:minor": "pnpm run build && pnpm version minor && pnpm publish",
24
- "release:major": "pnpm run build && pnpm version major && pnpm publish"
25
- }
26
- }
27
+ "gitHead": "546a15fac58d28315057449adf122a5ab8575901"
28
+ }
package/src/index.js CHANGED
@@ -121,7 +121,7 @@ async function blockTransformer(inputText, config) {
121
121
  }
122
122
 
123
123
 
124
- const { COMMENT_OPEN_REGEX, COMMENT_CLOSE_REGEX } = foundBlocks
124
+ const { openPattern, closePattern } = foundBlocks
125
125
 
126
126
 
127
127
  const blocksWithTransforms = foundBlocks.blocks
@@ -136,8 +136,8 @@ async function blockTransformer(inputText, config) {
136
136
 
137
137
  const regexInfo = {
138
138
  blocks: foundBlocks.pattern,
139
- open: COMMENT_OPEN_REGEX,
140
- close: COMMENT_CLOSE_REGEX,
139
+ open: openPattern,
140
+ close: closePattern,
141
141
  }
142
142
 
143
143
  const transformsToRun = sortTransforms(blocksWithTransforms, transforms)
@@ -211,6 +211,8 @@ async function blockTransformer(inputText, config) {
211
211
  }
212
212
 
213
213
  let newContent = afterContent.content.value
214
+
215
+ // console.log("afterContent.content.rawValue", afterContent.content.rawValue)
214
216
  /* handle different cases of typeof newContent. @TODO: make this an option */
215
217
  if (typeof newContent === 'number') {
216
218
  newContent = String(newContent)
@@ -220,14 +222,28 @@ async function blockTransformer(inputText, config) {
220
222
  newContent = JSON.stringify(newContent, null, 2)
221
223
  }
222
224
 
223
- const formattedNewContent = (options.noTrim) ? newContent : trimString(newContent)
224
- const fix = removeConflictingComments(formattedNewContent, COMMENT_OPEN_REGEX, COMMENT_CLOSE_REGEX)
225
+ // console.log('options', options)
226
+ // console.log('newContent', `"${newContent}"`)
227
+
228
+ const formattedNewContent = (options.noTrim) ? newContent : newContent
229
+ // const formattedNewContent = newContent//.trim()
230
+ // console.log('formattedNewContent', `"${formattedNewContent}"`)
231
+ const fix = removeConflictingComments(formattedNewContent, openPattern, closePattern)
232
+
233
+ // console.log('fix', `"${fix}"`)
225
234
 
226
235
  let preserveIndent = 0
227
- if (match.content.indentation) {
228
- preserveIndent = match.content.indentation.length
236
+ // console.log('match.content.indent', match.content.indent)
237
+ if (match.content.indent) {
238
+ preserveIndent = match.content.indent
239
+ // console.log('preserveIndent', preserveIndent)
229
240
  } else if (preserveIndent === 0) {
230
- preserveIndent = block.indentation.length
241
+ preserveIndent = block.indent
242
+ }
243
+
244
+ // Don't apply indentation for single-line content when original was also single-line
245
+ if (!context.isMultiline && !block.match.includes('\n')) {
246
+ preserveIndent = 0
231
247
  }
232
248
 
233
249
  let addTrailingNewline = ''
@@ -259,6 +275,9 @@ async function blockTransformer(inputText, config) {
259
275
 
260
276
  const stripComments = isNewPath && removeComments
261
277
 
278
+
279
+ // console.log('inputText', inputText)
280
+ // console.log('updatedContents', updatedContents)
262
281
  return {
263
282
  isChanged: inputText !== updatedContents,
264
283
  isNewPath,
@@ -300,7 +319,7 @@ function getDetails({
300
319
  }
301
320
 
302
321
  if (srcPath) {
303
- const location = getCodeLocation(srcPath, foundBlock.block.lines[0])
322
+ const location = getCodeLocation(srcPath, foundBlock.lines[0])
304
323
  foundBlock.sourceLocation = location
305
324
  }
306
325
  return foundBlock
@@ -387,10 +406,30 @@ function trimString(str) {
387
406
  return str.trim()
388
407
  }
389
408
 
409
+ /**
410
+ * Trim leading and trailing lines from a string
411
+ * @param {string} str - The string to trim
412
+ * @returns {string} The string with leading and trailing lines removed
413
+ */
414
+ function trimLeadingAndTrailing(str) {
415
+ if (!str) return str
416
+ return str.replace(/^\s*\n+/, '').replace(/\n+\s*$/, '')
417
+ }
418
+
390
419
  function getCodeLocation(srcPath, line, column = '0') {
391
420
  return `${srcPath}:${line}:${column}`
392
421
  }
393
422
 
423
+ if (require.main === module) {
424
+ const yaml = `
425
+ - name: Run tests two
426
+ run: npm test two
427
+ `
428
+
429
+ // console.log(indentString(yaml, 4))
430
+ }
431
+
394
432
  module.exports = {
395
- blockTransformer
433
+ blockTransformer,
434
+ indentString,
396
435
  }
@@ -0,0 +1,90 @@
1
+ const core = require('@actions/core')
2
+ const github = require('@actions/github')
3
+
4
+ async function main() {
5
+ const context = github.context
6
+
7
+ let issueNumber, prNumber, headRef, baseRef, headSha, isPR = false;
8
+ let triggerText = '';
9
+
10
+ if (context.eventName === 'pull_request_target') {
11
+ // When a PR is created or updated
12
+ isPR = true;
13
+ issueNumber = context.payload.pull_request.number;
14
+ prNumber = context.payload.pull_request.number;
15
+ headRef = context.payload.pull_request.head.ref;
16
+ baseRef = context.payload.pull_request.base.ref;
17
+ headSha = context.payload.pull_request.head.sha;
18
+ triggerText = context.payload.pull_request.body;
19
+
20
+ console.log(`PR #${prNumber}: ${baseRef} <- ${headRef} (${headSha})`);
21
+
22
+ } else if (context.eventName === 'issues') {
23
+ // When an Issue is created or assigned
24
+ isPR = false;
25
+ issueNumber = context.payload.issue.number;
26
+ triggerText = `${context.payload.issue.title} ${context.payload.issue.body}`;
27
+
28
+ console.log(`Issue #${issueNumber} created`);
29
+
30
+ } else if (context.eventName === 'issue_comment') {
31
+ // Issue/PR comment
32
+ issueNumber = context.payload.issue.number;
33
+ triggerText = context.payload.comment.body;
34
+
35
+ if (context.payload.issue.pull_request) {
36
+ // Comment on a PR
37
+ isPR = true;
38
+ try {
39
+ const pr = await github.rest.pulls.get({
40
+ owner: context.repo.owner,
41
+ repo: context.repo.repo,
42
+ pull_number: issueNumber
43
+ });
44
+ prNumber = issueNumber;
45
+ headRef = pr.data.head.ref;
46
+ baseRef = pr.data.base.ref;
47
+ headSha = pr.data.head.sha;
48
+
49
+ console.log(`PR Comment #${prNumber}: ${baseRef} <- ${headRef}`);
50
+ } catch (error) {
51
+ console.error('Error fetching PR info:', error);
52
+ // In case of error, treat as a regular Issue
53
+ isPR = false;
54
+ }
55
+ } else {
56
+ // Regular Issue comment
57
+ isPR = false;
58
+ console.log(`Issue Comment #${issueNumber}`);
59
+ }
60
+
61
+ } else if (context.eventName === 'pull_request_review_comment' || context.eventName === 'pull_request_review') {
62
+ // PR review related
63
+ isPR = true;
64
+ issueNumber = context.payload.pull_request.number;
65
+ prNumber = context.payload.pull_request.number;
66
+ headRef = context.payload.pull_request.head.ref;
67
+ baseRef = context.payload.pull_request.base.ref;
68
+ headSha = context.payload.pull_request.head.sha;
69
+
70
+ if (context.eventName === 'pull_request_review_comment') {
71
+ triggerText = context.payload.comment.body;
72
+ } else {
73
+ triggerText = context.payload.review.body;
74
+ }
75
+
76
+ console.log(`PR Review #${prNumber}: ${baseRef} <- ${headRef}`);
77
+ }
78
+
79
+ // Set outputs
80
+ core.setOutput('issue-number', issueNumber);
81
+ core.setOutput('pr-number', prNumber || '');
82
+ core.setOutput('head-ref', headRef || '');
83
+ core.setOutput('base-ref', baseRef || '');
84
+ core.setOutput('head-sha', headSha || '');
85
+ core.setOutput('is-pr', isPR);
86
+ core.setOutput('trigger-text', triggerText);
87
+
88
+ console.log(`Final Context: Issue #${issueNumber}, isPR: ${isPR}, Event: ${context.eventName}`);
89
+
90
+ }
@@ -0,0 +1,2 @@
1
+ - name: New thing
2
+ run: npm test four
@@ -0,0 +1,85 @@
1
+ const { blockTransformer, indentString } = require('../../src')
2
+ const fs = require('fs')
3
+ const path = require('path')
4
+ const util = require('util')
5
+
6
+ function logValue(value, isFirst, isLast) {
7
+ const prefix = `${isFirst ? '> ' : ''}`
8
+ if (typeof value === 'object') {
9
+ console.log(`${util.inspect(value, false, null, true)}\n`)
10
+ return
11
+ }
12
+ if (isFirst) {
13
+ console.log(`\n\x1b[33m${prefix}${value}\x1b[0m`)
14
+ return
15
+ }
16
+ console.log((typeof value === 'string' && value.includes('\n')) ? `\`${value}\`` : value)
17
+ // isLast && console.log(`\x1b[37m\x1b[1m${'─'.repeat(94)}\x1b[0m\n`)
18
+ }
19
+
20
+ function deepLog() {
21
+ for (let i = 0; i < arguments.length; i++) logValue(arguments[i], i === 0, i === arguments.length - 1)
22
+ }
23
+
24
+ const yaml = `
25
+ name: Test Workflow
26
+ description: A simple test workflow for testing purposes
27
+ version: 1.0.0
28
+
29
+ on:
30
+ push:
31
+ branches: [main, develop]
32
+ pull_request:
33
+ branches: [main]
34
+
35
+ jobs:
36
+ test:
37
+ runs-on: ubuntu-latest
38
+ steps:
39
+ - name: Checkout code
40
+ uses: actions/checkout@v4
41
+
42
+ - name: Run tests
43
+ run: npm test
44
+
45
+ ## include file src="_test.yml" ##
46
+ - name: Run tests two
47
+ run: npm test two
48
+ ## /include ##
49
+
50
+ ## include js src="_run.js" ##
51
+ - name: Run tests two
52
+ run: npm test two
53
+ ## /include ##
54
+
55
+ build:
56
+ runs-on: ubuntu-latest
57
+ needs: test
58
+ steps:
59
+ - name: Build project
60
+ run: npm run build
61
+ `
62
+
63
+ blockTransformer(yaml, {
64
+ syntax: 'yaml',
65
+ open: 'include',
66
+ close: '/include',
67
+ transforms: {
68
+ file: ({ content, options }) => {
69
+ const { src } = options
70
+ const blockContent = fs.readFileSync(path.join(__dirname, src), 'utf8')
71
+ return blockContent
72
+ },
73
+ js: (api) => {
74
+ console.log('api', api)
75
+ const { content, options } = api
76
+ console.log('XYZ', content)
77
+ const jsContent = fs.readFileSync(path.join(__dirname, options.src), 'utf8')
78
+ return `
79
+ - name: Run tests two
80
+ run: |
81
+ ${indentString(jsContent, 4)}
82
+ `
83
+ }
84
+ }
85
+ }).then(deepLog)