Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@prettier/plugin-pug

Package Overview
Dependencies
Maintainers
12
Versions
104
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@prettier/plugin-pug - npm Package Compare versions

Comparing version 1.1.7 to 1.1.8

20

CHANGELOG.md
# Next
[diff](https://github.com/prettier/plugin-pug/compare/1.1.7...master)
[diff](https://github.com/prettier/plugin-pug/compare/1.1.8...master)
# 1.1.8
[diff](https://github.com/prettier/plugin-pug/compare/1.1.7...1.1.8)
- Calculate correct line width ([26fefff])
- Fix indentation for `doctype` ([51d3860])
- Handle angular pipe with parameter ([#70])
- Handle space for indented `text` ([#74])
[#70]: https://github.com/prettier/plugin-pug/issues/70
[#74]: https://github.com/prettier/plugin-pug/issues/74
[26fefff]: https://github.com/prettier/plugin-pug/commit/26fefffbe85f3f698545dbdd68c16140f4afd38c
[51d3860]: https://github.com/prettier/plugin-pug/commit/51d386083eb1a24f57127267d6b486416b94b1c4
# 1.1.7

@@ -9,5 +23,5 @@

- Fix handling of classes ([#70])
- Fix handling of classes ([#72])
[#70]: https://github.com/prettier/plugin-pug/issues/70
[#72]: https://github.com/prettier/plugin-pug/issues/72

@@ -14,0 +28,0 @@ # 1.1.6

35

dist/utils/common.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const prettier_1 = require("prettier");
function previousNormalAttributeToken(tokens, index) {

@@ -19,34 +18,2 @@ for (let i = index - 1; i > 0; i--) {

exports.previousNormalAttributeToken = previousNormalAttributeToken;
function formatText(text, singleQuote) {
let result = '';
while (text) {
const start = text.indexOf('{{');
if (start !== -1) {
result += text.slice(0, start);
text = text.slice(start + 2);
const end = text.indexOf('}}');
if (end !== -1) {
let code = text.slice(0, end);
code = code.trim();
code = prettier_1.format(code, { parser: 'babel', singleQuote: !singleQuote, printWidth: 9000 });
if (code[code.length - 2] === ';' && code[code.length - 1] === '\n') {
code = code.slice(0, -2);
}
result += `{{ ${code} }}`;
text = text.slice(end + 2);
}
else {
result += '{{';
result += text;
text = '';
}
}
else {
result += text;
text = '';
}
}
return result;
}
exports.formatText = formatText;
function unwrapLineFeeds(value) {

@@ -86,2 +53,2 @@ return value.includes('\n')

exports.makeString = makeString;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2NvbW1vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHVDQUFrQztBQUdsQyxTQUFnQiw0QkFBNEIsQ0FBQyxNQUE0QixFQUFFLEtBQWE7SUFDdkYsS0FBSyxJQUFJLENBQUMsR0FBVyxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDM0MsTUFBTSxLQUFLLEdBQVUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9CLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxrQkFBa0IsRUFBRTtZQUN0QyxPQUFPO1NBQ1A7UUFDRCxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFO1lBQy9CLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxJQUFJLEVBQUU7Z0JBQ2xELE9BQU8sS0FBSyxDQUFDO2FBQ2I7U0FDRDtLQUNEO0lBQ0QsT0FBTztBQUNSLENBQUM7QUFiRCxvRUFhQztBQUVELFNBQWdCLFVBQVUsQ0FBQyxJQUFZLEVBQUUsV0FBb0I7SUFDNUQsSUFBSSxNQUFNLEdBQVcsRUFBRSxDQUFDO0lBQ3hCLE9BQU8sSUFBSSxFQUFFO1FBQ1osTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqQyxJQUFJLEtBQUssS0FBSyxDQUFDLENBQUMsRUFBRTtZQUNqQixNQUFNLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDL0IsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzdCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDL0IsSUFBSSxH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
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2NvbW1vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLFNBQWdCLDRCQUE0QixDQUFDLE1BQTRCLEVBQUUsS0FBYTtJQUN2RixLQUFLLElBQUksQ0FBQyxHQUFXLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUMzQyxNQUFNLEtBQUssR0FBVSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDL0IsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGtCQUFrQixFQUFFO1lBQ3RDLE9BQU87U0FDUDtRQUNELElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxXQUFXLEVBQUU7WUFDL0IsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLE9BQU8sSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRTtnQkFDbEQsT0FBTyxLQUFLLENBQUM7YUFDYjtTQUNEO0tBQ0Q7SUFDRCxPQUFPO0FBQ1IsQ0FBQztBQWJELG9FQWFDO0FBRUQsU0FBZ0IsZUFBZSxDQUFDLEtBQWE7SUFDNUMsT0FBTyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztRQUMxQixDQUFDLENBQUMsS0FBSzthQUNKLEtBQUssQ0FBQyxJQUFJLENBQUM7YUFDWCxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQzthQUMxQixHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7YUFDbEQsSUFBSSxDQUFDLEVBQUUsQ0FBQzthQUNSLElBQUksRUFBRTtRQUNULENBQUMsQ0FBQyxLQUFLLENBQUM7QUFDVixDQUFDO0FBVEQsMENBU0M7QUFxQ0QsU0FBZ0IsUUFBUSxDQUFDLEdBQVc7SUFDbkMsT0FBTyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDbkMsQ0FBQztBQUZELDRCQUVDO0FBR0QsU0FBZ0IsVUFBVSxDQUN6QixVQUFrQixFQUNsQixjQUF5QixFQUN6Qiw2QkFBc0MsS0FBSztJQUUzQyxNQUFNLFVBQVUsR0FBRyxjQUFjLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUN0RCxNQUFNLFVBQVUsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLG9CQUFvQixFQUFFLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTtRQUNyRixJQUFJLE9BQU8sS0FBSyxVQUFVLEVBQUU7WUFDM0IsT0FBTyxPQUFPLENBQUM7U0FDZjtRQUNELElBQUksS0FBSyxLQUFLLGNBQWMsRUFBRTtZQUM3QixPQUFPLElBQUksR0FBRyxLQUFLLENBQUM7U0FDcEI7UUFDRCxJQUFJLEtBQUssRUFBRTtZQUNWLE9BQU8sS0FBSyxDQUFDO1NBQ2I7UUFDRCxPQUFPLDBCQUEwQixJQUFJLHNDQUFzQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDeEYsQ0FBQyxDQUFDLE9BQU87WUFDVCxDQUFDLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztJQUNuQixDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sY0FBYyxHQUFHLFVBQVUsR0FBRyxjQUFjLENBQUM7QUFDckQsQ0FBQztBQXJCRCxnQ0FxQkMifQ==
{
"name": "@prettier/plugin-pug",
"version": "1.1.7",
"version": "1.1.8",
"description": "Prettier Pug Plugin",

@@ -35,3 +35,3 @@ "main": "dist/index.js",

"@types/jest": "~25.1.2",
"@types/node": "~13.7.0",
"@types/node": "~13.7.1",
"@types/prettier": "~1.19.0",

@@ -38,0 +38,0 @@ "@typescript-eslint/eslint-plugin": "~2.19.2",

@@ -53,3 +53,3 @@ import { format, ParserOptions, RequiredOptions } from 'prettier';

import { isAngularAction, isAngularBinding, isAngularDirective, isAngularInterpolation } from './utils/angular';
import { formatText, isQuoted, makeString, previousNormalAttributeToken, unwrapLineFeeds } from './utils/common';
import { isQuoted, makeString, previousNormalAttributeToken, unwrapLineFeeds } from './utils/common';
import { isVueExpression } from './utils/vue';

@@ -73,2 +73,3 @@

private readonly quotes: "'" | '"';
private readonly otherQuotes: "'" | '"';

@@ -103,2 +104,3 @@ private readonly alwaysUseAttributeSeparator: boolean;

this.quotes = this.options.singleQuote ? "'" : '"';
this.otherQuotes = this.options.singleQuote ? '"' : "'";
this.alwaysUseAttributeSeparator = resolveAttributeSeparatorOption(options.attributeSeparator);

@@ -201,2 +203,81 @@ this.codeInterpolationOptions = {

private formatText(text: string): string {
let result: string = '';
while (text) {
const start = text.indexOf('{{');
if (start !== -1) {
result += text.slice(0, start);
text = text.slice(start + 2);
const end = text.indexOf('}}');
if (end !== -1) {
let code = text.slice(0, end);
try {
// Index of primary quote
const q1 = code.indexOf(this.quotes);
// Index of secondary (other) quote
const q2 = code.indexOf(this.otherQuotes);
// Index of backtick
const qb = code.indexOf('`');
if (q1 >= 0 && q2 >= 0 && q2 > q1 && (qb < 0 || q1 < qb)) {
logger.log({ code, quotes: this.quotes, otherQuotes: this.otherQuotes, q1, q2, qb });
logger.warn(
'The following expression could not be formatted correctly. Please try to fix it yourself and if there is a problem, please open a bug issue:',
code
);
result += `{{ ${code} }}`;
text = text.slice(end + 2);
continue;
} else {
code = format(code, {
parser: '__ng_interpolation' as any,
...this.codeInterpolationOptions
});
}
} catch (error) {
if (typeof error === 'string') {
if (error.includes('Unexpected token Lexer Error')) {
if (!error.includes('Unexpected character [`]')) {
logger.debug('[PugPrinter:formatText]: Using fallback strategy');
}
} else if (error.includes('Bindings cannot contain assignments')) {
logger.warn(
'[PugPrinter:formatText]: Bindings should not contain assignments:',
code.trim()
);
} else {
logger.warn('[PugPrinter:formatText]: ', error);
}
// else ignore message
} else {
logger.warn('[PugPrinter:formatText]: ', error);
}
try {
code = format(code, {
parser: 'babel',
...this.codeInterpolationOptions,
semi: false
});
if (code[0] === ';') {
code = code.slice(1);
}
} catch (error) {
logger.warn(error);
}
}
code = unwrapLineFeeds(code);
result += `{{ ${code} }}`;
text = text.slice(end + 2);
} else {
result += '{{';
result += text;
text = '';
}
} else {
result += text;
text = '';
}
}
return result;
}
private formatVueExpression(val: string): string {

@@ -219,9 +300,17 @@ return this.formatDelegatePrettier(val, '__vue_expression');

private formatAngularInterpolation(val: string): string {
val = val.slice(3, -3);
val = val.slice(1, -1); // Remove quotes
val = val.slice(2, -2); // Remove braces
val = val.trim();
val = val.replace(/\s\s+/g, ' ');
// val = format(val, {
// parser: '__ng_interpolation' as any,
// ...codeInterpolationOptions
// });
if (val.includes(`\\${this.otherQuotes}`)) {
logger.warn(
'The following expression could not be formatted correctly. Please try to fix it yourself and if there is a problem, please open a bug issue:',
val
);
} else {
val = format(val, {
parser: '__ng_interpolation' as any,
...this.codeInterpolationOptions
});
val = unwrapLineFeeds(val);
}
return this.quoteString(`{{ ${val} }}`);

@@ -264,6 +353,37 @@ }

let tempIndex: number = this.currentIndex + 1;
while (tempToken.type === 'attribute' && this.currentLineLength <= this.options.printWidth) {
this.currentLineLength += tempToken.name.length + 1 + tempToken.val.toString().length;
let nonPrefixAttributes = 0;
let hasPrefixAttribute = false;
while (tempToken.type === 'attribute') {
switch (tempToken.name) {
case 'class':
case 'id':
hasPrefixAttribute = true;
this.currentLineLength += 1 + tempToken.val.toString().length;
break;
default: {
nonPrefixAttributes += 1;
this.currentLineLength += tempToken.name.length;
const val = tempToken.val.toString();
if (val.length > 0 && val !== 'true') {
this.currentLineLength += 1 + val.length;
}
break;
}
}
tempToken = this.tokens[++tempIndex] as AttributeToken | EndAttributesToken;
}
if (hasPrefixAttribute) {
// Remove div
if (this.previousToken?.type === 'tag' && this.previousToken.val === 'div') {
this.currentLineLength -= 3;
}
}
const hasPrefixAttributes = nonPrefixAttributes > 0;
if (!hasPrefixAttributes) {
// Remove braces
this.currentLineLength -= 2;
} else if (nonPrefixAttributes > 1) {
// Attributes are separated by commas: ', '.length === 2
this.currentLineLength += 2 * (nonPrefixAttributes - 1);
}
if (this.currentLineLength > this.options.printWidth) {

@@ -407,3 +527,3 @@ this.wrapAttributes = true;

private ['end-attributes'](token: EndAttributesToken): void {
if (this.wrapAttributes) {
if (this.wrapAttributes && this.result[this.result.length - 1] !== '(') {
this.result += '\n';

@@ -551,2 +671,6 @@ this.result += this.indentString.repeat(this.indentLevel);

result += this.indentString;
if (/^ .+$/.test(val)) {
result += '|\n';
result += this.indentString.repeat(this.indentLevel);
}
result += '|';

@@ -566,4 +690,3 @@ if (/.*\S.*/.test(token.val)) {

val = val.trim();
val = formatText(val, this.options.singleQuote);
val = this.formatText(val);
val = val.replace(/#(\{|\[)/g, '\\#$1');

@@ -671,3 +794,3 @@ }

private doctype(token: DoctypeToken): string {
let result = 'doctype';
let result = `${this.computedIndent}doctype`;
if (token.val) {

@@ -674,0 +797,0 @@ result += ` ${token.val}`;

@@ -1,2 +0,1 @@

import { format } from 'prettier';
import { AttributeToken, Token } from 'pug-lexer';

@@ -19,32 +18,2 @@

export function formatText(text: string, singleQuote: boolean): string {
let result: string = '';
while (text) {
const start = text.indexOf('{{');
if (start !== -1) {
result += text.slice(0, start);
text = text.slice(start + 2);
const end = text.indexOf('}}');
if (end !== -1) {
let code = text.slice(0, end);
code = code.trim();
code = format(code, { parser: 'babel', singleQuote: !singleQuote, printWidth: 9000 });
if (code[code.length - 2] === ';' && code[code.length - 1] === '\n') {
code = code.slice(0, -2);
}
result += `{{ ${code} }}`;
text = text.slice(end + 2);
} else {
result += '{{';
result += text;
text = '';
}
} else {
result += text;
text = '';
}
}
return result;
}
export function unwrapLineFeeds(value: string): string {

@@ -51,0 +20,0 @@ return value.includes('\n')

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc