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

beauty-amp-core2

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

beauty-amp-core2 - npm Package Compare versions

Comparing version 0.4.5 to 0.4.6

src/varReplacer.js

55

beauty-amp-core.js

@@ -38,34 +38,21 @@ const path = require('path');

cutBlanksAtStartEnd(lines, lineDelimeter) {
const delimeter = lineDelimeter !== undefined ? lineDelimeter : '\n';
let text = lines.join(delimeter);
text = text.trim();
const newLines = text.split(delimeter);
return newLines;
cutBlanksAtStartEnd(lines, delimeter = '\n') {
return lines.join(delimeter).trim().split(delimeter);
},
getCodeBlocks(lines, lineDelimeter, settings, editorSetup) {
const delimeter = lineDelimeter !== undefined ? lineDelimeter : '\n';
getCodeBlocks(lines, delimeter = '\n', settings, editorSetup) {
const fullText = lines.join(delimeter);
let blocks = [];
const blockRegEx = /%%\[.*?\]%%/gis;
// get matches as code blocks:
let ampBlocks = fullText.match(blockRegEx);
// logger.log('AMP blocks: ', ampBlocks);
// split by block regex:
let htmlBlocks = fullText.split(blockRegEx);
// logger.log('HTML blocks: ', htmlBlocks);
// merge both arrays into one final using the CodeBlocks:
for (let i = 0; i < htmlBlocks.length - 1; i++) {
blocks.push(new CodeBlock(htmlBlocks[i].trim(), false, delimeter, settings, editorSetup, logger));
blocks.push(new CodeBlock(ampBlocks[i].trim(), true, delimeter, settings, editorSetup, logger));
}
blocks.push(new CodeBlock(htmlBlocks[htmlBlocks.length - 1].trim(), false, delimeter, settings, editorSetup, logger));
const ampBlocks = fullText.match(blockRegEx) || [];
const htmlBlocks = fullText.split(blockRegEx);
const blocks = htmlBlocks.flatMap((htmlBlock, i) => {
const blocks = [new CodeBlock(htmlBlock.trim(), false, delimeter, settings, editorSetup, logger)];
if (ampBlocks[i]) {
blocks.push(new CodeBlock(ampBlocks[i].trim(), true, delimeter, settings, editorSetup, logger));
}
return blocks;
});
return blocks;

@@ -170,3 +157,2 @@ },

// run Prettier on HTML:
if (includeHtml) {

@@ -258,11 +244,8 @@ lines = await this.processHtml(lines);

function lookForSetupFile() {
try {
const path = require('path');
const setupPath = path.resolve(process.cwd(), './.beautyamp.json');
let rawdata = fs.readFileSync(setupPath);
const setupPath = path.resolve(process.cwd(), './.beautyamp.json');
if (fs.existsSync(setupPath)) {
const rawdata = fs.readFileSync(setupPath);
return JSON.parse(rawdata);
} catch(err) {
return false;
}
return false;
}
{
"name": "beauty-amp-core2",
"version": "0.4.5",
"version": "0.4.6",
"description": "Beautify (prettify) AMPscript for Marketing Cloud - prettifying library only. Version for further support.",

@@ -23,3 +23,3 @@ "publisher": "fib3",

},
"homepage": "https://github.com/FiB3/beautyAmpCore2",
"homepage": "https://fib3.vercel.app/",
"devDependencies": {

@@ -26,0 +26,0 @@ "jest": "^29.7.0"

@@ -5,3 +5,3 @@ # Beauty AMP Core 2

Includes HTML formatting using Prettier.
Duplicated to ensure support of the original library.
Duplicated to continue support of the original library.

@@ -16,8 +16,17 @@ ## Installation

This module can format AMPscript code either as an array (of lines) or as a string.
The output type matches the input type.
### beautify(lines)
Format code. Lines are broken on `"\n"`. Is Async.
`lines`: __Array|String__ - text of your code
`includeHtml` __Boolen=true__ Include the HTML in beautifying (e.g. if HTML code is not format-able).
`return`: __{Array|String}__ Formatted code. Array or string based on the initial input.
`throws`: Syntax Error if HTML cannot be formatted.
#### Array input:
``` javascript
const beautifier = require('beauty-amp-core2');
beautifier.setup(undefined, undefined, {
loggerOn: false
});
beautifier.setup(); // setup is explained later

@@ -36,12 +45,25 @@ let lines = [`<h1>My Test Case:</h1>`,

### beautify(lines)
Format code. Lines are broken on `"\n"`.
`lines`: __Array|String__ - text of your code
`includeHtml` __Boolen=true__ Include the HTML in beautifying (e.g. if HTML code is not format-able).
`return`: __{Array|String}__ Formatted code. Array or string based on the initial input.
`throws`: Syntax Error if HTML cannot be formatted.
#### String input:
``` javascript
const beautifier = require('beauty-amp-core2');
beautifier.setup(); // setup is explained later
let lines = `<h1>My Test Case:</h1>
%%[ VAR @lang
If (@lang == 'EN') then Output("Hello World!")
Else
Output("Ciao!")
endif
]%%`;
const result = await beautifier.beautify(lines);
console.log(result); // returns code as a string
```
## Setup
You can set the extension as following.
You can set the extension either in code or using a file.
### In code:
``` javascript

@@ -61,10 +83,7 @@ const ampscript = {

const logs = {
loggerOn: false // <= disable logging
};
beautifier.setup(ampscript, editor, logs);
beautifier.setup(ampscript, editor);
```
A new experimental feature allows to use a setup file in your project's folder: `.beautyamp.json`:
### Using setup file:
Or use a setup file in your project's folder (project root). Name `.beautyamp.json`:

@@ -85,2 +104,7 @@ ```json

}
```
You still need to call the `setup()`:
```javascript
beautifier.setup();
```
const _ = require('lodash');
const VarReplacer = require('./varReplacer');
const formatters = require('./formatters');

@@ -8,100 +9,101 @@

module.exports = class CodeBlock {
constructor(lines, isAmp, delimeter, setup, editorSetup, loggerRef) {
logger = loggerRef;
this.delimeter = delimeter === undefined ? '\n' : delimeter;
this.indentator = editorSetup.insertSpaces ? ' '.repeat(editorSetup.tabSize) : '\t';
logger.log(`Indentation Sign: "${this.indentator}". Use Spaces: ${editorSetup.insertSpaces}, width: ${editorSetup.tabSize}`);
// this.indentator = indentationSign === undefined ? '\t' : indentationSign;
constructor(lines, isAmp, delimeter = '\n', setup = {}, { insertSpaces, tabSize } = {}, loggerRef = { log: () => {} }) {
logger = loggerRef;
logger.log(`=== CodeBlock() ===`);
this.delimeter = delimeter;
this.indentator = insertSpaces ? ' '.repeat(tabSize) : '\t';
logger.log(`Indentation Sign: "${this.indentator}". Use Spaces: ${insertSpaces}, width: ${tabSize}`);
this.indentMarker = '=>';
this.pureLines = lines;
this.pureLines = lines;
this.lines = lines;
// following two cannot be true at the same time:
this.isAmp = isAmp; // any %%[ ]%% block
this.isOutputAmp = false; // any %%= =%% block
this.isOneliner = false; // defaults
this.nestLevel = 0; // defaults
this.nestModifier = 0; // is this (one-line) block increasing/decreasing the nest level?
// logger.log('setup: ', setup);
this.capitalizeSet = setup.capitalizeSet;
this.capitalizeVar = setup.capitalizeVar;
this.capitalizeAndOrNot = setup.capitalizeAndOrNot;
this.capitalizeIfFor = setup.capitalizeIfFor;
this.maxParametersPerLine = typeof setup.maxParametersPerLine === 'number' ? setup.maxParametersPerLine : 20;
// start processing:
this.isAmp = isAmp;
this.isOutputAmp = false;
this.isOneliner = false;
this.nestLevel = 0;
this.nestModifier = 0;
const { capitalizeSet, capitalizeVar, capitalizeAndOrNot, capitalizeIfFor, maxParametersPerLine = 20 } = setup;
this.capitalizeSet = capitalizeSet;
this.capitalizeVar = capitalizeVar;
this.capitalizeAndOrNot = capitalizeAndOrNot;
this.capitalizeIfFor = capitalizeIfFor;
this.maxParametersPerLine = maxParametersPerLine;
this.replacer = new VarReplacer(logger);
if (this.isAmp) {
this.lines = this.replacer.hideVars(this.lines);
this.makeOneLiner();
this.checkForOneliners();
if (this.isOneliner) {
// oneliner:
this.formatOneLiner();
} else {
// for multi-line blocks:
this.createNewLines(); // makes the one-liner into a list again!
const lines = typeof this.lines === 'string' ? [this.lines] : this.lines;
lines.forEach((line, i, lines) => {
let lineTemp = line;
lineTemp = this.formatAssignment(lineTemp);
lineTemp = this.formatVarDeclaration(lineTemp, i);
lineTemp = this.formatElseAndEndifLine(lineTemp, i);
logger.log(`formatElseAndEndifLine() => `, lineTemp);
lineTemp = this.formatForDeclaration(lineTemp, i);
lineTemp = this.formatForNext(lineTemp, i);
lineTemp = this.formatMethodLine(lineTemp, i);
lineTemp = this.runStatements(lineTemp, i);
lines[i] = lineTemp;
}, this);
this.createNewLines();
const codeLines = typeof this.lines === 'string' ? [this.lines] : this.lines;
this.lines = codeLines.map((line, i) => {
line = this.formatAssignment(line);
line = this.formatVarDeclaration(line, i);
line = this.formatElseAndEndifLine(line, i);
logger.log(`formatElseAndEndifLine() => `, line);
line = this.formatForDeclaration(line, i);
line = this.formatForNext(line, i);
line = this.formatMethodLine(line, i);
return this.runStatements(line, i);
});
}
} else {
// checks on non-AMP-blocks (HTML/output AMP):
this.checkForOutputAmpBlock();
}
logger.log(`=== CodeBlock() END ===`);
}
formatForDeclaration(line, i) {
/**
* Format FOR declaration line (main to call).
* @param {string} line
* @param {*} i
* @returns {string}
*/
formatForDeclaration(line) {
const forDeclaration = /(FOR)\s+(.*)\s+(DO)/gi;
let _this = this;
if (forDeclaration.test(line)) {
return line.replace(forDeclaration, function (match, p1, p2, p3) {
return _this.formatFor(p1, p2, p3);
});
return line.replace(forDeclaration, (match, p1, p2, p3) => this.formatFor(p1, p2, p3));
}
return line;
}
/**
* Format FOR iteration line.
* @param {string} forWord
* @param {string} iterator
* @param {string} doWord
* @returns {string}
*/
formatFor(forWord, iterator, doWord) {
if (this.capitalizeIfFor) {
forWord = forWord.toUpperCase();
doWord = doWord.toUpperCase();
} else {
forWord = forWord.toLowerCase();
doWord = doWord.toLowerCase();
}
// TODO: format the iterator:
forWord = this.capitalizeIfFor ? forWord.toUpperCase() : forWord.toLowerCase();
doWord = this.capitalizeIfFor ? doWord.toUpperCase() : doWord.toLowerCase();
iterator = this.formatIterationDeclaration(iterator);
return `${forWord} ${iterator} ${doWord}`;
}
/**
* Format for iteration declaration line.
* @param {string} iterator line of code
* @returns {string}
*/
formatIterationDeclaration(iterator) {
const declaration = /(.*)[\t\ ]+(to)[\t\ ]+(.*)/gi;
let _this = this;
if (declaration.test(iterator)) {
return iterator.replace(declaration, function (match, p1, p2, p3) {
const toWord = _this.capitalizeIfFor ? p2.toUpperCase() : p2.toLowerCase();
return _this.formatFor(p1, toWord, p3);
return iterator.replace(declaration, (match, p1, p2, p3) => {
logger.log(`formatIterationDeclaration(): ${match}, ${p1}, ${p2}, ${p3}.`);
const toWord = this.capitalizeIfFor ? p2.toUpperCase() : p2.toLowerCase();
return `${p1} ${toWord} ${p3}`;
});

@@ -112,18 +114,16 @@ }

formatForNext(line, i) {
/**
* Format NEXT iteration line.
* @param {string} line
* @param {*} i
* @returns {string}
*/
formatForNext(line) {
const forCounterCheck = /((NEXT)[\t\ ]+(\S+)|(NEXT))/gi;
logger.log(`For-Next-start`);
let _this = this;
if (forCounterCheck.test(line)) {
logger.log(`..."${line}"`);
try {
return line.replace(forCounterCheck, function (match, p1, p2, p3) {
// logger.log('====>', match, p1, p2, p3);
if (p2 && p3) {
return _this.formatNextIteration(p2, p3);
} else {
return p1;
}
});
return line.replace(forCounterCheck, (match, p1, p2, p3) => p2 && p3 ? this.formatNextIteration(p2, p3) : p1);
} catch (err) {

@@ -137,17 +137,17 @@ logger.log('!ERROR:: ', err);

/**
* Format next iteration line.
* @param {string} nextKeyword next keyword itself
* @param {string} counter iterator var from the statement
* @return {string}
*/
formatNextIteration(nextKeyword, counter) {
nextKeyword = nextKeyword.trim();
logger.log(`=> NEXT: "${nextKeyword}", counter: "${counter}"`);
if (this.capitalizeIfFor) {
nextKeyword = nextKeyword.toUpperCase();
} else {
nextKeyword = nextKeyword.toLowerCase();
}
// logger.log(`=> NEXT: "${nextKeyword}"`);
nextKeyword = this.capitalizeIfFor ? nextKeyword.toUpperCase() : nextKeyword.toLowerCase();
if (typeof counter === 'string' && counter !== '') {
// TODO: finish this:
// let statement = this.formatStatement(condition);
return `${nextKeyword} ${counter}`;
} else {
// logger.log(`=> no counter`);
return `${nextKeyword}`;

@@ -157,19 +157,19 @@ }

/**
* Format variable declaration line.
* @param {string} line
* @param {*} i placeholder
* @returns
*/
formatVarDeclaration(line, i) {
const declarationCheck = /^VAR\s+(.*)/i;
let varKeyword = 'var';
if (this.capitalizeVar) {
varKeyword = 'VAR';
}
const varKeyword = this.capitalizeVar ? 'VAR' : 'var';
if (declarationCheck.test(line)) {
logger.log(`VAR: "${line}"`);
let paramsStr = line.replace(declarationCheck, '$1');
let vars = paramsStr.split(',');
let params = [];
vars.forEach((param) => {
params.push(param.trim());
});
return varKeyword + ' ' + params.join(', ');
const paramsStr = line.replace(declarationCheck, '$1');
const vars = paramsStr.split(',');
const params = vars.map(param => param.trim());
return `${varKeyword} ${params.join(', ')}`;
}

@@ -280,17 +280,2 @@ return line;

// formatElseAndEndifLine(line, i) {
// const elseOrEndifCheck = /[\t\ ]*(ENDIF|ELSE)[\t\ ]*/gi; // original
// let _this = this;
// if (elseOrEndifCheck.test(line)) {
// logger.log(`formatElseAndEndifLine("${line}"):`);
// let lineRes = line.replace(elseOrEndifCheck, function (match, p1) {
// return _this.formatElseAndEndif(p1);
// });
// logger.log(`formatElseAndEndifLine() => "${lineRes}"`);
// return lineRes;
// }
// return line;
// }
formatElseAndEndifLine(line, i) {

@@ -557,4 +542,2 @@ const elseOrEndifFunctionCheck = /[\t\ ]*(ENDIF|ELSE)[\t\ ]*(\S+\()/gi;

/**

@@ -566,28 +549,25 @@ * Get line indentation string (whitespaces).

*/
getIndentation(inBlockLineIndentation) {
// must be handled separately!
const inLineIndentation = typeof inBlockLineIndentation === 'number' ? inBlockLineIndentation : 0;
const nstLvl = this.nestLevel >= 0 ? this.nestLevel : 0; // because no block can start at minus column
// logger.log(`${this.nestLevel}, ${inLineIndentation}`);
const finalIndent = nstLvl + inLineIndentation >= 0 ? nstLvl + inLineIndentation : 0;
getIndentation(inBlockLineIndentation = 0) {
const nstLvl = Math.max(this.nestLevel, 0); // no block can start at minus column
const finalIndent = Math.max(nstLvl + inBlockLineIndentation, 0);
return this.indentator.repeat(finalIndent);
}
/**
* Make one-liner from multi-line block.
* Works with this.lines.
*/
makeOneLiner() {
const commentBreaker = /(\/\*[\s\S]*?\*\/|<!--[\s\S]*?-->)/gi;
let parts = this.lines.split(commentBreaker);
let lines = [];
// logger.log(parts);
if (typeof this.lines === 'string') {
parts.forEach((part) => {
const parts = this.lines.split(commentBreaker);
const lines = parts.map((part) => {
if (commentBreaker.test(part)) {
logger.log('skip: ', part);
return part;
} else {
let codeParts = part.split(this.delimeter);
part = codeParts.join(' ');
return part.split(this.delimeter).join(' ');
}
lines.push(part);
})
});
this.lines = lines.join(' ');

@@ -597,8 +577,2 @@ } else {

}
// if (typeof this.lines === 'string') {
// let parts = this.lines.split(this.delimeter);
// this.lines = parts.join(' ');
// } else {
// this.lines = this.lines.join(' ');
// }
}

@@ -609,3 +583,2 @@

const blockOpeners = /^(IF\s+(.*)\s+THEN|FOR\s+(.*)\s+DO)/i;
// const blockReOpeners = /(ELSEIF\s+(.*)\s+THEN|ELSE)/i; // not necessary - does not change the level
const blockClosure = /(ENDIF|NEXT[\ \t]+\@\w+|NEXT)/i;

@@ -621,7 +594,5 @@

// opening block:
// logger.log(`>> ${lineCopy}`);
finalNestChange += 1;
} else if (blockClosure.test(lineCopy)) {
// closing block:
// logger.log(`<< ${lineCopy}`);
finalNestChange -= 1;

@@ -631,3 +602,2 @@ }

}, this);
// logger.log(`block nest change: ` + finalNestChange);
return finalNestChange;

@@ -645,19 +615,13 @@ }

getMethodIndentation(line) {
// TODO: XXX
logger.log(`getMethodIndentation(${line})`);
let newLine = '';
if (line.startsWith(this.indentMarker)) {
// how many are there? Only from the beginning!!!
let i = 0;
while (line.startsWith(this.indentMarker) && i < 20) {
newLine += this.indentator; // method indent char
line = line.substring(this.indentMarker.length, line.length);
i++;
}
newLine += line;
} else {
newLine = line;
const indentMarkerLength = this.indentMarker.length;
while (line.startsWith(this.indentMarker)) {
newLine += this.indentator;
line = line.substring(indentMarkerLength);
}
logger.log(`getMethodIndentation() => ${newLine}`);
return newLine;
logger.log(`getMethodIndentation() => ${newLine + line}`);
return newLine + line;
}

@@ -739,20 +703,24 @@

/**
* Return lines from CodeBlock.
* @returns {string}
*/
returnAsLines() {
// logger.log(`=> isAmp: ${this.isAmp}, type: ${typeof this.lines}, isArray: ${Array.isArray(this.lines)}`);
if (Array.isArray(this.lines)) {
this.lines = this.lines.join(this.delimeter);
}
// logger.log(`Block - isAmp: ${this.isAmp}, isOneLine: ${this.isOneliner}, isOutputAmp: ${this.isOutputAmp}`);
if (this.isAmp && !this.isOneliner) { // if AMPscript:
this.indentAmpBlockLines();
} else if (this.isOutputAmp || this.isOneliner) { // in case of Output AMPscript %%= =%%:
// this is for one-liner output AMPscript:
// logger.log(`...oneLineIndent. ${typeof this.lines}, ${this.nestLevel}`);
this.lines = this.lines.trim();
this.lines = this.getIndentation() + this.lines;
if (this.isAmp) {
if (!this.isOneliner) {
this.indentAmpBlockLines();
} else {
this.lines = this.getIndentation() + this.lines.trim();
}
this.lines = this.replacer.showVars(this.lines);
} else if (this.isOutputAmp || this.isOneliner) {
this.lines = this.getIndentation() + this.lines.trim();
}
// this.lines = `${this.nestModifier}/${this.nestLevel} => ${this.lines}`;
return this.lines;
}
}

@@ -10,13 +10,7 @@ const _ = require('lodash');

splitParameters: function (text) {
// console.log(text);
let delimeter = ',';
let splitted = [];
let opener = ''; // char which has opened the "non-mathing group"
let closer = '';
let openers = {
"'": `'`,
'"': `"`,
'(': ')'
};
let openers = { "'": `'`, '"': `"`, '(': ')' };
let nestableOpeners = ['('];

@@ -32,11 +26,8 @@ let counted = 0;

if (ch === delimeter && opener === '') {
// SPLIT-time!
splitted.push(word);
word = '';
} else {
// console.log(`${i}: ${ch}, o:${opener}, c:${closer}, counted:${counted}`);
word += ch;
if (ch in openers && opener === '' && p_ch !== '\\') {
// open NON-SPLITtable context:
opener = ch;

@@ -46,9 +37,6 @@ closer = openers[ch];

} else if (ch === opener && nestableOpeners.includes(opener) && p_ch !== '\\') {
// console.log('===> 2');
counted++;
} else if (ch === closer && p_ch !== '\\') {
// non-splittable context:
counted--;
if (counted === 0) {
// close hte non-splittable context
opener = '';

@@ -60,2 +48,3 @@ closer = '';

});
if (word !== '') {

@@ -74,4 +63,4 @@ splitted.push(word);

*/
splitMethodParams: function (methodString) {
methodStr = methodString.trim();
splitMethodParams: function (methodStr) {
methodStr = methodStr.trim();
const parenthesisStart = methodStr.indexOf("(") + 1;

@@ -87,16 +76,9 @@ let parenthesisEnd = methodStr.length;

if ((ch === "'" || ch === '"') && p_ch !== '\\') {
if (ch === stringOpener) {
stringOpener = ''; // exiting string
} else {
stringOpener = ch; // entering string
}
stringOpener = ch === stringOpener ? '' : ch;
} else if (ch === '(') {
opened++;
} else if (ch === ')') {
opened--;
if (opened === 0) {
parenthesisEnd = i;
break;
}
} // else not needed
} else if (ch === ')' && --opened === 0) {
parenthesisEnd = i;
break;
}
}

@@ -108,5 +90,4 @@

// console.log(`${parenthesisStart}:${parenthesisEnd}: ${[methodStart, parameters, methodEnd].join('_|_')}`);
return [methodStart, parameters, methodEnd];
}
}
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