Skip to content

Commit

Permalink
feat: custom fill char
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Aug 3, 2023
1 parent 22f71fa commit e1b3fdf
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 9 deletions.
5 changes: 3 additions & 2 deletions src/acorn.ts
Expand Up @@ -8,14 +8,15 @@ import type { StripLiteralOptions } from './types'
* Will throw error if the input is not valid JavaScript.
*/
export function _stripLiteralAcorn(code: string, options?: StripLiteralOptions) {
const FILL = ' '
const FILL = options?.fillChar ?? ' '
const FILL_COMMENT = ' '
let result = ''

const filter = options?.filter ?? (() => true)

function fillupTo(index: number) {
if (index > result.length)
result += code.slice(result.length, index).replace(/[^\n]/g, FILL)
result += code.slice(result.length, index).replace(/[^\n]/g, FILL_COMMENT)
}

const tokens: Token[] = []
Expand Down
10 changes: 6 additions & 4 deletions src/regex.ts
Expand Up @@ -15,11 +15,13 @@ const quotesRE = [
* But will have some caveats on distinguish strings and comments.
*/
export function stripLiteralRegex(code: string, options?: StripLiteralOptions) {
const FILL_COMMENT = ' '
const FILL = options?.fillChar ?? ' '
const filter = options?.filter ?? (() => true)

code = code
.replace(multilineCommentsRE, s => filter(s) ? ' '.repeat(s.length) : s)
.replace(singlelineCommentsRE, s => filter(s) ? ' '.repeat(s.length) : s)
.replace(multilineCommentsRE, s => filter(s) ? FILL_COMMENT.repeat(s.length) : s)
.replace(singlelineCommentsRE, s => filter(s) ? FILL_COMMENT.repeat(s.length) : s)

let expanded = code
// Recursively replace ${} to support nested constructs (e.g. ${`${x}`})
Expand All @@ -35,8 +37,8 @@ export function stripLiteralRegex(code: string, options?: StripLiteralOptions) {
.replace(re, (s, quote, body, index) => {
if (!filter(s.slice(1, -1)))
return s
code = code.slice(0, index + 1) + ' '.repeat(s.length - 2) + code.slice(index + s.length - 1)
return quote + ' '.repeat(s.length - 2) + quote
code = code.slice(0, index + 1) + FILL.repeat(s.length - 2) + code.slice(index + s.length - 1)
return quote + FILL.repeat(s.length - 2) + quote
})
})

Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Expand Up @@ -3,4 +3,12 @@ export interface StripLiteralOptions {
* Will be called for each string literal. Return false to skip stripping.
*/
filter?: (s: string) => boolean

/**
* Fill the stripped literal with this character.
* It must be a single character.
*
* @default ' '
*/
fillChar?: string
}
56 changes: 56 additions & 0 deletions test/custom-fill.test.ts
@@ -0,0 +1,56 @@
import { describe, expect, it } from 'vitest'
import { executeWithVerify } from './utils'

describe('custom-fill', () => {
it('acorn', () => {
const result = executeWithVerify(`
// comment1
const a = 'aaaa'
/* comment2 */
const b = "bbbb"
const c = \`aaaa\${foo}dddd\${bar}\`
`.trim(),
false,
{
fillChar: '-',
filter: s => s !== 'aaaa',
})

expect(result).toMatchInlineSnapshot(`
"// mode: acorn
const a = 'aaaa'
const b = \\"----\\"
const c = \`aaaa\${foo}----\${bar}\`"
`)
})

it('regex', () => {
const result = executeWithVerify(`
\\
// comment1
const a = 'aaaa'
/* comment2 */
const b = "bbbb"
const c = \`aaaa\${foo}dddd\${bar}\`
`.trim(),
false,
{
fillChar: '-',
filter: s => s !== 'aaaa',
})

expect(result).toMatchInlineSnapshot(`
"// mode: regex
\\\\ const a = 'aaaa'
const b = \\"----\\"
const c = \`aaaa\${foo}----\${bar}\`"
`)
})
})
8 changes: 5 additions & 3 deletions test/utils.ts
Expand Up @@ -12,9 +12,11 @@ export function executeWithVerify(code: string, verifyAst = true, options?: Stri

const stripped = result.result

for (let i = 0; i < stripped.length; i++) {
if (!stripped[i].match(/\s/))
expect(stripped[i]).toBe(code[i])
if (!options?.fillChar) {
for (let i = 0; i < stripped.length; i++) {
if (!stripped[i].match(/\s/))
expect(stripped[i]).toBe(code[i])
}
}

expect(stripped.length).toBe(code.length)
Expand Down

0 comments on commit e1b3fdf

Please sign in to comment.