@link-assistant/web-capture 1.1.2 → 1.7.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 (60) hide show
  1. package/CHANGELOG.md +57 -13
  2. package/Dockerfile +26 -21
  3. package/README.md +290 -160
  4. package/bin/web-capture.js +622 -17
  5. package/package.json +15 -4
  6. package/src/animation.js +283 -0
  7. package/src/archive.js +225 -0
  8. package/src/batch.js +180 -0
  9. package/src/browser.js +150 -111
  10. package/src/docx.js +182 -0
  11. package/src/extract-images.js +120 -0
  12. package/src/figures.js +208 -0
  13. package/src/gdocs.js +335 -0
  14. package/src/image.js +65 -8
  15. package/src/index.js +15 -0
  16. package/src/latex.js +127 -0
  17. package/src/lib.js +281 -1
  18. package/src/localize-images.js +202 -0
  19. package/src/markdown.js +7 -2
  20. package/src/metadata.js +333 -0
  21. package/src/pdf.js +76 -0
  22. package/src/popups.js +171 -0
  23. package/src/postprocess.js +263 -0
  24. package/src/retry.js +48 -0
  25. package/src/themed-image.js +167 -0
  26. package/src/verify.js +312 -0
  27. package/tests/e2e/docker.test.js +51 -12
  28. package/tests/e2e/process.test.js +34 -10
  29. package/tests/fixtures/habr-articles.js +45 -0
  30. package/tests/integration/api-endpoints.test.js +231 -0
  31. package/tests/integration/habr-article.test.js +337 -0
  32. package/tests/mock/index.test.js +5 -3
  33. package/tests/unit/animation.test.js +33 -0
  34. package/tests/unit/batch.test.js +114 -0
  35. package/tests/unit/browser.test.js +38 -2
  36. package/tests/unit/extract-images.test.js +233 -0
  37. package/tests/unit/figures.test.js +74 -0
  38. package/tests/unit/gdocs.test.js +278 -0
  39. package/tests/unit/heading-image.test.js +49 -0
  40. package/tests/unit/latex.test.js +123 -0
  41. package/tests/unit/localize-images.test.js +78 -0
  42. package/tests/unit/metadata.test.js +140 -0
  43. package/tests/unit/postprocess.test.js +110 -0
  44. package/tests/unit/retry.test.js +111 -0
  45. package/tests/unit/verify.test.js +182 -0
  46. package/.github/workflows/release.yml +0 -294
  47. package/ARCHITECTURE.md +0 -982
  48. package/LICENSE +0 -24
  49. package/apply.sh +0 -166
  50. package/docs/market-analysis-2025-05-13.md +0 -64
  51. package/scripts/changeset-version.mjs +0 -38
  52. package/scripts/create-github-release.mjs +0 -93
  53. package/scripts/create-manual-changeset.mjs +0 -88
  54. package/scripts/format-github-release.mjs +0 -83
  55. package/scripts/format-release-notes.mjs +0 -218
  56. package/scripts/instant-version-bump.mjs +0 -121
  57. package/scripts/publish-to-npm.mjs +0 -128
  58. package/scripts/setup-npm.mjs +0 -37
  59. package/scripts/validate-changeset.mjs +0 -106
  60. package/scripts/version-and-commit.mjs +0 -237
