diff --git a/scripts/lint-script.js b/scripts/lint-script.js index d67980f17..cce751da9 100644 --- a/scripts/lint-script.js +++ b/scripts/lint-script.js @@ -3,51 +3,87 @@ Run using `npm run linter`. You might have to run `npm i -g semistandard` for this script to run properly. */ -// Load modules -const fs = require('fs-extra'), cp = require('child_process'), path = require('path'), chalk = require('chalk'); -// Set variables for paths -var snippetsPath = './snippets'; -// Read files, lint each one individually and update +const fs = require('fs-extra'); +const cp = require('child_process'); +const path = require('path'); +const chalk = require('chalk'); +const prettier = require('prettier'); + +const SNIPPETS_PATH = './snippets'; +const TEMP_PATH = './temp'; + +const codeRE = /```js([\s\S]*?)```/g; + +console.time('lint'); + try { - let snippetFilenames = fs.readdirSync(snippetsPath); - let jobCounter = 0; - snippetFilenames.sort((a, b) => { - a = a.toLowerCase(); - b = b.toLowerCase(); - if (a < b) return -1; - if (a > b) return 1; - return 0; - }); - // Read each file, get its code, write it to a temporary file, pass it through - // semistandard, get the output from the file, update the original file. - for(let snippet of snippetFilenames){ - // Start a timer for the file - console.time(`Linter (${snippet})`); - // Synchronously read data from the snippet, get the code, write it to a temporary file - let snippetData = fs.readFileSync(path.join(snippetsPath,snippet),'utf8'); - let codeStart = snippetData.indexOf('```js'), codeEnd = snippetData.search(/```[\n\r\s]+```js/g); - let originalCode = snippetData.slice(codeStart+5,codeEnd); - while(jobCounter >= 20){ - setTimeout(()=>{},1000); + const snippets = fs.readdirSync(SNIPPETS_PATH) + .sort((a, b) => a.toLowerCase() - b.toLowerCase()) + // turn it into an object so we can add data to it to be used in a different scope + .map(name => ({ name })); + + if (!fs.existsSync(TEMP_PATH)) { + fs.mkdirSync(TEMP_PATH); + } + + for (const snippet of snippets) { + snippet.data = fs.readFileSync(path.join(SNIPPETS_PATH, snippet.name), 'utf8'); + snippet.tempNames = []; + snippet.code = []; + + let match = codeRE.exec(snippet.data); + // make a counter so we write the definition + example code blocks to a different file + let counter = 0; + while (match) { + snippet.code.push(match[1]); // capture group + snippet.tempNames.push(snippet.name.replace('.md', counter)); + match = codeRE.exec(snippet.data); + counter++; } - const tempSnippet = snippet.replace('.md', ''); - fs.writeFileSync(`${tempSnippet}.temp.js`,`${originalCode}`); - // Run semistandard asynchronously (only way this manages to run), get linted code - // and write back to the original snippet file. Remove temporary file - cp.exec(`semistandard "${tempSnippet}.temp.js" --fix`,{},(error, stdOut, stdErr) => { - jobCounter += 1; - let lintedCode = fs.readFileSync(`${tempSnippet}.temp.js`,'utf8'); - fs.writeFile(path.join(snippetsPath,snippet), `${snippetData.slice(0, codeStart+5)+lintedCode+snippetData.slice(codeEnd)}`); - fs.unlink(`${tempSnippet}.temp.js`); - // Log a success message - console.log(`${chalk.green('SUCCESS!')} Linted snippet: ${snippet}`); - // Log the time taken for the file - console.timeEnd(`Linter (${snippet})`); - jobCounter -= 1; + + snippet.code.forEach((str, i) => { + fs.writeFileSync(`${TEMP_PATH}/${snippet.tempNames[i]}.js`, `${snippet.code[i]}`); }); } -} -catch (err){ // Handle errors (hopefully not!) + + cp.exec(`semistandard "${TEMP_PATH}" --fix`, {}, (err, stdout, stderr) => { + // Loop through each snippet now that semistandard has done its job, + // run prettier and write to the files + for (const snippet of snippets) { + // an array to store each linted code block (definition + example) + const lintedCode = []; + + for (const tempName of snippet.tempNames) { + let data = fs.readFileSync(`${TEMP_PATH}/${tempName}.js`,'utf8'); + + // prettier sometimes throws an error.. + try { + data = prettier.format(data, { + printWidth: 100, + singleQuote: true + }); + } catch (e) {} + + lintedCode.push(data); + + fs.unlink(`${TEMP_PATH}/${tempName}.js`); + } + + // We replace each ```js ``` code block with the newly linted code + let index = -1; + snippet.data = snippet.data.replace(codeRE, () => { + index++; + return '```js\n' + lintedCode[index] + '```'; + }); + + fs.writeFileSync(path.join(SNIPPETS_PATH, snippet.name), snippet.data); + } + + fs.removeSync(TEMP_PATH); + + console.timeEnd('lint'); + }); +} catch (err) { console.log(`${chalk.red('ERROR!')} During linting: ${err}`); process.exit(1); }