Skip to content

Commit 8d44acc

Browse files
committed
Fix newlines being removed for nothing
We need to join with a single space for newlines and make sure that it's safe to remove this space. We achieve this by compressing spaces around symbols instead.
1 parent acbdced commit 8d44acc

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

src/minify/index.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { makePlaceholder, splitByPlaceholders } from '../css/placeholderUtils'
22

33
const makeMultilineCommentRegex = newlinePattern => new RegExp('\\/\\*(.|' + newlinePattern + ')*?\\*\\/', 'g')
44
const lineCommentStart = /\/\//g
5+
const symbolRegex = /(\s*[;:{},]\s*)/g
56

67
// Counts occurences of substr inside str
78
const countOccurences = (str, substr) => str.split(substr).length - 1
@@ -37,6 +38,25 @@ export const stripLineComment = line => (
3738
))
3839
)
3940

41+
export const compressSymbols = code => code
42+
.split(symbolRegex)
43+
.reduce((str, fragment, index) => {
44+
// Even-indices are non-symbol fragments
45+
if (index % 2 === 0) {
46+
return str + fragment
47+
}
48+
49+
// Only manipulate symbols outside of strings
50+
if (
51+
countOccurences(str, '\'') % 2 === 0 &&
52+
countOccurences(str, '\"') % 2 === 0
53+
) {
54+
return str + fragment.trim()
55+
}
56+
57+
return str + fragment
58+
}, '')
59+
4060
// Detects lines that are exclusively line comments
4161
const isLineComment = line => line.trim().startsWith('//')
4262

@@ -46,14 +66,14 @@ const minify = linebreakPattern => {
4666
const multilineCommentRegex = makeMultilineCommentRegex(linebreakPattern)
4767

4868
return code => {
49-
const lines = code
69+
const newCode = code
5070
.replace(multilineCommentRegex, '\n') // Remove multiline comments
5171
.split(linebreakRegex) // Split at newlines
72+
.filter(line => line.length > 0 && !isLineComment(line)) // Removes lines containing only line comments
5273
.map(stripLineComment) // Remove line comments inside text
74+
.join(' ') // Rejoin all lines
5375

54-
return lines
55-
.filter(line => !isLineComment(line)) // Removes lines containing only line comments
56-
.join('')
76+
return compressSymbols(newCode)
5777
}
5878
}
5979

test/minify/index.test.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {
22
stripLineComment,
33
minifyRaw,
4-
minifyCooked
4+
minifyCooked,
5+
compressSymbols
56
} from '../../src/minify'
67

78
describe('minify utils', () => {
@@ -27,7 +28,7 @@ describe('minify utils', () => {
2728
describe('minify(Raw|Cooked)', () => {
2829
it('Removes multi-line comments', () => {
2930
const input = 'this is a/* ignore me please */test'
30-
const expected = 'this is atest' // NOTE: They're replaced with newlines, and newlines are joined
31+
const expected = 'this is a test' // NOTE: They're replaced with newlines, and newlines are joined
3132
const actual = minifyRaw(input)
3233

3334
expect(actual).toBe(expected)
@@ -36,7 +37,7 @@ describe('minify utils', () => {
3637

3738
it('Joins all lines of code', () => {
3839
const input = 'this\nis\na/* ignore me \n please */\ntest'
39-
const expected = 'thisisatest'
40+
const expected = 'this is a test'
4041
const actual = minifyRaw(input)
4142

4243
expect(actual).toBe(expected)
@@ -45,7 +46,7 @@ describe('minify utils', () => {
4546

4647
it('Removes line comments filling an entire line', () => {
4748
const input = 'line one\n// remove this comment\nline two'
48-
const expected = 'line oneline two'
49+
const expected = 'line one line two'
4950
const actual = minifyRaw(input)
5051

5152
expect(actual).toBe(expected)
@@ -54,7 +55,7 @@ describe('minify utils', () => {
5455

5556
it('Removes line comments at the end of lines of code', () => {
5657
const input = 'valid line with // a comment\nout comments'
57-
const expected = 'valid line with out comments'
58+
const expected = 'valid line with out comments'
5859
const actual = minifyRaw(input)
5960

6061
expect(actual).toBe(expected)
@@ -65,13 +66,29 @@ describe('minify utils', () => {
6566
describe('minifyRaw', () => {
6667
it('works with raw escape codes', () => {
6768
const input = 'this\\nis\\na/* ignore me \\n please */\\ntest'
68-
const expected = 'thisisatest'
69+
const expected = 'this is a test'
6970
const actual = minifyRaw(input)
7071

7172
expect(minifyRaw(input)).toBe(expected)
7273

7374
// NOTE: This is just a sanity check
74-
expect(minifyCooked(input)).toBe('this\\nis\\na\\ntest')
75+
expect(minifyCooked(input)).toBe('this\\nis\\na \\ntest')
76+
})
77+
})
78+
79+
describe('compressSymbols', () => {
80+
it('removes spaces around symbols', () => {
81+
const input = '; : { } , ; '
82+
const expected = ';:{},;'
83+
84+
expect(compressSymbols(input)).toBe(expected)
85+
})
86+
87+
it('ignores symbols inside strings', () => {
88+
const input = '; " : " \' : \' ;'
89+
const expected = ';" : " \' : \';'
90+
91+
expect(compressSymbols(input)).toBe(expected)
7592
})
7693
})
7794
})

0 commit comments

Comments
 (0)