PluginProbe
MONEI Payments for WooCommerce / 7.3.0
MONEI Payments for WooCommerce v7.3.0
7.3.3 7.3.2 7.3.1 7.3.0 7.2.4 7.2.3 7.2.2 7.2.0 7.2.1 7.1.3 2.1.0 3.0.0 3.1.0 3.1.1 4.0.0 4.1.0 4.1.1 4.2.0 4.2.1 5.0 5.1.0 5.1.1 5.1.2 5.2.2 5.2.3 All 87 releases
monei / scripts / generate-readme.js

generate-readme.js in MONEI Payments for WooCommerce 7.3.0, at scripts/generate-readme.js

297 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 #!/usr/bin/env node
2
3 /**
4 * Custom WordPress readme.txt generator
5 *
6 * Takes CHANGELOG.md and generates readme.txt and README.md
7 * Shows the LATEST N versions (not the oldest N like the buggy npm package)
8 */
9
10 /* eslint-disable no-console */
11
12 const fs = require( 'fs' );
13 const path = require( 'path' );
14
15 // Configuration
16 const CONFIG = {
17 changelogFile: 'CHANGELOG.md',
18 templateFile: '.readme-template',
19 outputTxt: 'readme.txt',
20 outputMd: 'README.md',
21 packageFile: 'package.json',
22 mainFile: 'woocommerce-gateway-monei.php',
23 changelogLimit: parseInt( process.argv[ 2 ] ) || 10, // Default to 10 versions
24 };
25
26 /**
27 * Parse CHANGELOG.md and extract version entries
28 * @param changelogContent
29 */
30 function parseChangelog( changelogContent ) {
31 const versions = [];
32 const lines = changelogContent.split( '\n' );
33
34 let currentVersion = null;
35 let currentBody = [];
36
37 for ( const line of lines ) {
38 // Match version headers like "## 6.3.12 (2025-10-01)" or "## <small>6.3.12 (2025-10-01)</small>"
39 const versionMatch = line.match(
40 /^##\s+(?:<small>)?(\d+\.\d+\.\d+)\s+\(([^)]+)\)(?:<\/small>)?/
41 );
42
43 if ( versionMatch ) {
44 // Save previous version if exists
45 if ( currentVersion ) {
46 versions.push( {
47 version: currentVersion.version,
48 date: currentVersion.date,
49 body: currentBody.join( '\n' ).trim(),
50 } );
51 }
52
53 // Start new version
54 currentVersion = {
55 version: versionMatch[ 1 ],
56 date: versionMatch[ 2 ],
57 };
58 currentBody = [];
59 } else if ( currentVersion && line.trim() ) {
60 // Add to current version body
61 currentBody.push( line );
62 }
63 }
64
65 // Save last version
66 if ( currentVersion ) {
67 versions.push( {
68 version: currentVersion.version,
69 date: currentVersion.date,
70 body: currentBody.join( '\n' ).trim(),
71 } );
72 }
73
74 return versions;
75 }
76
77 /**
78 * Format versions for WordPress readme.txt format
79 * @param versions
80 * @param limit
81 */
82 function formatForReadme( versions, limit ) {
83 // CHANGELOG.md has newest first, oldest last - take first N versions
84 const limited = versions.slice( 0, limit );
85
86 const formatted = limited.map( ( version, index ) => {
87 const header = `= v${ version.version } - ${ version.date } =`;
88 const body = version.body
89 .split( '\n' )
90 .filter( ( line ) => line.trim() && ! line.match( /^##/ ) ) // Remove headers
91 .filter( ( line ) => ! line.match( /chore:\s+release/ ) ) // Remove "chore: release" commits
92 .join( '\n' );
93
94 return index === 0
95 ? `${ header }\n${ body }`
96 : `\n\n${ header }\n${ body }`;
97 } );
98
99 return formatted.join( '' );
100 }
101
102 /**
103 * Read package.json version
104 */
105 function getPackageVersion() {
106 const packagePath = path.join( process.cwd(), CONFIG.packageFile );
107 const packageData = JSON.parse( fs.readFileSync( packagePath, 'utf8' ) );
108 return packageData.version;
109 }
110
111 /**
112 * Read main plugin file metadata
113 */
114 function getPluginMetadata() {
115 const mainPath = path.join( process.cwd(), CONFIG.mainFile );
116 const content = fs.readFileSync( mainPath, 'utf8' );
117
118 const metadata = {};
119
120 // Extract metadata from plugin header comments
121 const patterns = {
122 name: /Plugin Name:\s*(.+)/,
123 uri: /Plugin URI:\s*(.+)/,
124 description: /Description:\s*(.+)/,
125 version: /Version:\s*(\d+\.\d+\.\d+)/,
126 author: /Author:\s*(.+)/,
127 authorUri: /Author URI:\s*(.+)/,
128 license: /License:\s*(.+)/,
129 licenseUri: /License URI:\s*(.+)/,
130 textDomain: /Text Domain:\s*(.+)/,
131 requiresAtLeast: /Requires at least:\s*(.+)/,
132 testedUpTo: /Tested up to:\s*(.+)/,
133 requiresPHP: /Requires PHP:\s*(.+)/,
134 wcRequiresAtLeast: /WC requires at least:\s*(.+)/,
135 wcTestedUpTo: /WC tested up to:\s*(.+)/,
136 };
137
138 for ( const [ key, pattern ] of Object.entries( patterns ) ) {
139 const match = content.match( pattern );
140 if ( match ) {
141 metadata[ key ] = match[ 1 ].trim();
142 }
143 }
144
145 return metadata;
146 }
147
148 /**
149 * Generate readme.txt (WordPress format)
150 * @param template
151 * @param changelog
152 * @param metadata
153 * @param version
154 */
155 function generateReadmeTxt( template, changelog, metadata, version ) {
156 let readme = template;
157
158 // Replace version
159 readme = readme.replace( /{{__PLUGIN_VERSION__}}/g, version );
160
161 // Replace changelog
162 readme = readme.replace( /{{__PLUGIN_CHANGELOG__}}/g, changelog );
163
164 // Replace metadata if exists
165 if ( metadata.requiresAtLeast ) {
166 readme = readme.replace(
167 /Requires at least: .+/g,
168 `Requires at least: ${ metadata.requiresAtLeast }`
169 );
170 }
171 if ( metadata.testedUpTo ) {
172 readme = readme.replace(
173 /Tested up to: .+/g,
174 `Tested up to: ${ metadata.testedUpTo }`
175 );
176 }
177 if ( metadata.requiresPHP ) {
178 readme = readme.replace(
179 /Requires PHP: .+/g,
180 `Requires PHP: ${ metadata.requiresPHP }`
181 );
182 }
183 if ( metadata.wcRequiresAtLeast ) {
184 readme = readme.replace(
185 /WC requires at least: .+/g,
186 `WC requires at least: ${ metadata.wcRequiresAtLeast }`
187 );
188 }
189 if ( metadata.wcTestedUpTo ) {
190 readme = readme.replace(
191 /WC tested up to: .+/g,
192 `WC tested up to: ${ metadata.wcTestedUpTo }`
193 );
194 }
195
196 return readme;
197 }
198
199 /**
200 * Generate README.md (GitHub format)
201 * @param readmeTxt
202 */
203 function generateReadmeMd( readmeTxt ) {
204 let readme = readmeTxt;
205
206 // Convert WordPress readme.txt format to Markdown
207 // Headers: === Title === -> # Title
208 readme = readme.replace( /^===\s*(.+?)\s*===/gm, '# $1' );
209
210 // Subheaders: == Section == -> ## Section
211 readme = readme.replace( /^==\s*(.+?)\s*==/gm, '## $1' );
212
213 // Changelog versions: = v6.3.12 - 2025-10-01 = -> ### v6.3.12 - 2025-10-01
214 readme = readme.replace(
215 /^=\s+(v\d+\.\d+\.\d+\s+-\s+\d{4}-\d{2}-\d{2})\s+=$/gm,
216 '### $1'
217 );
218
219 // Subsections: = Subsection = -> ### Subsection
220 readme = readme.replace( /^=\s+(.+?)\s+=$/gm, '### $1' );
221
222 return readme;
223 }
224
225 /**
226 * Main function
227 */
228 function main() {
229 try {
230 console.log( '🚀 Generating WordPress readme files...\n' );
231
232 // Read files
233 const changelogPath = path.join( process.cwd(), CONFIG.changelogFile );
234 const templatePath = path.join( process.cwd(), CONFIG.templateFile );
235
236 if ( ! fs.existsSync( changelogPath ) ) {
237 throw new Error( `CHANGELOG.md not found at ${ changelogPath }` );
238 }
239
240 if ( ! fs.existsSync( templatePath ) ) {
241 throw new Error(
242 `.readme-template not found at ${ templatePath }`
243 );
244 }
245
246 const changelogContent = fs.readFileSync( changelogPath, 'utf8' );
247 const template = fs.readFileSync( templatePath, 'utf8' );
248
249 // Get version and metadata
250 const version = getPackageVersion();
251 const metadata = getPluginMetadata();
252
253 console.log( `📦 Version: ${ version }` );
254 console.log(
255 `📝 Changelog limit: ${ CONFIG.changelogLimit } versions\n`
256 );
257
258 // Parse and format changelog
259 const versions = parseChangelog( changelogContent );
260 console.log( `�
261 Found ${ versions.length } versions in CHANGELOG.md` );
262
263 const formattedChangelog = formatForReadme(
264 versions,
265 CONFIG.changelogLimit
266 );
267
268 // Generate readme files
269 const readmeTxt = generateReadmeTxt(
270 template,
271 formattedChangelog,
272 metadata,
273 version
274 );
275 const readmeMd = generateReadmeMd( readmeTxt );
276
277 // Write files
278 const txtPath = path.join( process.cwd(), CONFIG.outputTxt );
279 const mdPath = path.join( process.cwd(), CONFIG.outputMd );
280
281 fs.writeFileSync( txtPath, readmeTxt );
282 fs.writeFileSync( mdPath, readmeMd );
283
284 console.log( `�
285 Generated ${ CONFIG.outputTxt }` );
286 console.log( `�
287 Generated ${ CONFIG.outputMd }` );
288 console.log( '\n✨ Done!' );
289 } catch ( error ) {
290 console.error( '\n❌ Error:', error.message );
291 process.exit( 1 );
292 }
293 }
294
295 // Run
296 main();
297