@@ -1,218 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Script to format GitHub release notes with proper formatting:
5
- * - Fix special characters like \n
6
- * - Add link to PR that contains the release commit (if found)
7
- * - Add shields.io NPM version badge
8
- * - Format nicely with proper markdown
9
- *
10
- * IMPORTANT: Update the PACKAGE_NAME constant below to match your package.json
11
- *
12
- * PR Detection Logic:
13
- * 1. Extract commit hash from changelog entry (if present)
14
- * 2. Fall back to --commit-sha argument (passed from workflow)
15
- * 3. Look up PRs that contain the commit via GitHub API
16
- * 4. If no PR found, simply don't display any PR link (no guessing)
17
- *
18
- * Uses link-foundation libraries:
19
- * - use-m: Dynamic package loading without package.json dependencies
20
- * - command-stream: Modern shell command execution with streaming support
21
- * - lino-arguments: Unified configuration from CLI args, env vars, and .lenv files
22
- *
23
- * Note: Uses --release-version instead of --version to avoid conflict with yargs' built-in --version flag.
24
- */
25
-
26
- const PACKAGE_NAME = '@link-assistant/web-capture';
27
-
28
- // Load use-m dynamically
29
- const { use } = eval(
30
- await (await fetch('https://unpkg.com/use-m/use.js')).text()
31
- );
32
-
33
- // Import link-foundation libraries
34
- const { $ } = await use('command-stream');
35
- const { makeConfig } = await use('lino-arguments');
36
-
37
- // Parse CLI arguments using lino-arguments
38
- // Note: Using --release-version instead of --version to avoid conflict with yargs' built-in --version flag
39
- const config = makeConfig({
40
- yargs: ({ yargs, getenv }) =>
41
- yargs
42
- .option('release-version', {
43
- type: 'string',
44
- default: getenv('VERSION', ''),
45
- describe: 'Version number (e.g., v0.8.36)',
46
- })
47
- .option('release-id', {
48
- type: 'string',
49
- default: getenv('RELEASE_ID', ''),
50
- describe: 'GitHub release ID',
51
- })
52
- .option('repository', {
53
- type: 'string',
54
- default: getenv('REPOSITORY', ''),
55
- describe: 'GitHub repository (e.g., owner/repo)',
56
- })
57
- .option('commit-sha', {
58
- type: 'string',
59
- default: getenv('COMMIT_SHA', ''),
60
- describe: 'Commit SHA for PR detection',
61
- }),
62
- });
63
-
64
- const releaseId = config.releaseId;
65
- const version = config.releaseVersion;
66
- const repository = config.repository;
67
- const passedCommitSha = config.commitSha;
68
-
69
- if (!releaseId || !version || !repository) {
70
- console.error(
71
- 'Usage: format-release-notes.mjs --release-id <releaseId> --release-version <version> --repository <repository> [--commit-sha <sha>]'
72
- );
73
- process.exit(1);
74
- }
75
-
76
- try {
77
- // Get current release body
78
- const result = await $`gh api repos/${repository}/releases/${releaseId}`.run({
79
- capture: true,
80
- });
81
- const releaseData = JSON.parse(result.stdout);
82
-
83
- const currentBody = releaseData.body || '';
84
-
85
- // Skip if already formatted (has shields.io badge image)
86
- if (currentBody.includes('img.shields.io')) {
87
- console.log('ℹ️ Release notes already formatted');
88
- process.exit(0);
89
- }
90
-
91
- // Extract changes section (Major, Minor, or Patch)
92
- // This regex handles multiple formats:
93
- // 1. With commit hash: "### [Major|Minor|Patch] Changes\n- abc1234: Description"
94
- // 2. Without commit hash: "### [Major|Minor|Patch] Changes\n- Description"
95
- const changesPattern =
96
- /### (Major|Minor|Patch) Changes\s*\n\s*-\s+(?:([a-f0-9]+):\s+)?(.+?)$/s;
97
- const changesMatch = currentBody.match(changesPattern);
98
-
99
- let commitHash = null;
100
- let rawDescription = null;
101
- let changeType = null;
102
-
103
- if (changesMatch) {
104
- // Extract: [full match, changeType, commitHash (optional), description]
105
- [, changeType, commitHash, rawDescription] = changesMatch;
106
- console.log(`ℹ️ Found ${changeType} Changes section`);
107
-
108
- // If commitHash is undefined and description contains it, try to extract
109
- if (!commitHash && rawDescription) {
110
- // This handles the case where description itself might be null/undefined
111
- // and we need to safely check for commit hash at the start
112
- const descWithHashMatch = rawDescription.match(/^([a-f0-9]+):\s+(.+)$/s);
113
- if (descWithHashMatch) {
114
- [, commitHash, rawDescription] = descWithHashMatch;
115
- }
116
- }
117
- } else {
118
- console.log('⚠️ Could not parse changes from release notes');
119
- console.log(' Looking for pattern: ### [Major|Minor|Patch] Changes');
120
- process.exit(0);
121
- }
122
-
123
- // Clean up the description:
124
- // 1. Convert literal \n sequences (escaped newlines from GitHub API) to actual newlines
125
- // 2. Remove leading/trailing quotes (including escaped quotes from command-stream shell escaping)
126
- // 3. Remove any trailing npm package links or markdown that might be there
127
- // 4. Normalize whitespace while preserving line breaks
128
- const cleanDescription = rawDescription
129
- .replace(/\\n/g, '\n') // Convert escaped \n to actual newlines
130
- .replace(/^(\\['"])+/g, '') // Remove leading escaped quotes (e.g., \', \", \'', \'')
131
- .replace(/(['"])+$/g, '') // Remove trailing unescaped quotes (e.g., ', ", '', '')
132
- .replace(/^(['"])+/g, '') // Remove leading unescaped quotes
133
- .replace(/📦.*$/s, '') // Remove any existing npm package info
134
- .replace(/---.*$/s, '') // Remove any existing separators and everything after
135
- .trim()
136
- .split('\n') // Split by lines
137
- .map((line) => line.trim()) // Trim whitespace from each line
138
- .join('\n') // Rejoin with newlines
139
- .replace(/\n{3,}/g, '\n\n'); // Normalize excessive blank lines (3+ becomes 2)
140
-
141
- // Find the PR that contains the release commit
142
- // Uses commit hash from changelog or passed commit SHA from workflow
143
- let prNumber = null;
144
-
145
- // Determine which commit SHA to use for PR lookup
146
- const commitShaToLookup = commitHash || passedCommitSha;
147
-
148
- if (commitShaToLookup) {
149
- const source = commitHash ? 'changelog' : 'workflow';
150
- console.log(
151
- `ℹ️ Looking up PR for commit ${commitShaToLookup} (from ${source})`
152
- );
153
-
154
- try {
155
- const prResult =
156
- await $`gh api "repos/${repository}/commits/${commitShaToLookup}/pulls"`.run(
157
- { capture: true }
158
- );
159
- const prsData = JSON.parse(prResult.stdout);
160
-
161
- // Find the PR that's not the version bump PR (not "chore: version packages")
162
- const relevantPr = prsData.find(
163
- (pr) => !pr.title.includes('version packages')
164
- );
165
-
166
- if (relevantPr) {
167
- prNumber = relevantPr.number;
168
- console.log(`✅ Found PR #${prNumber} containing commit`);
169
- } else if (prsData.length > 0) {
170
- console.log(
171
- '⚠️ Found PRs but all are version bump PRs, not linking any'
172
- );
173
- } else {
174
- console.log(
175
- 'ℹ️ No PR found containing this commit - not adding PR link'
176
- );
177
- }
178
- } catch (error) {
179
- console.log('⚠️ Could not find PR for commit', commitShaToLookup);
180
- console.log(' Error:', error.message);
181
- if (process.env.DEBUG) {
182
- console.error(error);
183
- }
184
- }
185
- } else {
186
- // No commit hash available from any source
187
- console.log('ℹ️ No commit SHA available - not adding PR link');
188
- }
189
-
190
- // Build formatted release notes
191
- const versionWithoutV = version.replace(/^v/, '');
192
- const npmBadge = `[![npm version](https://img.shields.io/badge/npm-${versionWithoutV}-blue.svg)](https://www.npmjs.com/package/${PACKAGE_NAME}/v/${versionWithoutV})`;
193
-
194
- let formattedBody = `${cleanDescription}`;
195
-
196
- // Add PR link if available
197
- if (prNumber) {
198
- formattedBody += `\n\n**Related Pull Request:** #${prNumber}`;
199
- }
200
-
201
- formattedBody += `\n\n---\n\n${npmBadge}`;
202
-
203
- // Update the release using JSON input to properly handle special characters
204
- const updatePayload = JSON.stringify({ body: formattedBody });
205
- await $`gh api repos/${repository}/releases/${releaseId} -X PATCH --input -`.run(
206
- { stdin: updatePayload }
207
- );
208
-
209
- console.log(`✅ Formatted release notes for v${versionWithoutV}`);
210
- if (prNumber) {
211
- console.log(` - Added link to PR #${prNumber}`);
212
- }
213
- console.log(' - Added shields.io npm badge');
214
- console.log(' - Cleaned up formatting');
215
- } catch (error) {
216
- console.error('❌ Error formatting release notes:', error.message);
217
- process.exit(1);
218
- }
@@ -1,121 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Instant version bump script for manual releases
5
- * Bypasses the changeset workflow and directly updates version and changelog
6
- *
7
- * Usage: node scripts/instant-version-bump.mjs --bump-type <major|minor|patch> [--description <description>]
8
- *
9
- * Uses link-foundation libraries:
10
- * - use-m: Dynamic package loading without package.json dependencies
11
- * - command-stream: Modern shell command execution with streaming support
12
- * - lino-arguments: Unified configuration from CLI args, env vars, and .lenv files
13
- */
14
-
15
- import { readFileSync, writeFileSync } from 'fs';
16
-
17
- // Load use-m dynamically
18
- const { use } = eval(
19
- await (await fetch('https://unpkg.com/use-m/use.js')).text()
20
- );
21
-
22
- // Import link-foundation libraries
23
- const { $ } = await use('command-stream');
24
- const { makeConfig } = await use('lino-arguments');
25
-
26
- // Parse CLI arguments using lino-arguments
27
- const config = makeConfig({
28
- yargs: ({ yargs, getenv }) =>
29
- yargs
30
- .option('bump-type', {
31
- type: 'string',
32
- default: getenv('BUMP_TYPE', ''),
33
- describe: 'Version bump type: major, minor, or patch',
34
- choices: ['major', 'minor', 'patch'],
35
- })
36
- .option('description', {
37
- type: 'string',
38
- default: getenv('DESCRIPTION', ''),
39
- describe: 'Description for the version bump',
40
- }),
41
- });
42
-
43
- try {
44
- const { bumpType, description } = config;
45
- const finalDescription = description || `Manual ${bumpType} release`;
46
-
47
- if (!bumpType || !['major', 'minor', 'patch'].includes(bumpType)) {
48
- console.error(
49
- 'Usage: node scripts/instant-version-bump.mjs --bump-type <major|minor|patch> [--description <description>]'
50
- );
51
- process.exit(1);
52
- }
53
-
54
- console.log(`\nBumping version (${bumpType})...`);
55
-
56
- // Get current version
57
- const packageJson = JSON.parse(readFileSync('package.json', 'utf-8'));
58
- const oldVersion = packageJson.version;
59
- console.log(`Current version: ${oldVersion}`);
60
-
61
- // Bump version using npm version (doesn't create git tag)
62
- await $`npm version ${bumpType} --no-git-tag-version`;
63
-
64
- // Get new version
65
- const updatedPackageJson = JSON.parse(readFileSync('package.json', 'utf-8'));
66
- const newVersion = updatedPackageJson.version;
67
- console.log(`New version: ${newVersion}`);
68
-
69
- // Update CHANGELOG.md
70
- console.log('\nUpdating CHANGELOG.md...');
71
- const changelogPath = 'CHANGELOG.md';
72
- let changelog = readFileSync(changelogPath, 'utf-8');
73
-
74
- // Create new changelog entry
75
- const newEntry = `## ${newVersion}
76
-
77
- ### ${bumpType.charAt(0).toUpperCase() + bumpType.slice(1)} Changes
78
-
79
- - ${finalDescription}
80
-
81
- `;
82
-
83
- // Insert new entry after the first heading (# Changelog or similar)
84
- // Look for the first ## heading and insert before it
85
- const firstVersionMatch = changelog.match(/^## /m);
86
-
87
- if (firstVersionMatch) {
88
- const insertPosition = firstVersionMatch.index;
89
- changelog =
90
- changelog.slice(0, insertPosition) +
91
- newEntry +
92
- changelog.slice(insertPosition);
93
- } else {
94
- // If no version headings exist, append after the main heading
95
- const mainHeadingMatch = changelog.match(/^# .+$/m);
96
- if (mainHeadingMatch) {
97
- const insertPosition =
98
- mainHeadingMatch.index + mainHeadingMatch[0].length;
99
- changelog = `${changelog.slice(0, insertPosition)}\n\n${newEntry}${changelog.slice(insertPosition)}`;
100
- } else {
101
- // If no headings at all, prepend
102
- changelog = `${newEntry}\n${changelog}`;
103
- }
104
- }
105
-
106
- writeFileSync(changelogPath, changelog, 'utf-8');
107
- console.log('✅ CHANGELOG.md updated');
108
-
109
- // Synchronize package-lock.json
110
- console.log('\nSynchronizing package-lock.json...');
111
- await $`npm install --package-lock-only`;
112
-
113
- console.log('\n✅ Instant version bump complete');
114
- console.log(`Version: ${oldVersion} → ${newVersion}`);
115
- } catch (error) {
116
- console.error('Error during instant version bump:', error.message);
117
- if (process.env.DEBUG) {
118
- console.error('Stack trace:', error.stack);
119
- }
120
- process.exit(1);
121
- }
@@ -1,128 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Publish to npm using OIDC trusted publishing
5
- * Usage: node scripts/publish-to-npm.mjs [--should-pull]
6
- * should_pull: Optional flag to pull latest changes before publishing (for release job)
7
- *
8
- * IMPORTANT: Update the PACKAGE_NAME constant below to match your package.json
9
- *
10
- * Uses link-foundation libraries:
11
- * - use-m: Dynamic package loading without package.json dependencies
12
- * - command-stream: Modern shell command execution with streaming support
13
- * - lino-arguments: Unified configuration from CLI args, env vars, and .lenv files
14
- */
15
-
16
- import { readFileSync, appendFileSync } from 'fs';
17
-
18
- const PACKAGE_NAME = '@link-assistant/web-capture';
19
-
20
- // Load use-m dynamically
21
- const { use } = eval(
22
- await (await fetch('https://unpkg.com/use-m/use.js')).text()
23
- );
24
-
25
- // Import link-foundation libraries
26
- const { $ } = await use('command-stream');
27
- const { makeConfig } = await use('lino-arguments');
28
-
29
- // Parse CLI arguments using lino-arguments
30
- const config = makeConfig({
31
- yargs: ({ yargs, getenv }) =>
32
- yargs.option('should-pull', {
33
- type: 'boolean',
34
- default: getenv('SHOULD_PULL', false),
35
- describe: 'Pull latest changes before publishing',
36
- }),
37
- });
38
-
39
- const { shouldPull } = config;
40
- const MAX_RETRIES = 3;
41
- const RETRY_DELAY = 10000; // 10 seconds
42
-
43
- /**
44
- * Sleep for specified milliseconds
45
- * @param {number} ms
46
- */
47
- function sleep(ms) {
48
- return new Promise((resolve) => globalThis.setTimeout(resolve, ms));
49
- }
50
-
51
- /**
52
- * Append to GitHub Actions output file
53
- * @param {string} key
54
- * @param {string} value
55
- */
56
- function setOutput(key, value) {
57
- const outputFile = process.env.GITHUB_OUTPUT;
58
- if (outputFile) {
59
- appendFileSync(outputFile, `${key}=${value}\n`);
60
- }
61
- }
62
-
63
- async function main() {
64
- try {
65
- if (shouldPull) {
66
- // Pull the latest changes we just pushed
67
- await $`git pull origin main`;
68
- }
69
-
70
- // Get current version
71
- const packageJson = JSON.parse(readFileSync('./package.json', 'utf8'));
72
- const currentVersion = packageJson.version;
73
- console.log(`Current version to publish: ${currentVersion}`);
74
-
75
- // Check if this version is already published on npm
76
- console.log(
77
- `Checking if version ${currentVersion} is already published...`
78
- );
79
- const checkResult =
80
- await $`npm view "${PACKAGE_NAME}@${currentVersion}" version`.run({
81
- capture: true,
82
- });
83
-
84
- // command-stream returns { code: 0 } on success, { code: 1 } on failure (e.g., E404)
85
- // Exit code 0 means version exists, non-zero means version not found
86
- if (checkResult.code === 0) {
87
- console.log(`Version ${currentVersion} is already published to npm`);
88
- setOutput('published', 'true');
89
- setOutput('published_version', currentVersion);
90
- setOutput('already_published', 'true');
91
- return;
92
- } else {
93
- // Version not found on npm (E404), proceed with publish
94
- console.log(
95
- `Version ${currentVersion} not found on npm, proceeding with publish...`
96
- );
97
- }
98
-
99
- // Publish to npm using OIDC trusted publishing with retry logic
100
- for (let i = 1; i <= MAX_RETRIES; i++) {
101
- console.log(`Publish attempt ${i} of ${MAX_RETRIES}...`);
102
- try {
103
- await $`npm run changeset:publish`;
104
- setOutput('published', 'true');
105
- setOutput('published_version', currentVersion);
106
- console.log(
107
- `\u2705 Published ${PACKAGE_NAME}@${currentVersion} to npm`
108
- );
109
- return;
110
- } catch (error) {
111
- if (i < MAX_RETRIES) {
112
- console.log(
113
- `Publish failed: ${error.message}, waiting ${RETRY_DELAY / 1000}s before retry...`
114
- );
115
- await sleep(RETRY_DELAY);
116
- }
117
- }
118
- }
119
-
120
- console.error(`\u274C Failed to publish after ${MAX_RETRIES} attempts`);
121
- process.exit(1);
122
- } catch (error) {
123
- console.error('Error:', error.message);
124
- process.exit(1);
125
- }
126
- }
127
-
128
- main();
@@ -1,37 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Update npm for OIDC trusted publishing
5
- * npm trusted publishing requires npm >= 11.5.1
6
- * Node.js 20.x ships with npm 10.x, so we need to update
7
- *
8
- * Uses link-foundation libraries:
9
- * - use-m: Dynamic package loading without package.json dependencies
10
- * - command-stream: Modern shell command execution with streaming support
11
- */
12
-
13
- // Load use-m dynamically
14
- const { use } = eval(
15
- await (await fetch('https://unpkg.com/use-m/use.js')).text()
16
- );
17
-
18
- // Import command-stream for shell command execution
19
- const { $ } = await use('command-stream');
20
-
21
- try {
22
- // Get current npm version
23
- const currentResult = await $`npm --version`.run({ capture: true });
24
- const currentVersion = currentResult.stdout.trim();
25
- console.log(`Current npm version: ${currentVersion}`);
26
-
27
- // Update npm to latest
28
- await $`npm install -g npm@latest`;
29
-
30
- // Get updated npm version
31
- const updatedResult = await $`npm --version`.run({ capture: true });
32
- const updatedVersion = updatedResult.stdout.trim();
33
- console.log(`Updated npm version: ${updatedVersion}`);
34
- } catch (error) {
35
- console.error('Error updating npm:', error.message);
36
- process.exit(1);
37
- }
@@ -1,106 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Validate changeset for CI - ensures exactly one valid changeset exists
5
- *
6
- * IMPORTANT: Update the package name below to match your package.json
7
- */
8
-
9
- import { readdirSync, readFileSync } from 'fs';
10
- import { join } from 'path';
11
-
12
- const PACKAGE_NAME = '@link-assistant/web-capture';
13
-
14
- try {
15
- // Count changeset files (excluding README.md and config.json)
16
- const changesetDir = '.changeset';
17
- const changesetFiles = readdirSync(changesetDir).filter(
18
- (file) => file.endsWith('.md') && file !== 'README.md'
19
- );
20
-
21
- const changesetCount = changesetFiles.length;
22
- console.log(`Found ${changesetCount} changeset file(s)`);
23
-
24
- // Ensure exactly one changeset file exists
25
- if (changesetCount === 0) {
26
- console.error(
27
- "::error::No changeset found. Please add a changeset by running 'npm run changeset' and commit the result."
28
- );
29
- process.exit(1);
30
- } else if (changesetCount > 1) {
31
- console.error(
32
- `::error::Multiple changesets found (${changesetCount}). Each PR should have exactly ONE changeset.`
33
- );
34
- console.error('::error::Found changeset files:');
35
- changesetFiles.forEach((file) => console.error(` ${file}`));
36
- process.exit(1);
37
- }
38
-
39
- // Get the changeset file
40
- const changesetFile = join(changesetDir, changesetFiles[0]);
41
- console.log(`Validating changeset: ${changesetFile}`);
42
-
43
- // Read the changeset file
44
- const content = readFileSync(changesetFile, 'utf-8');
45
-
46
- // Check if changeset has a valid type (major, minor, or patch)
47
- const versionTypeRegex = new RegExp(
48
- `^['"]${PACKAGE_NAME}['"]:\\s+(major|minor|patch)`,
49
- 'm'
50
- );
51
- if (!versionTypeRegex.test(content)) {
52
- console.error(
53
- '::error::Changeset must specify a version type: major, minor, or patch'
54
- );
55
- console.error(`::error::Expected format in ${changesetFile}:`);
56
- console.error('::error::---');
57
- console.error(`::error::'${PACKAGE_NAME}': patch`);
58
- console.error('::error::---');
59
- console.error('::error::');
60
- console.error('::error::Your description here');
61
- console.error('\nFile content:');
62
- console.error(content);
63
- process.exit(1);
64
- }
65
-
66
- // Extract description (everything after the closing ---) and check it's not empty
67
- const parts = content.split('---');
68
- if (parts.length < 3) {
69
- console.error(
70
- '::error::Changeset must include a description of the changes'
71
- );
72
- console.error(
73
- "::error::The description should appear after the closing '---' in the changeset file"
74
- );
75
- console.error(`::error::Current content of ${changesetFile}:`);
76
- console.error(content);
77
- process.exit(1);
78
- }
79
-
80
- const description = parts.slice(2).join('---').trim();
81
- if (!description) {
82
- console.error(
83
- '::error::Changeset must include a description of the changes'
84
- );
85
- console.error(
86
- "::error::The description should appear after the closing '---' in the changeset file"
87
- );
88
- console.error(`::error::Current content of ${changesetFile}:`);
89
- console.error(content);
90
- process.exit(1);
91
- }
92
-
93
- // Extract version type
94
- const versionTypeMatch = content.match(versionTypeRegex);
95
- const versionType = versionTypeMatch ? versionTypeMatch[1] : 'unknown';
96
-
97
- console.log('✅ Changeset validation passed');
98
- console.log(` Type: ${versionType}`);
99
- console.log(` Description: ${description}`);
100
- } catch (error) {
101
- console.error('Error during changeset validation:', error.message);
102
- if (process.env.DEBUG) {
103
- console.error('Stack trace:', error.stack);
104
- }
105
- process.exit(1);
106
- }