Skip to content

Commit

Permalink
Implementation of strict indentation
Browse files Browse the repository at this point in the history
  • Loading branch information
lovedder1995 committed Dec 18, 2023
1 parent 69bf34e commit ca3528e
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 11 deletions.
30 changes: 22 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
const { readFileSync, writeFileSync } = require('fs')

const indentation = ({ file, filename }) => {
const lines = file.split('\n')

require('php-bundler/rules/spaces.js')({ lines, filename })
require('php-bundler/rules/indentation.js')({ lines, filename })
require('./rules/comments.js')({ lines, filename })
require('./rules/end_of_file.js')({ lines, filename })
require('./rules/expressions.js')({ lines, filename })
require('./rules/functions.js')({ lines, filename })

return lines.join('\n')
}

const aModuleFilename = /(?<=module\(["'])(.*?)(?=["']\))/
const aModuleExpression = /module\(["'](.*?)['"]\);/
const aModuleExpression = /module\(["'](.*?)['"]\)/

const closure = code => `(function () {
${code}
})();
`
})()`

const resoveModule = ({ file, moduleFilename }) => {
if (!moduleFilename) moduleFilename = file.match(aModuleFilename)
if (!moduleFilename) return file
moduleFilename = moduleFilename[0]

let moduleFile = readFileSync(moduleFilename, 'utf-8')

let moduleFile = readFileSync(moduleFilename[0], 'utf-8')
.replace('<?php', '')
.trim()
moduleFile = indentation({ file: moduleFile, filename: moduleFilename })

moduleFile = closure(moduleFile)
const bundle = file.replace(aModuleExpression, moduleFile)
Expand All @@ -33,6 +46,7 @@ const resoveModule = ({ file, moduleFilename }) => {

const mainFile = readFileSync('main.php', 'utf-8')

const bundle = resoveModule({ file: mainFile })
let bundle = indentation({ file: mainFile, filename: 'main.php' })
bundle = resoveModule({ file: bundle })

writeFileSync('index.php', bundle)
writeFileSync('index.php', `<?php\n${bundle}`)
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "php-bundler",
"version": "1.0.0",
"version": "2.0.0",
"main": "index.js",
"repository": {
"type": "git",
Expand Down
17 changes: 17 additions & 0 deletions rules/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = ({ lines, filename }) => {
lines.every((line, index) => {
if (line.includes('#')) {
if (!line.trimStart().startsWith('#')) {
console.log(`${filename} ${index + 1}`, '- Comments should be on their own line')
return false
}

if (line.includes('# ') || (line.includes('#') && !line.includes('# '))) {
console.log(`${filename} ${index + 1}`, '- There must be one space between the octothrope and the comment.')
return false
}
}

return true
})
}
11 changes: 11 additions & 0 deletions rules/end_of_file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = ({ lines, filename }) => {
const noBlankLineEnd = lines.slice(-1)[0] !== ''
if (noBlankLineEnd) {
console.log(filename, '- The file must end with one blank line')
}

const twoBlankLinesEnd = lines.slice(-1)[0] === '' && lines.slice(-2)[0] === ''
if (twoBlankLinesEnd) {
console.log(filename, '- The file must end with one blank line')
}
}
18 changes: 18 additions & 0 deletions rules/expressions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = ({ lines, filename }) => {
lines.every((line, index) => {
if (line.endsWith(';')) {
console.log(`${filename} ${index + 1}`, '- Lines should not end with a semicolon')
return false
}

if (line.trimStart() !== '' && !line.trimStart().startsWith('#')) {
if (!line.includes('function') && ['{', '(', '[', ','].every(lineEnd => !line.endsWith(lineEnd))) {
if ([']', ')'].every(nextLineStart => !lines[index + 1].trimStart().startsWith(nextLineStart))) {
lines[index] = `${line};`
}
}
}

return true
})
}
92 changes: 92 additions & 0 deletions rules/functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
const matchFunctionDeclaration = ({ indentationLevel, line, index, filename }) => {
if (line.startsWith(indentationLevel) && line.endsWith(')') && line.includes('function')) {
if (!line.includes('function (')) {
console.log(`${filename} ${index + 1}`, '- There must be a space between the function and the parenthesis')
} else {
return { index, line }
}
}
}

const missingClosingParentheses = (line) => {
const openingParenthesis = [...line.matchAll(/\(/g)].length
const closingParenthesis = [...line.matchAll(/\)/g)].length

return openingParenthesis - closingParenthesis
}

module.exports = ({ lines, filename }) => {
const indentation = [
' ',
' ',
' ',
' ',
''
]

indentation.every(indentationLevel => {
lines.reduce((functionDeclaration, line, index) => {
if (!functionDeclaration.line) {
const matchedFunctionDeclaration = matchFunctionDeclaration({ indentationLevel, line, index, filename })

if (matchedFunctionDeclaration) {
return matchedFunctionDeclaration
}
} else {
if (line === '') {
const lastLine = lines.length - 1 === index
const topLevelFunction = indentationLevel === ''

if (topLevelFunction) {
if (lastLine) {
lines[functionDeclaration.index] = `${functionDeclaration.line} {`
lines[index] = '};\n'
}
} else {
const remainingExpressionsInTheScope = !lastLine && lines[index + 1].startsWith(`${indentationLevel} `)
if (remainingExpressionsInTheScope) {
return functionDeclaration
}

lines[functionDeclaration.index] = `${functionDeclaration.line} {`
if (missingClosingParentheses(lines[functionDeclaration.index])) {
lines[index - 1] = `${lines[index - 1]}});`
} else {
lines[index - 1] = `${lines[index - 1]}};`
}
functionDeclaration = {}
}
} else {
const topDeclaration = !line.startsWith(' ')
if (topDeclaration) {
const linesBefore = [
lines[index - 1],
lines[index - 2],
lines[index - 3]
]

const twoBlankLines = linesBefore[0] === '' && linesBefore[1] === '' && linesBefore[2] !== ''

if (!twoBlankLines) {
console.log(`${filename} ${index + 1}`, '- There must be two blank lines between each top level function')
return {}
}
lines[functionDeclaration.index] = `${functionDeclaration.line} {`
lines[index - 2] = '};'
functionDeclaration = {}

const matchedFunctionDeclaration = matchFunctionDeclaration({ indentationLevel, line, index, filename })

if (matchedFunctionDeclaration) {
return matchedFunctionDeclaration
}
}
}
}

return functionDeclaration
}, {})

return true
})
}
24 changes: 24 additions & 0 deletions rules/indentation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = ({ lines, filename }) => {
const indentation = [
0,
4,
8,
12,
16
]

lines.every((line, index) => {
const lineIndentation = line.length - line.trimStart().length
if (lineIndentation > 16) {
console.log(`${filename} ${index + 1}`, '- Too much nesting, refactoring is needed.')
return false
}

if (!indentation.includes(lineIndentation)) {
console.log(`${filename} ${index + 1}`, '- Bad indentation')
return false
}

return true
})
}
10 changes: 10 additions & 0 deletions rules/spaces.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = ({ lines, filename }) => {
lines.every((line, index) => {
if (line.length > line.trimEnd().length) {
console.log(`${filename} ${index + 1}`, '- Lines must not end with spaces')
return false
}

return true
})
}

0 comments on commit ca3528e

Please sign in to comment.