Skip to content

Commit

Permalink
Improve conversion of tags to literals
Browse files Browse the repository at this point in the history
Closes #133
  • Loading branch information
lehni committed Oct 4, 2020
1 parent 8106cda commit f01b05e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 21 deletions.
42 changes: 21 additions & 21 deletions src/printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export class PugPrinter {
>;
/* eslint-enable @typescript-eslint/indent */

private currentTagPosition: number = 0;
private possibleIdPosition: number = 0;
private possibleClassPosition: number = 0;

Expand Down Expand Up @@ -264,6 +265,21 @@ export class PugPrinter {
return parts;
}

private maybeReplaceTagWithLiteral(search: RegExp, replace: string) {
const currentTagEnd = Math.max(this.possibleIdPosition, this.possibleClassPosition);
const tag = this.result.slice(this.currentTagPosition, currentTagEnd);
const replaced: string = tag.replace(search, replace);
if (replaced !== tag) {
const prefix = this.result.slice(0, this.currentTagPosition);
const suffix = this.result.slice(currentTagEnd);
this.result = `${prefix}${replaced}${suffix}`;
// tag was replaced, so adjust possible positions as well
const diff = tag.length - replaced.length;
this.possibleIdPosition -= diff;
this.possibleClassPosition -= diff;
}
}

private formatDelegatePrettier(
val: string,
parser: '__vue_expression' | '__ng_binding' | '__ng_action' | '__ng_directive'
Expand Down Expand Up @@ -432,6 +448,7 @@ export class PugPrinter {
this.currentLineLength += val.length;
const result: string = `${this.computedIndent}${val}`;
logger.debug('tag', { result, val: token.val, length: token.val.length }, this.currentLineLength);
this.currentTagPosition = this.result.length + this.computedIndent.length;
this.possibleIdPosition = this.result.length + result.length;
this.possibleClassPosition = this.result.length + result.length;
return result;
Expand Down Expand Up @@ -547,11 +564,8 @@ export class PugPrinter {
if (isQuoted(token.val)) {
if (token.name === 'class') {
// Handle class attribute
let val: string = token.val;
val = val.slice(1, -1);
val = val.trim();
val = val.replace(/\s\s+/g, ' ');
const classes: string[] = val.split(' ');
const val: string = token.val.slice(1, -1).trim();
const classes: string[] = val.split(/\s+/);
const specialClasses: string[] = [];
const normalClasses: string[] = [];
const validClassNameRegex: RegExp = /^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/;
Expand All @@ -572,14 +586,7 @@ export class PugPrinter {
this.result.slice(position)
].join('');
this.possibleClassPosition += 1 + normalClasses.join('.').length;
// See if `div` can be removed from the literal
const replaced: string = this.result.replace(/div\./, '.');
if (replaced !== this.result) {
this.result = replaced;
// `div` was removed, so reduce possible positions as well
this.possibleIdPosition -= 3;
this.possibleClassPosition -= 3;
}
this.maybeReplaceTagWithLiteral(/div\./, '.');
}
if (specialClasses.length > 0) {
token.val = makeString(specialClasses.join(' '), this.quotes);
Expand Down Expand Up @@ -608,14 +615,7 @@ export class PugPrinter {
const literal: string = `#${val}`;
this.result = [this.result.slice(0, position), literal, this.result.slice(position)].join('');
this.possibleClassPosition += literal.length;
// See if `div` can be removed from the literal
const replaced: string = this.result.replace(/div#/, '#');
if (replaced !== this.result) {
this.result = replaced;
// `div` was removed, so reduce possible positions as well
this.possibleIdPosition -= 3;
this.possibleClassPosition -= 3;
}
this.maybeReplaceTagWithLiteral(/div#/, '#');
this.previousAttributeRemapped = true;
return;
}
Expand Down
5 changes: 5 additions & 0 deletions tests/literals/matching-content/formatted.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
p
| Just some text mentioning "div#id"
| or perhaps it talks about "div.class"
#id
.class
14 changes: 14 additions & 0 deletions tests/literals/matching-content/matching-content.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { readFileSync } from 'fs';
import { resolve } from 'path';
import { format } from 'prettier';
import { plugin } from './../../../src/index';

describe('Attributes', () => {
test('should not replace matching literal strings in text content', () => {
const expected: string = readFileSync(resolve(__dirname, 'formatted.pug'), 'utf8');
const code: string = readFileSync(resolve(__dirname, 'unformatted.pug'), 'utf8');
const actual: string = format(code, { parser: 'pug' as any, plugins: [plugin] });

expect(actual).toBe(expected);
});
});
5 changes: 5 additions & 0 deletions tests/literals/matching-content/unformatted.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
p
| Just some text mentioning "div#id"
| or perhaps it talks about "div.class"
div(id="id")
div(class="class")

0 comments on commit f01b05e

Please sign in to comment.