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

indent.js

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

indent.js - npm Package Compare versions

Comparing version 0.1.2 to 0.1.3

tests/big-bang.spec.js

2

bower.json
{
"name": "indent.js",
"version": "0.1.2",
"version": "0.1.3",
"homepage": "https://github.com/zebzhao/indent.js",

@@ -5,0 +5,0 @@ "main": "lib/indent.js",

@@ -11,19 +11,136 @@ ;(function(root, factory) {

var indent = (function() {
var rulesCache = {};
function filterRules(language) {
if (rulesCache[language])
return rulesCache[language];
var ret = [];
rulesCache[language] = ret;
for (var i=0; i<masterRules.length; i++) {
if (masterRules[i].langs.indexOf(language.toLowerCase()) != -1)
ret.push(masterRules[i]);
}
return ret;
}
var NEW_LINE_REGEX = /\r*\n/;
var jsRules = [
/**
* indent - whether rule will cause indent
* ignore - ignore rule matching as long as is last active rule, e.g. string, comments
* advance - greedily consume endTokens when rule ends
* head - match at beginning of line only
* langs - used to filter by language later
* lineOffset - added to the line field when rule is applied
*
* Always keep NEW_LINE_REGEX endToken as last element,
* as otherwise it will be matched first, and subsequent ones may be ignored
* and skipped permanently by other rules.
*/
var masterRules = [
{
langs: "html",
name: "comment",
startToken: [/\<\!\-\-/],
endToken: [/\-\-\>/],
ignore: true,
advance: true
},
{
langs: "html",
name: "doctype",
startToken: [/\<\!/],
endToken: [NEW_LINE_REGEX],
ignore: true,
advance: true
},
{
langs: "html",
name: "link|br|input|meta",
startToken: [/\<(link|br|input|meta)/i],
endToken: [/>/],
advance: true
},
{
langs: "html",
name: "mode switch js",
startToken: [function (string, rule) {
var start = /<script[\s>].*/i;
var end = /<\/script>/i;
var startMatch = start.exec(string);
var endMatch = end.exec(string);
if (startMatch && (!endMatch || endMatch.index < startMatch.index)) {
return {
matchIndex: startMatch.index,
length: startMatch[0].length
};
}
return {matchIndex: -1};
}],
endToken: [/<\/script>/i],
rules: "js",
advance: true,
indent: true
},
{
langs: "html",
name: "mode switch css",
startToken: [function (string, rule) {
var start = /<style[\s>].*/i;
var end = /<\/style>/i;
var startMatch = start.exec(string);
var endMatch = end.exec(string);
if (startMatch && (!endMatch || endMatch.index < startMatch.index)) {
return {
matchIndex: startMatch.index,
length: startMatch[0].length
};
}
return {matchIndex: -1};
}],
endToken: [/<\/style>/i],
rules: "css",
advance: true,
indent: true
},
{
langs: "html",
name: "close-tag",
startToken: [/<\/[A-Za-z0-9\-]+>/],
endToken: [/./],
indent: true
},
{
langs: "html",
name: "tag attr",
startToken: [/<[A-Za-z0-9\-]+/],
endToken: [/>/],
indent: true
},
{
langs: "html",
name: "tag",
startToken: [/>/],
endToken: [/<\/[A-Za-z0-9\-]+>/],
indent: true,
advance: true
},
{
langs: "js",
name: "line comment",
startToken: [/\/\//],
endToken: [NEW_LINE_REGEX],
ignore: true,
indent: false
ignore: true
},
{
langs: "js css",
name: "block comment",
startToken: [/\/\*/],
endToken: [/\*\//],
ignore: true,
indent: false
ignore: true
},
{
langs: "js",
name: "regex",

@@ -72,6 +189,6 @@ startToken: [function (string, rule) {

ignore: true,
indent: false,
advance: true
},
{
langs: "js css html",
name: "string",

@@ -81,6 +198,6 @@ startToken: [/\"/],

ignore: true,
indent: false,
advance: true
},
{
langs: "js css html",
name: "string",

@@ -90,6 +207,6 @@ startToken: [/\'/],

ignore: true,
indent: false,
advance: true
},
{
langs: "js css html",
name: "string",

@@ -99,26 +216,29 @@ startToken: [/\`/],

ignore: true,
indent: false,
advance: true
},
{
langs: "js",
name: "if",
startToken: [/^if[\s]*(?=\()/, /[\s]+if[\s]*(?=\()/],
endToken: [/else[\s]+/, /\{/, /\;/],
endToken: [/else[\s]+/, /\{/, /;/],
indent: true
},
{
langs: "js",
name: "for",
startToken: [/^for[\s]*(?=\()/],
endToken: [/\{/, /\;/],
endToken: [/\{/, /;/],
indent: true
},
{
langs: "js",
name: "else",
startToken: [/else[\s]+/],
endToken: [/if/, /\{/, /\;/, NEW_LINE_REGEX],
endToken: [/if/, /\{/, /;/, NEW_LINE_REGEX],
indent: true
},
{
langs: "js css",
name: "bracket",
startToken: [/\(/],
startToken: [/\([\s]*(var)?/],
endToken: [/\)/],

@@ -129,5 +249,27 @@ indent: true,

{
langs: "js",
name: "dot chain",
startToken: [/^\../],
endToken: [/;/, NEW_LINE_REGEX],
indent: true,
head: true,
lineOffset: -1
},
{
langs: "js",
name: "dot chain",
startToken: [/\.\s*$/],
endToken: [function (string, rule) {
return {
matchIndex: string.length ? 1 : -1,
length: string.length ? 0 : 1
};
}],
indent: true
},
{
langs: "js css",
name: "array",
startToken: [/\[/],
endToken: [/\]/],
endToken: [/]/],
indent: true,

@@ -137,5 +279,6 @@ advance: true

{
langs: "js css",
name: "block",
startToken: [/\{/],
endToken: [/\}/],
endToken: [/}/],
indent: true,

@@ -145,11 +288,13 @@ advance: true

{
langs: "js",
name: "var",
startToken: [/var[\s]+/],
endToken: [/\;/],
endToken: [/;/],
indent: true
},
{
langs: "js",
name: "case",
startToken: [/^case[\s]+/],
endToken: [/break[\s;]+/, /^case[\s]+/, /^default[\s]+/, /\}/],
endToken: [/break[\s;]+/, /^case[\s]+/, /^default[\s]+/, /}/],
indent: true

@@ -159,45 +304,4 @@ }

var htmlRules = [
{
name: "comment",
startToken: [/\<\!\-\-/],
endToken: [/\-\-\>/],
ignore: true,
indent: false,
advance: true
},
{
name: "doctype",
startToken: [/\<\!/],
endToken: [NEW_LINE_REGEX],
ignore: true,
indent: false,
advance: true
},
{
name: "link|br|input|meta",
startToken: [/\<(link|br|input|meta)/i],
endToken: [/(\"[^\"]*\"|'[^']*'|[^'\">])*>/],
ignore: true,
indent: false,
advance: true
},
{
name: "tag",
startToken: [/<(\"[^\"]*\"|'[^']*'|[^'\">])*>/],
endToken: [/\<\/[^\>]+\>/],
indent: true,
advance: true
},
{
name: "tag",
startToken: [/<(\"[^\"]*\"|'[^']*'|[^'\">])*/],
endToken: [/\/\>/],
indent: false,
advance: true
}
].concat(jsRules);
return {
indentCSS: indentJS,
indentCSS: indentCSS,
indentJS: indentJS,

@@ -208,10 +312,14 @@ indentHTML: indentHTML

function indentJS(code, indentString) {
return indent(code, jsRules, indentString);
return indent(code, filterRules('js'), indentString);
}
function indentCSS(code, indentString) {
return indent(code, filterRules('css'), indentString);
}
function indentHTML(code, indentString) {
return indent(code, htmlRules, indentString);
return indent(code, filterRules('html'), indentString);
}
function indent(code, rules, indentation) {
function indent(code, baseRules, indentation) {
var lines = code.split(/[\r]?\n/gi);

@@ -227,2 +335,3 @@ var lineCount = lines.length;

var matchEnd, matchStart;
var modeRules = null;

@@ -233,3 +342,3 @@ while (l < lineCount) {

matchStart = matchStartRule(lineToMatch, rules, pos);
matchStart = matchStartRule(lineToMatch, modeRules || baseRules, pos);

@@ -246,10 +355,4 @@ if (activeRules.length) {

else if (lastRule.ignore || matchStart.matchIndex == -1 || matchEnd.matchIndex <= matchStart.matchIndex) {
if (lastRule.indent) {
consumeIndentation();
if (matchEnd.matchIndex == 0) {
calculateIndents();
}
}
removeLastRule();
pos = matchEnd.cursor;
removeLastRule();
continue; // Repeat process for matching line start/end

@@ -274,7 +377,20 @@ }

activeRules.push(lastRule);
if (lastRule.indent)
incrementIndentation();
if (lastRule.indent) {
incrementIndentation(lastRule.lineOffset);
}
if (lastRule.rules) {
modeRules = filterRules(lastRule.rules);
}
}
function removeLastRule() {
if (lastRule.indent) {
consumeIndentation();
if (matchEnd.matchIndex == 0) {
calculateIndents();
}
}
if (lastRule.rules) {
modeRules = null;
}
activeRules.pop();

@@ -300,3 +416,3 @@ lastRule = activeRules[activeRules.length - 1];

function incrementIndentation() {
function incrementIndentation(lineOffset) {
var matched = indentBuffer[indentBuffer.length - 1];

@@ -310,4 +426,5 @@ if (matched && matched.line == l) {

open: true,
line: l
line: lineOffset ? l + lineOffset : l
});
if (lineOffset < 0) calculateIndents();
}

@@ -344,3 +461,4 @@ }

match = searchAny(string, rule.startToken, rule);
if (match.matchIndex != -1 && match.matchIndex < minIndex) {
if (match.matchIndex != -1 && match.matchIndex < minIndex
&& (!rule.head || index == 0)) {
minIndex = match.matchIndex;

@@ -347,0 +465,0 @@ minMatch = match;

@@ -10,4 +10,4 @@ ;(function(root, factory) {

}(this, function() {
var indent=function(){function n(n,e){return t(n,s,e)}function e(n,e){return t(n,m,e)}function t(n,e,t){function d(n){y=n.cursor,k=n.rule,I.push(k),k.indent&&u()}function c(){I.pop(),k=I[I.length-1]}function s(){p=0;for(var n,e=0;e<v.length;e++)n=v[e],n.open&&n.line!=b&&p++}function m(){x[b]=a(t,p)+A,b++,y=0,s()}function u(){var n=v[v.length-1];n&&n.line==b?n.indent++:v.push({indent:1,open:!0,line:b})}function h(){var n=v[v.length-1];n&&(n.open=b==n.line,--n.indent<=0&&v.pop())}for(var k,g,f,T=n.split(/[\r]?\n/gi),l=T.length,x=[],v=[],I=[],p=0,b=0,y=0;b<l;){var A=T[b].trim(),L=r(A)+"\r\n";if(f=o(L,e,y),I.length)if(g=i(L,k,y),g.matchIndex==-1){if(k.ignore){m();continue}}else if(k.ignore||f.matchIndex==-1||g.matchIndex<=f.matchIndex){k.indent&&(h(),0==g.matchIndex&&s()),y=g.cursor,c();continue}f.matchIndex!=-1?d(f):m()}return x.join("\r\n")}function a(n,e){return new Array(e+1).join(n)}function r(n){return n.replace(/\\(u[0-9A-Za-z]{4}|u\{[0-9A-Za-z]{1,6}]\}|x[0-9A-Za-z]{2}|.)/g,"0")}function o(n,e,t){n=n.substring(t,n.length);for(var a,r,o,i=null,c=n.length,s=0;s<e.length;s++)o=e[s],r=d(n,o.startToken,o),r.matchIndex!=-1&&r.matchIndex<c&&(c=r.matchIndex,a=r,i=o);return{rule:i,matchIndex:i?c+t:-1,cursor:i?c+t+a.matchLength:-1}}function i(n,e,t){n=n.substr(t,n.length);var a=d(n,e.endToken,e),r=e.advance?a.matchIndex+a.matchLength:a.matchIndex;return{matchIndex:a.matchIndex==-1?-1:a.matchIndex+t,cursor:r==-1?-1:r+t}}function d(n,e,t){for(var a,r=-1,o=0,i=0;i<e.length;i++)if(a=e[i],"function"==typeof a){var d=a(n,t);r=d.matchIndex,o=d.length}else if(r=n.search(a),r!=-1){o=n.match(a)[0].length;break}return{matchIndex:r,matchLength:o,cursor:r+o,patternIndex:i}}var c=/\r*\n/,s=[{name:"line comment",startToken:[/\/\//],endToken:[c],ignore:!0,indent:!1},{name:"block comment",startToken:[/\/\*/],endToken:[/\*\//],ignore:!0,indent:!1},{name:"regex",startToken:[function(n,e){var t=/[(,=:[!&|?{};][\s]*\/[^\/]|^[\s]*\/[^\/]/,a=n.search(t);if(a!=-1){a=n.indexOf("/",a);var r=n.substring(a+1),o=d(r,e.endToken,e);if(o.matchIndex!=-1){r=r.substring(0,o.matchIndex);try{return new RegExp(r),{matchIndex:a,length:1}}catch(i){return{matchIndex:-1}}}}return{matchIndex:-1}}],endToken:[function(n,e){for(var t=0,a=n.indexOf("/");a!=-1;)try{new RegExp(n.substring(0,a));break}catch(r){a=n.indexOf("/",t),t=a+1}return{matchIndex:a,length:a==-1?0:1}}],ignore:!0,indent:!1,advance:!0},{name:"string",startToken:[/\"/],endToken:[/\"/,c],ignore:!0,indent:!1,advance:!0},{name:"string",startToken:[/\'/],endToken:[/\'/,c],ignore:!0,indent:!1,advance:!0},{name:"string",startToken:[/\`/],endToken:[/\`/],ignore:!0,indent:!1,advance:!0},{name:"if",startToken:[/^if[\s]*(?=\()/,/[\s]+if[\s]*(?=\()/],endToken:[/else[\s]+/,/\{/,/\;/],indent:!0},{name:"for",startToken:[/^for[\s]*(?=\()/],endToken:[/\{/,/\;/],indent:!0},{name:"else",startToken:[/else[\s]+/],endToken:[/if/,/\{/,/\;/,c],indent:!0},{name:"bracket",startToken:[/\(/],endToken:[/\)/],indent:!0,advance:!0},{name:"array",startToken:[/\[/],endToken:[/\]/],indent:!0,advance:!0},{name:"block",startToken:[/\{/],endToken:[/\}/],indent:!0,advance:!0},{name:"var",startToken:[/var[\s]+/],endToken:[/\;/],indent:!0},{name:"case",startToken:[/^case[\s]+/],endToken:[/break[\s;]+/,/^case[\s]+/,/^default[\s]+/,/\}/],indent:!0}],m=[{name:"comment",startToken:[/\<\!\-\-/],endToken:[/\-\-\>/],ignore:!0,indent:!1,advance:!0},{name:"doctype",startToken:[/\<\!/],endToken:[c],ignore:!0,indent:!1,advance:!0},{name:"link|br|input|meta",startToken:[/\<(link|br|input|meta)/i],endToken:[/(\"[^\"]*\"|'[^']*'|[^'\">])*>/],ignore:!0,indent:!1,advance:!0},{name:"tag",startToken:[/<(\"[^\"]*\"|'[^']*'|[^'\">])*>/],endToken:[/\<\/[^\>]+\>/],indent:!0,advance:!0},{name:"tag",startToken:[/<(\"[^\"]*\"|'[^']*'|[^'\">])*/],endToken:[/\/\>/],indent:!1,advance:!0}].concat(s);return{indentCSS:n,indentJS:n,indentHTML:e}}();
var indent=function(){function n(n){if(l[n])return l[n];var e=[];l[n]=e;for(var t=0;t<m.length;t++)m[t].langs.indexOf(n.toLowerCase())!=-1&&e.push(m[t]);return e}function e(e,t){return s(e,n("js"),t)}function t(e,t){return s(e,n("css"),t)}function a(e,t){return s(e,n("html"),t)}function s(e,t,a){function s(e){y=e.cursor,u=e.rule,p.push(u),u.indent&&m(u.lineOffset),u.rules&&(A=n(u.rules))}function d(){u.indent&&(g(),0==k.matchIndex&&l()),u.rules&&(A=null),p.pop(),u=p[p.length-1]}function l(){j=0;for(var n,e=0;e<I.length;e++)n=I[e],n.open&&n.line!=b&&j++}function h(){v[b]=r(a,j)+w,b++,y=0,l()}function m(n){var e=I[I.length-1];e&&e.line==b?e.indent++:(I.push({indent:1,open:!0,line:n?b+n:b}),n<0&&l())}function g(){var n=I[I.length-1];n&&(n.open=b==n.line,--n.indent<=0&&I.pop())}for(var u,k,f,T=e.split(/[\r]?\n/gi),x=T.length,v=[],I=[],p=[],j=0,b=0,y=0,A=null;b<x;){var w=T[b].trim(),z=o(w)+"\r\n";if(f=i(z,A||t,y),p.length)if(k=c(z,u,y),k.matchIndex==-1){if(u.ignore){h();continue}}else if(u.ignore||f.matchIndex==-1||k.matchIndex<=f.matchIndex){d(),y=k.cursor;continue}f.matchIndex!=-1?s(f):h()}return v.join("\r\n")}function r(n,e){return new Array(e+1).join(n)}function o(n){return n.replace(/\\(u[0-9A-Za-z]{4}|u\{[0-9A-Za-z]{1,6}]\}|x[0-9A-Za-z]{2}|.)/g,"0")}function i(n,e,t){n=n.substring(t,n.length);for(var a,s,r,o=null,i=n.length,c=0;c<e.length;c++)r=e[c],s=d(n,r.startToken,r),s.matchIndex!=-1&&s.matchIndex<i&&(!r.head||0==t)&&(i=s.matchIndex,a=s,o=r);return{rule:o,matchIndex:o?i+t:-1,cursor:o?i+t+a.matchLength:-1}}function c(n,e,t){n=n.substr(t,n.length);var a=d(n,e.endToken,e),s=e.advance?a.matchIndex+a.matchLength:a.matchIndex;return{matchIndex:a.matchIndex==-1?-1:a.matchIndex+t,cursor:s==-1?-1:s+t}}function d(n,e,t){for(var a,s=-1,r=0,o=0;o<e.length;o++)if(a=e[o],"function"==typeof a){var i=a(n,t);s=i.matchIndex,r=i.length}else if(s=n.search(a),s!=-1){r=n.match(a)[0].length;break}return{matchIndex:s,matchLength:r,cursor:s+r,patternIndex:o}}var l={},h=/\r*\n/,m=[{langs:"html",name:"comment",startToken:[/\<\!\-\-/],endToken:[/\-\-\>/],ignore:!0,advance:!0},{langs:"html",name:"doctype",startToken:[/\<\!/],endToken:[h],ignore:!0,advance:!0},{langs:"html",name:"link|br|input|meta",startToken:[/\<(link|br|input|meta)/i],endToken:[/>/],advance:!0},{langs:"html",name:"mode switch js",startToken:[function(n,e){var t=/<script[\s>].*/i,a=/<\/script>/i,s=t.exec(n),r=a.exec(n);return s&&(!r||r.index<s.index)?{matchIndex:s.index,length:s[0].length}:{matchIndex:-1}}],endToken:[/<\/script>/i],rules:"js",advance:!0,indent:!0},{langs:"html",name:"mode switch css",startToken:[function(n,e){var t=/<style[\s>].*/i,a=/<\/style>/i,s=t.exec(n),r=a.exec(n);return s&&(!r||r.index<s.index)?{matchIndex:s.index,length:s[0].length}:{matchIndex:-1}}],endToken:[/<\/style>/i],rules:"css",advance:!0,indent:!0},{langs:"html",name:"close-tag",startToken:[/<\/[A-Za-z0-9\-]+>/],endToken:[/./],indent:!0},{langs:"html",name:"tag attr",startToken:[/<[A-Za-z0-9\-]+/],endToken:[/>/],indent:!0},{langs:"html",name:"tag",startToken:[/>/],endToken:[/<\/[A-Za-z0-9\-]+>/],indent:!0,advance:!0},{langs:"js",name:"line comment",startToken:[/\/\//],endToken:[h],ignore:!0},{langs:"js css",name:"block comment",startToken:[/\/\*/],endToken:[/\*\//],ignore:!0},{langs:"js",name:"regex",startToken:[function(n,e){var t=/[(,=:[!&|?{};][\s]*\/[^\/]|^[\s]*\/[^\/]/,a=n.search(t);if(a!=-1){a=n.indexOf("/",a);var s=n.substring(a+1),r=d(s,e.endToken,e);if(r.matchIndex!=-1){s=s.substring(0,r.matchIndex);try{return new RegExp(s),{matchIndex:a,length:1}}catch(o){return{matchIndex:-1}}}}return{matchIndex:-1}}],endToken:[function(n,e){for(var t=0,a=n.indexOf("/");a!=-1;)try{new RegExp(n.substring(0,a));break}catch(s){a=n.indexOf("/",t),t=a+1}return{matchIndex:a,length:a==-1?0:1}}],ignore:!0,advance:!0},{langs:"js css html",name:"string",startToken:[/\"/],endToken:[/\"/,h],ignore:!0,advance:!0},{langs:"js css html",name:"string",startToken:[/\'/],endToken:[/\'/,h],ignore:!0,advance:!0},{langs:"js css html",name:"string",startToken:[/\`/],endToken:[/\`/],ignore:!0,advance:!0},{langs:"js",name:"if",startToken:[/^if[\s]*(?=\()/,/[\s]+if[\s]*(?=\()/],endToken:[/else[\s]+/,/\{/,/;/],indent:!0},{langs:"js",name:"for",startToken:[/^for[\s]*(?=\()/],endToken:[/\{/,/;/],indent:!0},{langs:"js",name:"else",startToken:[/else[\s]+/],endToken:[/if/,/\{/,/;/,h],indent:!0},{langs:"js css",name:"bracket",startToken:[/\([\s]*(var)?/],endToken:[/\)/],indent:!0,advance:!0},{langs:"js",name:"dot chain",startToken:[/^\../],endToken:[/;/,h],indent:!0,head:!0,lineOffset:-1},{langs:"js",name:"dot chain",startToken:[/\.\s*$/],endToken:[function(n,e){return{matchIndex:n.length?1:-1,length:n.length?0:1}}],indent:!0},{langs:"js css",name:"array",startToken:[/\[/],endToken:[/]/],indent:!0,advance:!0},{langs:"js css",name:"block",startToken:[/\{/],endToken:[/}/],indent:!0,advance:!0},{langs:"js",name:"var",startToken:[/var[\s]+/],endToken:[/;/],indent:!0},{langs:"js",name:"case",startToken:[/^case[\s]+/],endToken:[/break[\s;]+/,/^case[\s]+/,/^default[\s]+/,/}/],indent:!0}];return{indentCSS:t,indentJS:e,indentHTML:a}}();
return indent;
}));
{
"name": "indent.js",
"version": "0.1.2",
"version": "0.1.3",
"description": "Fast minimalistic pure indentation of JavaScript, CSS, and HTML.",

@@ -5,0 +5,0 @@ "main": "lib/indent.js",

@@ -45,5 +45,25 @@ # indent.js

---
This project is great for code editors and file watchers. I'd love to hear about how your projects use indent.js.
##Projects with indent.js:
1. [JsWriter - Web-base JavaScript IDE](https://jswriter.com/)
Developers
---
ISupport for other languages would be nice, and greatly welcomed!
Unfortunately, I do not know these languages well enough to construct rules for them.
###Languages still not supported:
1. TypeScript
2. CoffeeScript
3. Pug
4. Less/Sass
###Getting the project
1. Run `npm install` to install dependencies

@@ -50,0 +70,0 @@ 2. Run `npm test` to run tests in `tests` folder

var indent = (function() {
var rulesCache = {};
function filterRules(language) {
if (rulesCache[language])
return rulesCache[language];
var ret = [];
rulesCache[language] = ret;
for (var i=0; i<masterRules.length; i++) {
if (masterRules[i].langs.indexOf(language.toLowerCase()) != -1)
ret.push(masterRules[i]);
}
return ret;
}
var NEW_LINE_REGEX = /\r*\n/;
var jsRules = [
/**
* indent - whether rule will cause indent
* ignore - ignore rule matching as long as is last active rule, e.g. string, comments
* advance - greedily consume endTokens when rule ends
* head - match at beginning of line only
* langs - used to filter by language later
* lineOffset - added to the line field when rule is applied
*
* Always keep NEW_LINE_REGEX endToken as last element,
* as otherwise it will be matched first, and subsequent ones may be ignored
* and skipped permanently by other rules.
*/
var masterRules = [
{
langs: "html",
name: "comment",
startToken: [/\<\!\-\-/],
endToken: [/\-\-\>/],
ignore: true,
advance: true
},
{
langs: "html",
name: "doctype",
startToken: [/\<\!/],
endToken: [NEW_LINE_REGEX],
ignore: true,
advance: true
},
{
langs: "html",
name: "link|br|input|meta",
startToken: [/\<(link|br|input|meta)/i],
endToken: [/>/],
advance: true
},
{
langs: "html",
name: "mode switch js",
startToken: [function (string, rule) {
var start = /<script[\s>].*/i;
var end = /<\/script>/i;
var startMatch = start.exec(string);
var endMatch = end.exec(string);
if (startMatch && (!endMatch || endMatch.index < startMatch.index)) {
return {
matchIndex: startMatch.index,
length: startMatch[0].length
};
}
return {matchIndex: -1};
}],
endToken: [/<\/script>/i],
rules: "js",
advance: true,
indent: true
},
{
langs: "html",
name: "mode switch css",
startToken: [function (string, rule) {
var start = /<style[\s>].*/i;
var end = /<\/style>/i;
var startMatch = start.exec(string);
var endMatch = end.exec(string);
if (startMatch && (!endMatch || endMatch.index < startMatch.index)) {
return {
matchIndex: startMatch.index,
length: startMatch[0].length
};
}
return {matchIndex: -1};
}],
endToken: [/<\/style>/i],
rules: "css",
advance: true,
indent: true
},
{
langs: "html",
name: "close-tag",
startToken: [/<\/[A-Za-z0-9\-]+>/],
endToken: [/./],
indent: true
},
{
langs: "html",
name: "tag attr",
startToken: [/<[A-Za-z0-9\-]+/],
endToken: [/>/],
indent: true
},
{
langs: "html",
name: "tag",
startToken: [/>/],
endToken: [/<\/[A-Za-z0-9\-]+>/],
indent: true,
advance: true
},
{
langs: "js",
name: "line comment",
startToken: [/\/\//],
endToken: [NEW_LINE_REGEX],
ignore: true,
indent: false
ignore: true
},
{
langs: "js css",
name: "block comment",
startToken: [/\/\*/],
endToken: [/\*\//],
ignore: true,
indent: false
ignore: true
},
{
langs: "js",
name: "regex",

@@ -62,6 +179,6 @@ startToken: [function (string, rule) {

ignore: true,
indent: false,
advance: true
},
{
langs: "js css html",
name: "string",

@@ -71,6 +188,6 @@ startToken: [/\"/],

ignore: true,
indent: false,
advance: true
},
{
langs: "js css html",
name: "string",

@@ -80,6 +197,6 @@ startToken: [/\'/],

ignore: true,
indent: false,
advance: true
},
{
langs: "js css html",
name: "string",

@@ -89,26 +206,29 @@ startToken: [/\`/],

ignore: true,
indent: false,
advance: true
},
{
langs: "js",
name: "if",
startToken: [/^if[\s]*(?=\()/, /[\s]+if[\s]*(?=\()/],
endToken: [/else[\s]+/, /\{/, /\;/],
endToken: [/else[\s]+/, /\{/, /;/],
indent: true
},
{
langs: "js",
name: "for",
startToken: [/^for[\s]*(?=\()/],
endToken: [/\{/, /\;/],
endToken: [/\{/, /;/],
indent: true
},
{
langs: "js",
name: "else",
startToken: [/else[\s]+/],
endToken: [/if/, /\{/, /\;/, NEW_LINE_REGEX],
endToken: [/if/, /\{/, /;/, NEW_LINE_REGEX],
indent: true
},
{
langs: "js css",
name: "bracket",
startToken: [/\(/],
startToken: [/\([\s]*(var)?/],
endToken: [/\)/],

@@ -119,5 +239,27 @@ indent: true,

{
langs: "js",
name: "dot chain",
startToken: [/^\../],
endToken: [/;/, NEW_LINE_REGEX],
indent: true,
head: true,
lineOffset: -1
},
{
langs: "js",
name: "dot chain",
startToken: [/\.\s*$/],
endToken: [function (string, rule) {
return {
matchIndex: string.length ? 1 : -1,
length: string.length ? 0 : 1
};
}],
indent: true
},
{
langs: "js css",
name: "array",
startToken: [/\[/],
endToken: [/\]/],
endToken: [/]/],
indent: true,

@@ -127,5 +269,6 @@ advance: true

{
langs: "js css",
name: "block",
startToken: [/\{/],
endToken: [/\}/],
endToken: [/}/],
indent: true,

@@ -135,11 +278,13 @@ advance: true

{
langs: "js",
name: "var",
startToken: [/var[\s]+/],
endToken: [/\;/],
endToken: [/;/],
indent: true
},
{
langs: "js",
name: "case",
startToken: [/^case[\s]+/],
endToken: [/break[\s;]+/, /^case[\s]+/, /^default[\s]+/, /\}/],
endToken: [/break[\s;]+/, /^case[\s]+/, /^default[\s]+/, /}/],
indent: true

@@ -149,45 +294,4 @@ }

var htmlRules = [
{
name: "comment",
startToken: [/\<\!\-\-/],
endToken: [/\-\-\>/],
ignore: true,
indent: false,
advance: true
},
{
name: "doctype",
startToken: [/\<\!/],
endToken: [NEW_LINE_REGEX],
ignore: true,
indent: false,
advance: true
},
{
name: "link|br|input|meta",
startToken: [/\<(link|br|input|meta)/i],
endToken: [/(\"[^\"]*\"|'[^']*'|[^'\">])*>/],
ignore: true,
indent: false,
advance: true
},
{
name: "tag",
startToken: [/<(\"[^\"]*\"|'[^']*'|[^'\">])*>/],
endToken: [/\<\/[^\>]+\>/],
indent: true,
advance: true
},
{
name: "tag",
startToken: [/<(\"[^\"]*\"|'[^']*'|[^'\">])*/],
endToken: [/\/\>/],
indent: false,
advance: true
}
].concat(jsRules);
return {
indentCSS: indentJS,
indentCSS: indentCSS,
indentJS: indentJS,

@@ -198,10 +302,14 @@ indentHTML: indentHTML

function indentJS(code, indentString) {
return indent(code, jsRules, indentString);
return indent(code, filterRules('js'), indentString);
}
function indentCSS(code, indentString) {
return indent(code, filterRules('css'), indentString);
}
function indentHTML(code, indentString) {
return indent(code, htmlRules, indentString);
return indent(code, filterRules('html'), indentString);
}
function indent(code, rules, indentation) {
function indent(code, baseRules, indentation) {
var lines = code.split(/[\r]?\n/gi);

@@ -217,2 +325,3 @@ var lineCount = lines.length;

var matchEnd, matchStart;
var modeRules = null;

@@ -223,3 +332,3 @@ while (l < lineCount) {

matchStart = matchStartRule(lineToMatch, rules, pos);
matchStart = matchStartRule(lineToMatch, modeRules || baseRules, pos);

@@ -236,10 +345,4 @@ if (activeRules.length) {

else if (lastRule.ignore || matchStart.matchIndex == -1 || matchEnd.matchIndex <= matchStart.matchIndex) {
if (lastRule.indent) {
consumeIndentation();
if (matchEnd.matchIndex == 0) {
calculateIndents();
}
}
removeLastRule();
pos = matchEnd.cursor;
removeLastRule();
continue; // Repeat process for matching line start/end

@@ -264,7 +367,20 @@ }

activeRules.push(lastRule);
if (lastRule.indent)
incrementIndentation();
if (lastRule.indent) {
incrementIndentation(lastRule.lineOffset);
}
if (lastRule.rules) {
modeRules = filterRules(lastRule.rules);
}
}
function removeLastRule() {
if (lastRule.indent) {
consumeIndentation();
if (matchEnd.matchIndex == 0) {
calculateIndents();
}
}
if (lastRule.rules) {
modeRules = null;
}
activeRules.pop();

@@ -290,3 +406,3 @@ lastRule = activeRules[activeRules.length - 1];

function incrementIndentation() {
function incrementIndentation(lineOffset) {
var matched = indentBuffer[indentBuffer.length - 1];

@@ -300,4 +416,5 @@ if (matched && matched.line == l) {

open: true,
line: l
line: lineOffset ? l + lineOffset : l
});
if (lineOffset < 0) calculateIndents();
}

@@ -334,3 +451,4 @@ }

match = searchAny(string, rule.startToken, rule);
if (match.matchIndex != -1 && match.matchIndex < minIndex) {
if (match.matchIndex != -1 && match.matchIndex < minIndex
&& (!rule.head || index == 0)) {
minIndex = match.matchIndex;

@@ -337,0 +455,0 @@ minMatch = match;

describe('html.spec.js', function() {
it('should handle full html file', function() {
it('should handle basic tags', function() {
var input = hereDoc(function() {/*!
<!DOCTYPE html>
<html>
<!--
-->
<head>
<!-- if you feel an urge to move this to bootstrap or something, you're most welcome -->
<meta charset="utf-8">
<title>Online JavaScript beautifier</title>
<link rel="icon" href="web/favicon.png" type="image/png">
<script src="web/third-party/codemirror/mode/javascript/javascript.js"></script>
<style>
body {
background: #eee;
color: #333;
}
a.self {
font-weight: bold;
border-bottom: 1px solid #aaa
}
p, select, label, .blurb, a.turn-off-codemirror {
font:13px/1.231 arial, sans-serif;
*font-size:small;
}
a.turn-off-codemirror {
margin-left: 25px;
}
button.submit {
width: 100%;
padding: 10px 0;
}
button.submit em {
}
select {
width: 220px;
}
table#options {
float: right;
}
.col-6 {
width: 50%;
float: left;
}
#about p {
margin: 0 6px 6px 0;
}
.uses li.sep {
margin-top: 8px;
}
</style>
<script>
var the = {
use_codemirror: (!window.location.href.match(/without-codemirror/)),
beautify_in_progress: false,
editor: null // codemirror editor
};
function run_tests() {
var st = new SanityTest();
Urlencoded.run_tests(st);
var results = st.results_raw()
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/ /g, '&nbsp;');
$('#testresults').html(results).show();
}
function read_settings_from_cookie() {
$('#detect-packers').prop('checked', $.cookie('detect-packers') !== 'off');
$('#break-chained-methods').prop('checked', $.cookie('break-chained-methods') === 'on');
$('#space-before-conditional').prop('checked', $.cookie('space-before-conditional') !== 'off');
$('#end-with-newline').prop('checked', $.cookie('end-with-newline') === 'on');
$('#comma-first').prop('checked', $.cookie('comma-first') === 'on');
$('#e4x').prop('checked', $.cookie('e4x') === 'on');
}
comment = '',
unpacked = '',
found = false;
do {
if (/^\s*\//.test(source)) {
source = source.substr(comment.length).replace(/^\s+/, '');
trailing_comments += comment + "\n";
} else if (/^\s*\/\//.test(source)) {
comment = source.match(/^\s*\//)[0];
source = source.substr(comment.length).replace(/^\s+/, '');
}
} while (found);
return trailing_comments + source;
}
</script>
</head>
<body>
<div id="about">
<p>
<a class="self" href="./">Beautify, unpack or deobfuscate JavaScript and HTML, make JSON/JSONP readable, etc.</a>
</p>
<p>
All of the source code is completely free and open, available on <a href="https://github.com/beautify-web/js-beautify">GitHub</a> under MIT licence,
<br>and we have a command-line version, python library and a <a href="https://npmjs.org/package/js-beautify">node package</a> as well.
</p>
</div>
<table id="options">
<tr>
<td>
<select name="tabsize" id="tabsize">
<option value="1">Indent with a tab character</option>
<option value="2">Indent with 2 spaces</option>
</select>
</td>
<td>
<input class="checkbox" type="checkbox" id="break-chained-methods">
<label for="break-chained-methods">Break lines on chained methods?</label>
<br>
<input class="checkbox" type="checkbox" id="unescape-strings">
<label for="unescape-strings">Unescape printable chars encoded as \xNN or \uNNNN?</label>
<br>
<input class="checkbox" type="checkbox" id="indent-inner-html">
<label for="indent-inner-html">Indent &lt;head&gt; and &lt;body&gt; sections?</label>
<br><a href="?without-codemirror" class="turn-off-codemirror">Use a simple textarea for code input?</a>
</td>
</tr>
</table>
<script>
var _gaq = [
['_trackPageview']
];
(function (d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src = '//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
}(document, 'script'));
</script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
*/
});
var expected = hereDoc(function() {/*!
<!DOCTYPE html>
<html>
<!--
-->
<head>
<!-- if you feel an urge to move this to bootstrap or something, you're most welcome -->
<meta charset="utf-8">
<title>Online JavaScript beautifier</title>
<link rel="icon" href="web/favicon.png" type="image/png">
<script src="web/third-party/codemirror/mode/javascript/javascript.js"></script>
<style>
body {
background: #eee;
color: #333;
}
a.self {
font-weight: bold;
border-bottom: 1px solid #aaa
}
p, select, label, .blurb, a.turn-off-codemirror {
font:13px/1.231 arial, sans-serif;
*font-size:small;
}
a.turn-off-codemirror {
margin-left: 25px;
}
button.submit {
width: 100%;
padding: 10px 0;
}
button.submit em {
}
select {
width: 220px;
}
table#options {
float: right;
}
.col-6 {
width: 50%;
float: left;
}
#about p {
margin: 0 6px 6px 0;
}
.uses li.sep {
margin-top: 8px;
}
</style>
<script>
var the = {
use_codemirror: (!window.location.href.match(/without-codemirror/)),
beautify_in_progress: false,
editor: null // codemirror editor
};
function run_tests() {
var st = new SanityTest();
Urlencoded.run_tests(st);
var results = st.results_raw()
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/ /g, '&nbsp;');
$('#testresults').html(results).show();
}
function read_settings_from_cookie() {
$('#detect-packers').prop('checked', $.cookie('detect-packers') !== 'off');
$('#break-chained-methods').prop('checked', $.cookie('break-chained-methods') === 'on');
$('#space-before-conditional').prop('checked', $.cookie('space-before-conditional') !== 'off');
$('#end-with-newline').prop('checked', $.cookie('end-with-newline') === 'on');
$('#comma-first').prop('checked', $.cookie('comma-first') === 'on');
$('#e4x').prop('checked', $.cookie('e4x') === 'on');
}
comment = '',
unpacked = '',
found = false;
do {
if (/^\s*\//.test(source)) {
source = source.substr(comment.length).replace(/^\s+/, '');
trailing_comments += comment + "\n";
} else if (/^\s*\/\//.test(source)) {
comment = source.match(/^\s*\//)[0];
source = source.substr(comment.length).replace(/^\s+/, '');
}
} while (found);
return trailing_comments + source;
}
</script>
</head>
<body>
<div id="about">
<p>
<a class="self" href="./">Beautify, unpack or deobfuscate JavaScript and HTML, make JSON/JSONP readable, etc.</a>
</p>
<p>
All of the source code is completely free and open, available on <a href="https://github.com/beautify-web/js-beautify">GitHub</a> under MIT licence,
<br>and we have a command-line version, python library and a <a href="https://npmjs.org/package/js-beautify">node package</a> as well.
</p>
</div>
<table id="options">
<tr>
<td>
<select name="tabsize" id="tabsize">
<option value="1">Indent with a tab character</option>
<option value="2">Indent with 2 spaces</option>
</select>
</td>
<td>
<input class="checkbox" type="checkbox" id="break-chained-methods">
<label for="break-chained-methods">Break lines on chained methods?</label>
<br>
<input class="checkbox" type="checkbox" id="unescape-strings">
<label for="unescape-strings">Unescape printable chars encoded as \xNN or \uNNNN?</label>
<br>
<input class="checkbox" type="checkbox" id="indent-inner-html">
<label for="indent-inner-html">Indent &lt;head&gt; and &lt;body&gt; sections?</label>
<br><a href="?without-codemirror" class="turn-off-codemirror">Use a simple textarea for code input?</a>
</td>
</tr>
</table>
<script>
var _gaq = [
['_trackPageview']
];
(function (d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src = '//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
}(document, 'script'));
</script>
</body>
</html>
<body>
<script type="text/javascript" src="index.js"></script>
</body>
*/
});
var actual = indent.indentHTML(input, ' ');
expect(actual).toEqual(expected);
expect(indent.indentHTML(input, ' ')).toEqual(expected);
});
});
it('should handle wrapped attrs', function() {
var input = hereDoc(function() {/*!
<body>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1" width="100%" height="100%" viewBox="0 0 400 400"
preserveAspectRatio="xMidYMid meet"></svg>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
*/
});
var expected = hereDoc(function() {/*!
<body>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1" width="100%" height="100%" viewBox="0 0 400 400"
preserveAspectRatio="xMidYMid meet"></svg>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
*/
});
expect(indent.indentHTML(input, ' ')).toEqual(expected);
});
});

@@ -146,2 +146,52 @@ describe('statements.spec.js', function() {

});
it('should handle terminate bracket on same line', function() {
var input = hereDoc(function() {/*!
if (test) {
cool();}
else if (test) {
cool();}
*/
});
var expected = hereDoc(function() {/*!
if (test) {
cool();}
else if (test) {
cool();}
*/
});
expect(indent.indentJS(input, ' ')).toEqual(expected);
});
it('should handle single line for loop', function() {
var input = hereDoc(function() {/*!
for (var key in obj) keys.push(key);
keys.sort();
*/
});
var expected = hereDoc(function() {/*!
for (var key in obj) keys.push(key);
keys.sort();
*/
});
expect(indent.indentJS(input, ' ')).toEqual(expected);
});
it('should handle conditionals', function() {
var input = hereDoc(function() {/*!
forEach(parts, function(value){
text += fn ? fn(date, $locale.DATETIME_FORMATS)
: value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
});
*/
});
var expected = hereDoc(function() {/*!
forEach(parts, function(value){
text += fn ? fn(date, $locale.DATETIME_FORMATS)
: value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
});
*/
});
expect(indent.indentJS(input, ' ')).toEqual(expected);
});
});
var fs = require('fs');
var indent = require('./../src/indent.js');
var indent = require('./../lib/indent.js');
var self = this;

@@ -9,4 +9,4 @@

console.log(
indent.indent.indentJS(data.toString(), ' ')
indent.indentJS(data.toString(), ' ')
);
});
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