pax_global_header00006660000000000000000000000064140440267760014524gustar00rootroot0000000000000052 comment=da4cc055366ce31535e34ed8760b59f7636e2ea6 applause-2.0.4/000077500000000000000000000000001404402677600133415ustar00rootroot00000000000000applause-2.0.4/.editorconfig000066400000000000000000000002231404402677600160130ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true applause-2.0.4/.gitattributes000066400000000000000000000000231404402677600162270ustar00rootroot00000000000000* text=auto eol=lf applause-2.0.4/.github/000077500000000000000000000000001404402677600147015ustar00rootroot00000000000000applause-2.0.4/.github/workflows/000077500000000000000000000000001404402677600167365ustar00rootroot00000000000000applause-2.0.4/.github/workflows/main.yml000066400000000000000000000006641404402677600204130ustar00rootroot00000000000000name: CI on: - push - pull_request jobs: test: name: Node.js ${{ matrix.node-version }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: - 14 - 12 - 10 steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm test applause-2.0.4/.gitignore000066400000000000000000000000271404402677600153300ustar00rootroot00000000000000node_modules yarn.lock applause-2.0.4/.npmrc000066400000000000000000000000231404402677600144540ustar00rootroot00000000000000package-lock=false applause-2.0.4/CHANGELOG.md000066400000000000000000000012531404402677600151530ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. ### [2.0.3](https://github.com/outaTiME/applause/compare/v2.0.2...v2.0.3) (2021-05-03) ### Bug Fixes * ignore non-string data types on replace ([bfbaa39](https://github.com/outaTiME/applause/commit/bfbaa39ba8123b9b8ab954b7964da0a831456ab8)), closes [#20](https://github.com/outaTiME/applause/issues/20) ### 2.0.2 (2021-05-03) ### Bug Fixes * add type check before accesing String.replace ([93edf8e](https://github.com/outaTiME/applause/commit/93edf8ee3b0a36ab97797eb82061ecfd09ba97b3)) applause-2.0.4/README.md000066400000000000000000000247161404402677600146320ustar00rootroot00000000000000# Applause 👏 [![Build Status](https://img.shields.io/travis/outaTiME/applause.svg)](https://travis-ci.org/outaTiME/applause) [![Version](https://img.shields.io/npm/v/applause.svg)](https://www.npmjs.com/package/applause) ![Prerequisite](https://img.shields.io/badge/node-%3E%3D10-blue.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#) [![Twitter: outa7iME](https://img.shields.io/twitter/follow/outa7iME.svg?style=social)](https://twitter.com/outa7iME) > Pattern replacer that helps to create human-friendly replacements. **Try the [playground], where you can test every single option of applause.** ## Install First make sure you have installed the latest version of [node.js](http://nodejs.org/) (You may need to restart your computer after this step). From NPM for programmatic use: ```shell npm install applause ``` From Git: ```shell git clone git://github.com/outaTiME/applause cd applause npm link . ``` ## Usage Assuming installation via NPM, you can use `applause` in your application like this: ```javascript var fs = require('fs'); var Applause = require('applause'); var options = { patterns: [ { match: 'foo', replacement: 'bar' } ] }; var applause = Applause.create(options); var contents = '@@foo'; var result = applause.replace(contents); console.log(result.content); // bar ``` ## Options ### patterns Type: `Array` Defines the patterns that will be used to replace the content input. ### patterns.match Type: `String|RegExp` Indicates the matching expression. If the match type is `String`, a simple variable search mechanism `@@string` is used (in any other case the default regexp replacement logic is used): ```javascript { patterns: [ { match: 'foo', replacement: 'bar' // Replaces "@@foo" with "bar" } ] } ``` ### patterns.replacement or patterns.replace Type: `String|Function|Object` Indicates the replacement for match. For more information about replacement, see [String.replace]. You can specify a function as a replacement. In this case, the function will be invoked after the match has been made. The result of the function (return value) will be used as the replacement string. ```javascript { patterns: [ { match: /foo/g, replacement: function () { return 'bar'; // Replaces "foo" with "bar" } } ] } ``` Objects are also supported as replacement (a string representation of the object is created using [JSON.stringify]): ```javascript { patterns: [ { match: /foo/g, replacement: [1, 2, 3] // Replaces "foo" with string representation of the array } ] } ``` > The replacement only resolves the [special replacement patterns] when using regexp to match. ### patterns.json Type: `Object` If a `json` attribute is found in the pattern definition, the object is flattened using the [delimiter](#delimiter) concatenation and each key-value pair will be used for replacement (simple variable lookup mechanism and no regexp support). ```javascript { patterns: [ { json: { key: 'value' // Replaces "@@key" with "value" } } ] } ``` Nested objects are also supported: ```javascript { patterns: [ { json: { key: 'value', // Replaces "@@key" with "value" inner: { // Replaces "@@inner" with string representation of the "inner" object key: 'value' // Replaces "@@inner.key" with "value" } } } ] } ``` You can define functions for deferred invocations: ```javascript { patterns: [ { json: function (done) { done({ key: 'value' }); } } ] } ``` ### patterns.yaml Type: `String` If a `yaml` attribute is found in the pattern definition, it will be converted and then processed as [json](#patternsjson) attribute. ```javascript { patterns: [ { yaml: 'key: "value"' // Replaces "@@key" with "value" } ] } ``` You can define functions for deferred invocations: ```javascript { patterns: [ { yaml: function (done) { done('key: "value"'); } } ] } ``` ### patterns.cson Type: `String` If a `cson` attribute is found in the pattern definition, it will be converted and then processed as [json](#patternsjson) attribute. ```javascript { patterns: [ { cson: 'key: "value"' } ] } ``` You can define functions for deferred invocations: ```javascript { patterns: [ { cson: function (done) { done('key: "value"'); } } ] } ``` ### variables Type: `Object` This is the old way of defining patterns using a simple plain object (simple variable lookup mechanism and no regexp support). You can still use this, but for more control you should use the new way of `patterns`. ```javascript { variables: { 'key': 'value' // Replaces "@@key" with "value" } } ``` ### prefix Type: `String` Default: `@@` The prefix used for matching (avoid wrong replacements / easy way). > This only applies for simple variable lookup mechanism. ### usePrefix Type: `Boolean` Default: `true` If set to "false", the pattern is matched without the "prefix" concatenation (this is useful when you want to lookup a simple string). > This only applies for simple variable lookup mechanism. ### preservePrefix Type: `Boolean` Default: `false` If set to "true", the "prefix" is preserved in the target. > This only applies for simple variable lookup mechanism and when `patterns.replacement` is a string. ### delimiter Type: `String` Default: `.` The delimiter used to flatten when using an object as a replacement. ### preserveOrder Type: `Boolean` Default: `false` If set to "true", we preserve the order of definition of the patterns; otherwise the order will be ascending to avoid replacement problems such as "head" / "header" (regexp matches will be resolved at last). [playground]: http://outatime.github.io/applause.io/ [String.replace]: http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace [JSON.stringify]: http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify [special replacement patterns]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter ## Examples ### Basic File `src/manifest.appcache`: ``` CACHE MANIFEST # @@timestamp CACHE: favicon.ico index.html NETWORK: * ``` Node: ```javascript var fs = require('fs'); var Applause = require('applause'); var options = { patterns: [ { match: 'timestamp', replacement: Date.now() } ] }; var applause = Applause.create(options); var contents = fs.readFileSync('./src/manifest.appcache', 'utf8'); var result = applause.replace(contents); console.log(result.content); // The replaced output ``` ### Multiple matching File `src/manifest.appcache`: ``` CACHE MANIFEST # @@timestamp CACHE: favicon.ico index.html NETWORK: * ``` File `src/humans.txt`: ``` __ _ _ _/__ /./|,//_` /_//_// /_|/// //_, outaTiME v.@@version /* TEAM */ Web Developer / Graphic Designer: Ariel Oscar Falduto Site: https://www.outa.im Twitter: @outa7iME Contact: afalduto at gmail dot com From: Buenos Aires, Argentina /* SITE */ Last update: @@timestamp Standards: HTML5, CSS3, robotstxt.org, humanstxt.org Components: H5BP, Modernizr, jQuery, Bootstrap, LESS, Jade, Grunt Software: Sublime Text, Photoshop, LiveReload ``` Node: ```javascript var fs = require('fs'); var pkg = require('./package.json'); var Applause = require('applause'); var options = { patterns: [ { match: 'version', replacement: pkg.version }, { match: 'timestamp', replacement: Date.now() } ] }; var applause = Applause.create(options); var contents = fs.readFileSync('./src/manifest.appcache', 'utf8'); var result = applause.replace(contents); console.log(result.content); // The replaced output contents = fs.readFileSync('./src/humans.txt', 'utf8'); result = applause.replace(contents); console.log(result.content); // The replaced output ``` ### Cache busting File `src/index.html`: ```html ``` Node: ```javascript var fs = require('fs'); var Applause = require('applause'); var options = { patterns: [ { match: 'timestamp', replacement: Date.now() } ] }; var applause = Applause.create(options); var contents = fs.readFileSync('./src/index.html', 'utf8'); var result = applause.replace(contents); console.log(result.content); // The replaced output ``` ### Include file File `src/index.html`: ```html @@include ``` Node: ```javascript var fs = require('fs'); var Applause = require('applause'); var options = { patterns: [ { match: 'include', replacement: fs.readFileSync('./includes/content.html', 'utf8') } ] }; var applause = Applause.create(options); var contents = fs.readFileSync('./src/index.html', 'utf8'); var result = applause.replace(contents); console.log(result.content); // The replaced output ``` ### Regular expression File `src/username.txt`: ``` John Smith ``` Node: ```javascript var fs = require('fs'); var Applause = require('applause'); var options = { patterns: [ { match: /(\w+)\s(\w+)/, replacement: '$2, $1' // Replaces "John Smith" with "Smith, John" } ] }; var applause = Applause.create(options); var contents = fs.readFileSync('./username.txt', 'utf8'); var result = applause.replace(contents); console.log(result.content); // The replaced output ``` ### Lookup for `foo` instead of `@@foo` Node: ```javascript var Applause = require('applause'); var options = [ { patterns: [ { match: /foo/g, // Explicitly using a regexp replacement: 'bar' } ] }, { patterns: [ { match: 'foo', replacement: 'bar' } ], prefix: '' // Removing the prefix manually }, { patterns: [ { match: 'foo', replacement: 'bar' } ], usePrefix: false // Using the option provided } ]; options.forEach(function (option) { var applause = Applause.create(option); var contents = 'foo'; var result = applause.replace(contents); console.log(result.content); // bar }); ``` ## Related - [js-yaml](https://github.com/nodeca/js-yaml) - YAML 1.2 parser and serialize - [cson-parser](https://github.com/groupon/cson-parser) - Safe parsing of CSON files ## License MIT © [outaTiME](https://outa.im) applause-2.0.4/commitlint.config.js000066400000000000000000000001051404402677600173160ustar00rootroot00000000000000module.exports = { extends: ['@commitlint/config-conventional'] }; applause-2.0.4/index.js000066400000000000000000000001201404402677600147770ustar00rootroot00000000000000var Applause = require('./src/applause'); // Expose module.exports = Applause; applause-2.0.4/license000066400000000000000000000021131404402677600147030ustar00rootroot00000000000000MIT License Copyright (c) outaTiME (https://outa.im) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. applause-2.0.4/package.json000066400000000000000000000031141404402677600156260ustar00rootroot00000000000000{ "name": "applause", "version": "2.0.4", "description": "Human-friendly replacements.", "license": "MIT", "repository": "outaTiME/applause", "author": { "name": "outaTiME", "email": "afalduto@gmail.com", "url": "https://outa.im" }, "exports": "./index.js", "engines": { "node": ">=10" }, "scripts": { "test": "eslint . && ava", "release": "release-it" }, "files": [ "index.js", "src" ], "keywords": [ "replace", "replacement", "pattern", "patterns", "match", "text", "string", "regex", "regexp", "json", "yaml", "cson", "flatten" ], "dependencies": { "lodash": "^4.17.21", "optional-require": "^1.0.2" }, "devDependencies": { "@commitlint/cli": "^12.1.1", "@commitlint/config-conventional": "^12.1.1", "@release-it/conventional-changelog": "^2.0.1", "ava": "^3.15.0", "cz-conventional-changelog": "^3.3.0", "eslint": "^7.20.0", "eslint-config-xo": "^0.35.0", "eslint-config-xo-space": "^0.27.0", "husky": "^6.0.0", "release-it": "^14.6.1" }, "optionalDependencies": { "cson-parser": "^4.0.8", "js-yaml": "^4.0.0" }, "eslintConfig": { "extends": [ "xo", "xo-space" ] }, "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } }, "config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } }, "release-it": { "git": { "commitMessage": "chore: release v${version}" }, "github": { "release": true } } } applause-2.0.4/src/000077500000000000000000000000001404402677600141305ustar00rootroot00000000000000applause-2.0.4/src/applause.js000066400000000000000000000115131404402677600163010ustar00rootroot00000000000000var _ = require('lodash'); var plugins = require('./plugins'); // Took from MDN // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions var escapeRegExp = function (string) { return string.replace(/([.*+?^${}()|[\]/\\])/g, '\\$1'); }; var getPatterns = function (applause) { var opts = applause.options; // Shallow patterns var patterns = _.chain(opts.patterns) .clone() .compact() .filter(function (pattern) { return !_.isEmpty(pattern); }) .value(); // Backward compatibility var variables = opts.variables; if (!_.isEmpty(variables)) { patterns.push({ json: variables }); } // Process for (var i = patterns.length - 1; i >= 0; i -= 1) { var pattern = patterns[i]; // Plugins plugins.forEach(function (plugin) { if (plugin.match(pattern, opts) === true) { plugin.transform(pattern, opts, function (items) { if (items instanceof Error) { throw items; } else { // Store transformed pattern in context pattern = items; } }); } else { // Plugin doesn't apply } }); // Convert to array if (!_.isArray(pattern)) { pattern = [pattern]; } // Link with pattern with original source pattern.forEach(function (pattern) { pattern.source = patterns[i]; }); // Attach index Array.prototype.splice.apply(patterns, [i, 1].concat(pattern)); } if (opts.preserveOrder !== true) { // Only sort non regex patterns (prevents replace issues like head, header) patterns.sort(function (a, b) { var x = a.match; var y = b.match; if (_.isString(x) && _.isString(y)) { return y.length - x.length; } if (_.isString(x)) { return -1; } return 1; }); } return patterns; }; // Applause var Applause = function (opts) { this.options = _.defaults(opts, { patterns: [], prefix: opts.usePrefix === false ? '' : '@@', usePrefix: true, preservePrefix: false, delimiter: '.', preserveOrder: false }); }; Applause.prototype.replace = function (content, process) { var opts = this.options; // Prevent null content = content || ''; // Prepare patterns var patterns = getPatterns(this); var detail = []; var totalCount = 0; // Iterate over each pattern and make replacement patterns.forEach(function (pattern) { // Filter empty patterns var match = pattern.match; // Support replace flag too var replacement = pattern.replacement; if (replacement === undefined || replacement === null) { replacement = pattern.replace; } // Var source = pattern.source; var expression = false; // Match check if (match !== undefined && match !== null) { if (_.isRegExp(match)) { expression = true; } else if (_.isString(match)) { if (match.length > 0) { match = new RegExp(opts.prefix + escapeRegExp(match), 'g'); } else { // Empty match return; } } else { throw new Error('Unsupported match type (RegExp or String expected).'); } } else { throw new Error('Match attribute expected in pattern definition.'); } // Replacement check if (replacement !== undefined && replacement !== null) { if (_.isFunction(replacement)) { // Replace using function return value replacement = function () { var args = Array.prototype.slice.call(arguments); return pattern.replacement.apply(this, args.concat(process || [])); }; } else { if (!_.isString(replacement)) { // Transform object to string replacement = JSON.stringify(replacement); } if (expression === false) { // Escape dollar sequences in easy mode replacement = replacement.replace(/\$/g, '$$$'); // Preserve prefix if (opts.preservePrefix === true) { replacement = opts.prefix + replacement; } } } } else { throw new Error('Replacement attribute expected in pattern definition.'); } // Replace logic var count = ((typeof content === 'string' && content.match(match)) || []).length; if (count > 0) { // Update content content = content.replace(match, replacement); // Save detail data detail.push({ match: match, replacement: replacement, source: pattern.source, count: count }); totalCount += count; } }); if (detail.length === 0) { content = false; } return { content: content, detail: detail, count: totalCount }; }; // Static Applause.create = function (opts) { return new Applause(opts); }; Applause.version = require('../package.json').version; // Expose module.exports = Applause; applause-2.0.4/src/plugins.js000066400000000000000000000003631404402677600161510ustar00rootroot00000000000000var plugins = [ require('./plugins/yaml'), require('./plugins/cson'), require('./plugins/json') ]; // Priority sort plugins.sort(function (a, b) { return (a.priority || 0) - (b.priority || 0); }); // Expose module.exports = plugins; applause-2.0.4/src/plugins/000077500000000000000000000000001404402677600156115ustar00rootroot00000000000000applause-2.0.4/src/plugins/cson.js000066400000000000000000000015271404402677600171160ustar00rootroot00000000000000var _ = require('lodash'); // Var CSON = require('cson-parser'); const optionalRequire = require('optional-require')(require); // Expose module.exports = { name: 'cson', priority: 10, match: function (pattern) { var cson = pattern.cson; var match = typeof cson !== 'undefined'; return match; }, transform: function (pattern, opts, done) { var cson = pattern.cson; // Function support if (_.isFunction(cson)) { cson.call(this, function (result) { // Override cson function with value cson = result; }); } try { const CSON = optionalRequire('cson-parser'); if (!CSON) { throw new Error('Missing ' + this.name + ' dependency for transform (cson-parser).'); } done({ json: CSON.parse(cson) }); } catch (e) { done(e); } } }; applause-2.0.4/src/plugins/json.js000066400000000000000000000024701404402677600171230ustar00rootroot00000000000000var _ = require('lodash'); var flatten = function (json, delimiter) { var result = []; var recurse = function (cur, prop) { for (var key in cur) { // eslint-disable-next-line no-prototype-builtins if (cur.hasOwnProperty(key)) { var item = cur[key]; var match = prop ? prop + delimiter + key : key; result.push({ match: match, replacement: item, expression: false }); // Deep scan if (typeof item === 'object') { recurse(item, prop ? prop + delimiter + key : key); } } } }; recurse(json); return result; }; // Expose module.exports = { name: 'json', priority: 20, match: function (pattern) { var json = pattern.json; var match = typeof json !== 'undefined'; return match; }, transform: function (pattern, opts, done) { var delimiter = opts.delimiter; var json = pattern.json; // Function support if (_.isFunction(json)) { json.call(this, function (result) { // Override json function with value json = result; }); } if (_.isPlainObject(json)) { // Replace json with flatten data done(flatten(json, delimiter)); } else { done(new Error('Unsupported type for json (plain object expected).')); } } }; applause-2.0.4/src/plugins/yaml.js000066400000000000000000000015131404402677600171110ustar00rootroot00000000000000var _ = require('lodash'); // Var YAML = require('js-yaml'); const optionalRequire = require('optional-require')(require); // Expose module.exports = { name: 'yaml', priority: 10, match: function (pattern) { var yaml = pattern.yaml; var match = typeof yaml !== 'undefined'; return match; }, transform: function (pattern, opts, done) { var yaml = pattern.yaml; // Function support if (_.isFunction(yaml)) { yaml.call(this, function (result) { // Override yaml function with value yaml = result; }); } try { const YAML = optionalRequire('js-yaml'); if (!YAML) { throw new Error('Missing ' + this.name + ' dependency for transform (js-yaml).'); } done({ json: YAML.load(yaml) }); } catch (e) { done(e); } } }; applause-2.0.4/test.js000066400000000000000000000371631404402677600146700ustar00rootroot00000000000000var test = require('ava'); var Applause = require('.'); test('should replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should replace simple key with empty value', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: '' } ] }); var result = applause.replace('@@key'); t.is(result.content, ''); }); test('should replace simple key with value and return the detail', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ], detail: true }); var result = applause.replace('@@key'); t.is(result.content, 'value'); t.is(result.detail.length, 1); }); test('should replace simple key with value (replacement alternative)', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replace: 'value' } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should replace simple key with value using custom prefix', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ], prefix: '@replace:' }); var result = applause.replace('@replace:key'); t.is(result.content, 'value'); }); test('should replace simple key with value without prefix', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ], usePrefix: false }); var result = applause.replace('key'); t.is(result.content, 'value'); }); test('should replace multiple key-value pairs', function (t) { var applause = Applause.create({ patterns: [ { match: 'key-1', replacement: 'value-1' }, { match: 'key-2', replacement: 'value-2' } ] }); var result = applause.replace('@@key-1,@@key-2'); t.is(result.content, 'value-1,value-2'); }); test('should replace multiple key-value pairs and return the detail', function (t) { var applause = Applause.create({ patterns: [ { match: 'key-1', replacement: 'value-1' }, { match: 'key-2', replacement: 'value-2' } ], detail: true }); var result = applause.replace('@@key-1,@@key-2'); t.is(result.content, 'value-1,value-2'); t.is(result.detail.length, 2); }); test('should not escape dollar sequence when use simple key', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: '$' } ] }); var result = applause.replace('@@key'); t.is(result.content, '$'); }); test('should escape dollar sequence when use regexp for matching', function (t) { var applause = Applause.create({ patterns: [ { match: /key/g, replacement: '$$' } ] }); var result = applause.replace('key'); t.is(result.content, '$'); }); test('should use special characters in replacement', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'detta är en sträng' } ] }); var result = applause.replace('@@key'); t.is(result.content, 'detta är en sträng'); }); test('should use regexp for matching', function (t) { var applause = Applause.create({ patterns: [ { match: /key/g, replacement: 'value' } ] }); var result = applause.replace('key'); t.is(result.content, 'value'); }); test('should use function for replacements', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: function () { return 'value'; } } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should replace "John Smith" for "Smith, John"', function (t) { var applause = Applause.create({ patterns: [ { match: /(\w+)\s(\w+)/, replacement: '$2, $1' } ] }); var result = applause.replace('John Smith'); t.is(result.content, 'Smith, John'); }); test('should throw error when invalid match type found', function (t) { var applause = Applause.create({ patterns: [ { match: 1, replacement: 'value' } ] }); t.throws(function () { applause.replace('@@1'); }); }); test('should throw error when match attribute is undefined', function (t) { var applause = Applause.create({ patterns: [ { replacement: 'value' } ] }); t.throws(function () { applause.replace('@@key'); }); }); test('should throw error when match attribute is null', function (t) { var applause = Applause.create({ patterns: [ { match: null, replacement: 'value' } ] }); t.throws(function () { applause.replace('@@key'); }); }); test('should throw error when replacement attribute is undefined', function (t) { var applause = Applause.create({ patterns: [ { match: 'key' } ] }); t.throws(function () { applause.replace('@@key'); }); }); test('should throw error when replacement attribute is null', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: null } ] }); t.throws(function () { applause.replace('@@key'); }); }); test('should ignore empty patterns definitions', function (t) { var applause = Applause.create({ patterns: [ { // Pass } ] }); var result = applause.replace('@@key'); t.is(result.content, false); }); test('should not match any pattern definition', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ] }); var result = applause.replace(); t.is(result.content, false); }); test('should ignore non-string data types', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ] }); var booleanResult = applause.replace(true); t.is(booleanResult.content, false); var numberResult = applause.replace(404); t.is(numberResult.content, false); }); test('should replace patterns using plain objects', function (t) { var applause = Applause.create({ variables: { key: 'value' } }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should replace simple key with array object representation', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: [1, 2, 3, 4] } ] }); var result = applause.replace('@@key'); t.is(result.content, '[1,2,3,4]'); }); test('should replace simple key with plain object representation', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: { foo: 'bar' } } ] }); var result = applause.replace('@@key'); t.is(result.content, '{"foo":"bar"}'); }); test('should sort patterns to prevent bad replaces', function (t) { var applause = Applause.create({ patterns: [ { match: 'smaller', replacement: '2' }, { match: 'small', replacement: '1' }, { match: 'smallest', replacement: '3' } ] }); var result = applause.replace('@@small-@@smaller-@@smallest'); t.is(result.content, '1-2-3'); }); test('should replace simple key with value and preserve prefix', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: 'value' } ], preservePrefix: true }); var result = applause.replace('@@key'); t.is(result.content, '@@value'); }); test('should replace simple key with array object representation and preserve prefix', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: [1, 2, 3, 4] } ], preservePrefix: true }); var result = applause.replace('@@key'); t.is(result.content, '@@[1,2,3,4]'); }); test('should replace simple key with value and not preserve prefix (function as replacement)', function (t) { var applause = Applause.create({ patterns: [ { match: 'key', replacement: function () { return 'value'; } } ], preservePrefix: true }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should replace simple key with value and not preserve prefix (regexp as match)', function (t) { var applause = Applause.create({ patterns: [ { match: /@@key/g, replacement: 'value' } ], preservePrefix: true }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should escape string to create an regexp', function (t) { var applause = Applause.create({ patterns: [ { match: '(../fonts/', replacement: '../font/' } ], usePrefix: false }); var result = applause.replace('(../fonts/'); t.is(result.content, '../font/'); }); test('should escape special characters in replacement', function (t) { var applause = Applause.create({ patterns: [ { match: '$var', replacement: '$var-value' }, { match: '@var', replacement: '@var-value' } ], usePrefix: false }); var result = applause.replace([ '$var', '@var' ].join()); t.is(result.content, [ '$var-value', '@var-value' ].join()); }); test('should escape special characters in replacement (function as replacement)', function (t) { var applause = Applause.create({ patterns: [ { match: '$var-fn', replacement: function () { return '$var-fn-value'; } }, { match: '@var-fn', replacement: function () { return '@var-fn-value'; } } ], usePrefix: false }); var result = applause.replace([ '$var-fn', '@var-fn' ].join()); t.is(result.content, [ '$var-fn-value', '@var-fn-value' ].join()); }); test('should check version number', function (t) { t.truthy(Applause.version); }); // Plugins // JSON test('should read from json and replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { json: { key: 'value' } } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should read from json and replace simple key with value (escape dollar sequence)', function (t) { var applause = Applause.create({ patterns: [ { json: { API_KEY: '12213lkhgjhvj$$bvhmvff@sdfertvc' } } ] }); var result = applause.replace('@@API_KEY'); t.is(result.content, '12213lkhgjhvj$$bvhmvff@sdfertvc'); }); test('should read from deferrer json and replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { json: function (done) { done({ key: 'value' }); } } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should sort the json patterns to prevent bad replaces', function (t) { var applause = Applause.create({ patterns: [ { json: { small: '1', smaller: '2', smallest: '3' } } ] }); var result = applause.replace('@@small-@@smaller-@@smallest'); t.is(result.content, '1-2-3'); }); // Flatten var jsonFixture = { key1: 'value1', key2: 'value2', group1: { group2: { key3: 'value3' }, group3: { key4: 'value4' }, array: [1, 2, 3] } }; test('should flatten json object', function (t) { var applause = Applause.create({ patterns: [ { json: jsonFixture } ] }); var result = applause.replace('@@group1.group2.key3'); t.is(result.content, 'value3'); }); test('should flatten json object with custom delimiter', function (t) { var applause = Applause.create({ patterns: [ { json: jsonFixture } ], delimiter: '-' }); var result = applause.replace('@@group1-group2-key3'); t.is(result.content, 'value3'); }); test('should replace simple key from json with plain object representation', function (t) { var applause = Applause.create({ patterns: [ { json: jsonFixture } ] }); var result = applause.replace('@@group1.group2'); t.is(result.content, '{"key3":"value3"}'); }); test('should replace simple key from json with plain object representation and preserve prefix', function (t) { var applause = Applause.create({ patterns: [ { json: jsonFixture } ], preservePrefix: true }); var result = applause.replace('@@group1.group2'); t.is(result.content, '@@{"key3":"value3"}'); }); // YAML test('should read from yaml and replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { yaml: 'key: "value"' } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should read from yaml and replace simple key with value (escape dollar sequence)', function (t) { var applause = Applause.create({ patterns: [ { yaml: 'API_KEY: "12213lkhgjhvj$$bvhmvff@sdfertvc"' } ] }); var result = applause.replace('@@API_KEY'); t.is(result.content, '12213lkhgjhvj$$bvhmvff@sdfertvc'); }); test('should read from deferrer yaml and replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { yaml: function (done) { done('key: "value"'); } } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should sort the yaml patterns to prevent bad replaces', function (t) { var applause = Applause.create({ patterns: [ { yaml: 'small: "1"\nsmaller: "2"\nsmallest: "3"' } ] }); var result = applause.replace('@@small-@@smaller-@@smallest'); t.is(result.content, '1-2-3'); }); // CSON test('should read from cson and replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { cson: 'key: "value"' } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should read from cson and replace simple key with value (escape dollar sequence)', function (t) { var applause = Applause.create({ patterns: [ { cson: 'API_KEY: "12213lkhgjhvj$$bvhmvff@sdfertvc"' } ] }); var result = applause.replace('@@API_KEY'); t.is(result.content, '12213lkhgjhvj$$bvhmvff@sdfertvc'); }); test('should read from deferrer cson and replace simple key with value', function (t) { var applause = Applause.create({ patterns: [ { cson: function (done) { done('key: "value"'); } } ] }); var result = applause.replace('@@key'); t.is(result.content, 'value'); }); test('should sort the cson patterns to prevent bad replaces', function (t) { var applause = Applause.create({ patterns: [ { cson: 'small: "1"\nsmaller: "2"\nsmallest: "3"' } ] }); var result = applause.replace('@@small-@@smaller-@@smallest'); t.is(result.content, '1-2-3'); }); applause-2.0.4/travis.yml000066400000000000000000000000661404402677600153760ustar00rootroot00000000000000language: node_js node_js: - '14' - '12' - '10'