Merge pull request #743 from Chalarangelo/refactor-builder

[REFACTOR/ENHANCEMENT] Refactor + Simplify Builder
This commit is contained in:
Angelos Chalaris
2018-09-14 19:33:50 +03:00
committed by GitHub
8 changed files with 2515 additions and 2573 deletions

371
README.md

File diff suppressed because it is too large Load Diff

211
package-lock.json generated
View File

@ -1894,6 +1894,29 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
"cosmiconfig": {
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.6.tgz",
"integrity": "sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ==",
"dev": true,
"requires": {
"is-directory": "0.3.1",
"js-yaml": "3.12.0",
"parse-json": "4.0.0"
},
"dependencies": {
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
"error-ex": "1.3.1",
"json-parse-better-errors": "1.0.2"
}
}
}
},
"cross-spawn": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
@ -4047,6 +4070,158 @@
"sshpk": "1.14.1"
}
},
"husky": {
"version": "1.0.0-rc.14",
"resolved": "https://registry.npmjs.org/husky/-/husky-1.0.0-rc.14.tgz",
"integrity": "sha512-lxdl0+FrKhRXvhOW978oCHCiaXQAtwoR0hdaPY1CwKd+dgbtktepEvk/3DXwQ7L1YriuG/9HDc4AHlzQ0T6cNw==",
"dev": true,
"requires": {
"cosmiconfig": "5.0.6",
"execa": "0.9.0",
"find-up": "3.0.0",
"get-stdin": "6.0.0",
"is-ci": "1.2.1",
"pkg-dir": "3.0.0",
"please-upgrade-node": "3.1.1",
"read-pkg": "4.0.1",
"run-node": "1.0.0",
"slash": "2.0.0"
},
"dependencies": {
"ci-info": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.5.1.tgz",
"integrity": "sha512-fKFIKXaYiL1exImwJ0AhR/6jxFPSKQBk2ayV5NiNoruUs2+rxC2kNw0EG+1Z9dugZRdCrppskQ8DN2cyaUM1Hw==",
"dev": true
},
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"dev": true,
"requires": {
"lru-cache": "4.1.2",
"shebang-command": "1.2.0",
"which": "1.3.0"
}
},
"execa": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz",
"integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==",
"dev": true,
"requires": {
"cross-spawn": "5.1.0",
"get-stream": "3.0.0",
"is-stream": "1.1.0",
"npm-run-path": "2.0.2",
"p-finally": "1.0.0",
"signal-exit": "3.0.2",
"strip-eof": "1.0.0"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "3.0.0"
}
},
"is-ci": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
"integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
"dev": true,
"requires": {
"ci-info": "1.5.1"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "3.0.0",
"path-exists": "3.0.0"
}
},
"p-limit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
"integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
"dev": true,
"requires": {
"p-try": "2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "2.0.0"
}
},
"p-try": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
"integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
"dev": true
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
"error-ex": "1.3.1",
"json-parse-better-errors": "1.0.2"
}
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
},
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
"pkg-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
"dev": true,
"requires": {
"find-up": "3.0.0"
}
},
"read-pkg": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz",
"integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=",
"dev": true,
"requires": {
"normalize-package-data": "2.4.0",
"parse-json": "4.0.0",
"pify": "3.0.0"
}
},
"slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true
}
}
},
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
@ -4248,6 +4423,12 @@
}
}
},
"is-directory": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
"dev": true
},
"is-dotfile": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
@ -5547,6 +5728,15 @@
"object-visit": "1.0.1"
}
},
"markdown-builder": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/markdown-builder/-/markdown-builder-0.8.4.tgz",
"integrity": "sha512-zI9O16OxyA7kqBdkCkgqvbDGO8FsCYF7rOV+XoeQ0H6ucZII7Do2p2kTkdiLTuxKWPBo/RFYnmP+To8KOp4jCQ==",
"dev": true,
"requires": {
"husky": "1.0.0-rc.14"
}
},
"markdown-it": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.1.tgz",
@ -6524,6 +6714,15 @@
}
}
},
"please-upgrade-node": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz",
"integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==",
"dev": true,
"requires": {
"semver-compare": "1.0.0"
}
},
"pluralize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
@ -7076,6 +7275,12 @@
"is-promise": "2.1.0"
}
},
"run-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz",
"integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==",
"dev": true
},
"run-parallel": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz",
@ -7228,6 +7433,12 @@
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"dev": true
},
"semver-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
"dev": true
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",

View File

@ -6,6 +6,7 @@
"html-minifier": "^3.5.15",
"jest": "^23.1.0",
"jest-tap-reporter": "^1.9.0",
"markdown-builder": "^0.8.4",
"markdown-it": "^8.4.1",
"mini.css": "^2.3.7",
"node-sass": "^4.9.0",

View File

@ -7,21 +7,35 @@ const fs = require('fs-extra');
const path = require('path');
const chalk = require('chalk');
const util = require('./util');
const markdown = require('markdown-builder');
const { headers, misc, lists } = markdown;
// Paths
const SNIPPETS_PATH = './snippets';
const SNIPPETS_ARCHIVE_PATH = './snippets_archive';
const STATIC_PARTS_PATH = './static-parts';
if (util.isTravisCI() && /^Travis build: \d+/g.test(process.env['TRAVIS_COMMIT_MESSAGE'])) {
if (
util.isTravisCI() &&
/^Travis build: \d+/g.test(process.env['TRAVIS_COMMIT_MESSAGE'])
) {
console.log(
`${chalk.green('NOBUILD')} README build terminated, parent commit is a Travis build!`
`${chalk.green(
'NOBUILD'
)} README build terminated, parent commit is a Travis build!`
);
process.exit(0);
}
if (
util.isTravisCI() &&
(process.env['TRAVIS_EVENT_TYPE'] === 'cron' || process.env['TRAVIS_EVENT_TYPE'] === 'api')
(process.env['TRAVIS_EVENT_TYPE'] === 'cron' ||
process.env['TRAVIS_EVENT_TYPE'] === 'api')
) {
console.log(`${chalk.green('ARCHIVE')} Cron job or custom build, building archive README!`);
console.log(
`${chalk.green(
'ARCHIVE'
)} Cron job or custom build, building archive README!`
);
console.time('Builder');
let snippets = {};
// Synchronously read all snippets from snippets_archive folder and sort them as necessary (case-insensitive)
@ -31,7 +45,10 @@ if (
.sort((a, b) => a.toLowerCase() - b.toLowerCase());
// Store the data read from each snippet in the appropriate object
for (const name of snippetFilenames.filter(s => s !== 'README.md')) {
snippets[name] = fs.readFileSync(path.join(SNIPPETS_ARCHIVE_PATH, name), 'utf8');
snippets[name] = fs.readFileSync(
path.join(SNIPPETS_ARCHIVE_PATH, name),
'utf8'
);
}
} catch (err) {
console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`);
@ -39,37 +56,43 @@ if (
}
try {
// Add the start static part
let output = `![Logo](/logo.png)
let output =
misc.image('Logo', '/logo.png') +
headers.h1('Snippets Archive') +
"These snippets, while useful and interesting, didn't quite make it into the repository due to either having very specific use-cases or being outdated. However we felt like they might still be useful to some readers, so here they are." +
headers.h2('Table of Contents');
# Snippets Archive
output += lists.ul(Object.entries(snippets), snippet =>
misc.link(`\`${snippet[0].slice(0, -3)}\``, misc.anchor(snippet[0].slice(0, -3)))
);
output += misc.hr();
These snippets, while useful and interesting, didn\'t quite make it into the repository due to either having very specific use-cases or being outdated. However we felt like they might still be useful to some readers, so here they are.
## Table of Contents
`;
for (const snippet of Object.entries(snippets))
output += `* [\`${snippet[0].slice(0, -3)}\`](#${snippet[0].toLowerCase().slice(0, -3)})\n`;
output += '\n---\n';
for (const snippet of Object.entries(snippets)) {
let data = snippet[1];
data =
data.slice(0, data.lastIndexOf('```js')) +
'<details>\n<summary>Examples</summary>\n\n' +
data.slice(data.lastIndexOf('```js'), data.lastIndexOf('```')) +
data.slice(data.lastIndexOf('```')) +
'\n</details>\n';
output += `\n${data + '\n<br>[⬆ Back to top](#table-of-contents)\n\n'}`;
data.slice(0, data.lastIndexOf('```js')).trim() +
misc.collapsible(
'Examples',
data.slice(data.lastIndexOf('```js'), data.lastIndexOf('```')) +
data.slice(data.lastIndexOf('```'))
);
output += data + '\n<br>' + misc.link('⬆ Back to top', misc.anchor('Table of Contents')) + '\n\n';
}
// Write to the README file of the archive
fs.writeFileSync(path.join(SNIPPETS_ARCHIVE_PATH, 'README.md'), output);
} catch (err) {
console.log(`${chalk.red('ERROR!')} During README generation for snippets archive: ${err}`);
console.log(
`${chalk.red(
'ERROR!'
)} During README generation for snippets archive: ${err}`
);
process.exit(1);
}
console.log(`${chalk.green('SUCCESS!')} README file generated for snippets archive!`);
console.log(
`${chalk.green('SUCCESS!')} README file generated for snippets archive!`
);
console.timeEnd('Builder');
}
let snippets = {};
@ -101,8 +124,14 @@ snippets = util.readSnippets(SNIPPETS_PATH);
// Load static parts for the README file
try {
startPart = fs.readFileSync(path.join(STATIC_PARTS_PATH, 'README-start.md'), 'utf8');
endPart = fs.readFileSync(path.join(STATIC_PARTS_PATH, 'README-end.md'), 'utf8');
startPart = fs.readFileSync(
path.join(STATIC_PARTS_PATH, 'README-start.md'),
'utf8'
);
endPart = fs.readFileSync(
path.join(STATIC_PARTS_PATH, 'README-end.md'),
'utf8'
);
} catch (err) {
console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`);
process.exit(1);
@ -111,6 +140,7 @@ try {
// Load tag data from the database
tagDbData = util.readTags();
console.log(tagDbData);
// Create the output for the README file
try {
const tags = [
@ -132,40 +162,51 @@ try {
console.log(tags);
// Add the start static part
output += `${startPart + '\n'}`;
output += `${startPart}\n`;
// Loop over tags and snippets to create the table of contents
for (const tag of tags) {
const capitalizedTag = util.capitalize(tag, true);
output += `### ${EMOJIS[tag] ||
''} ${capitalizedTag}\n\n<details>\n<summary>View contents</summary>\n\n`;
for (const taggedSnippet of Object.entries(tagDbData).filter(v => v[1][0] === tag)) {
output += `* [\`${taggedSnippet[0]}\`](#${taggedSnippet[0].toLowerCase()}${
taggedSnippet[1].includes('advanced') ? '-' : ''
})\n`;
}
output += '\n</details>\n\n';
const taggedSnippets = Object.entries(tagDbData).filter(v => v[1][0] === tag);
output += headers.h3((EMOJIS[tag] || '') + ' ' + capitalizedTag).trim();
output += misc.collapsible(
'View contents',
lists.ul(taggedSnippets, (snippet) =>
misc.link(
`\`${snippet[0]}\``,
`${misc.anchor(snippet[0])}${snippet[1].includes('advanced') ? '-' : ''}`
)
)
) + '\n';
}
// Loop over tags and snippets to create the list of snippets
for (const tag of tags) {
const capitalizedTag = util.capitalize(tag, true);
output += `---\n ## ${EMOJIS[tag] || ''} ${capitalizedTag}\n`;
for (const taggedSnippet of Object.entries(tagDbData).filter(v => v[1][0] === tag)) {
let data = snippets[taggedSnippet[0] + '.md'];
const taggedSnippets = Object.entries(tagDbData).filter(v => v[1][0] === tag);
output += misc.hr() + headers.h2((EMOJIS[tag] || '') + ' ' + capitalizedTag) + '\n';
for (const taggedSnippet of taggedSnippets) {
let snippet = snippets[taggedSnippet[0] + '.md'];
// Add advanced tag
if (taggedSnippet[1].includes('advanced')) {
data = data.split(/\r?\n/);
data[0] = data[0] + ' ![advanced](/advanced.svg)';
data = data.join('\n');
snippet = snippet.split(/\r?\n/);
// add label to snippet title (first line)
snippet[0] += ' ' + misc.image('advanced', '/advanced.svg');
snippet = snippet.join('\n');
}
data =
data.slice(0, data.lastIndexOf('```js')) +
'<details>\n<summary>Examples</summary>\n\n' +
data.slice(data.lastIndexOf('```js'), data.lastIndexOf('```')) +
data.slice(data.lastIndexOf('```')) +
'\n</details>\n';
output += `\n${data + '\n<br>[⬆ Back to top](#table-of-contents)\n\n'}`;
snippet = snippet.slice(0, snippet.lastIndexOf('```js')).trim() +
misc.collapsible(
'Examples',
snippet.slice(snippet.lastIndexOf('```js'), snippet.lastIndexOf('```')) +
snippet.slice(snippet.lastIndexOf('```'))
);
output += snippet + '\n<br>' + misc.link('⬆ Back to top', misc.anchor('Table of Contents')) + '\n\n';
}
}

View File

@ -194,14 +194,14 @@
"fileName": "isSimilar.md",
"text": "Determines if the `pattern` matches with `str`.\n\nUse `String.toLowerCase()` to convert both strings to lowercase, then loop through `str` and determine if it contains all characters of `pattern` and in the correct order.\nAdapted from [here](https://github.com/forrestthewoods/lib_fts/blob/80f3f8c52db53428247e741b9efe2cde9667050c/code/fts_fuzzy_match.js#L18).",
"codeBlocks": [
"``` js\nconst isSimilar = (pattern, str) =>\n\t[...str].reduce(\n\t\t(matchIndex, char) => char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() ? matchIndex + 1 : matchIndex, 0\n\t) === pattern.length ? true : false;\n```",
"``` js\nisSimilar('rt','Rohit'); // true\nisSimilar('tr','Rohit'); // false\n```"
"const isSimilar = (pattern, str) =>\n\t[...str].reduce(\n\t\t(matchIndex, char) => char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() ? matchIndex + 1 : matchIndex, 0\n\t) === pattern.length ? true : false;",
"isSimilar('rt','Rohit'); // true\nisSimilar('tr','Rohit'); // false"
],
"tags": []
},
"meta": {
"archived": true,
"hash": "b821ad7f7e34c6905f88e1618b629506e265e1a3459288ab7d7b3501b2476dd2"
"hash": "669cc6d3a6f96a65b6e4bf678bb0b95cde711baaabe206db66d69599f6e93a51"
}
},
{
@ -288,22 +288,22 @@
"isArmstrongNumber(1634); // true\nisArmstrongNumber(56); // false",
"``` js\nconst isSimilar = (pattern, str) =>\n\t[...str].reduce(\n\t\t(matchIndex, char) => char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() ? matchIndex + 1 : matchIndex, 0\n\t) === pattern.length ? true : false;\n```",
"``` js\nisSimilar('rt','Rohit'); // true\nisSimilar('tr','Rohit'); // false\n```",
"```\n\n</details>\n\n<br>[⬆ Back to top](#table-of-contents)\n\n\n### levenshteinDistance\n\nCalculates the [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance) between two strings.\n\nCalculates the number of changes (substitutions, deletions or additions) required to convert `string1` to `string2`. \nCan also be used to compare two strings as shown in the second example.\n\n```",
"```\n\n<details>\n<summary>Examples</summary>\n\n```",
"```\n\n</details>\n\n<br>[⬆ Back to top](#table-of-contents)\n\n\n### quickSort\n\nQuickSort an Array (ascending sort by default).\n\nUse recursion. \nUse `Array.filter` and spread operator (`...`) to create an array that all elements with values less than the pivot come before the pivot, and all elements with values greater than the pivot come after it. \nIf the parameter `desc` is truthy, return array sorts in descending order.\n\n```",
"```\n\n<details>\n<summary>Examples</summary>\n\n```",
"```\n\n</details>\n\n<br>[⬆ Back to top](#table-of-contents)\n\n\n### removeVowels\n\nReturns all the vowels in a `str` replaced by `repl`.\n\nUse `String.replace()` with a regexp to replace all vowels in `str`.\nOmot `repl` to use a default value of `''`.\n\n```",
"```\n\n<details>\n<summary>Examples</summary>\n\n```",
"```\n\n</details>\n\n<br>[⬆ Back to top](#table-of-contents)\n\n\n### solveRPN\n\nSolves the given mathematical expression in [reverse polish notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation).\nThrows appropriate errors if there are unrecognized symbols or the expression is wrong. The valid operators are :- `+`,`-`,`*`,`/`,`^`,`**` (`^`&`**` are the exponential symbols and are same). This snippet does not supports any unary operators.\n\nUse a dictionary, `OPERATORS` to specify each operator's matching mathematical operation.\nUse `String.replace()` with a regular expression to replace `^` with `**`, `String.split()` to tokenize the string and `Array.filter()` to remove empty tokens.\nUse `Array.forEach()` to parse each `symbol`, evaluate it as a numeric value or operator and solve the mathematical expression.\nNumeric values are converted to floating point numbers and pushed to a `stack`, while operators are evaluated using the `OPERATORS` dictionary and pop elements from the `stack` to apply operations.\n\n```",
"```\n\n<details>\n<summary>Examples</summary>\n\n```",
"```\n\n</details>\n\n<br>[⬆ Back to top](#table-of-contents)\n\n\n### howManyTimes\n\nReturns the number of times `num` can be divided by `divisor` (integer or fractional) without getting a fractional answer.\nWorks for both negative and positive integers.\n\nIf `divisor` is `-1` or `1` return `Infinity`.\nIf `divisor` is `-0` or `0` return `0`.\nOtherwise, keep dividing `num` with `divisor` and incrementing `i`, while the result is an integer.\nReturn the number of times the loop was executed, `i`.\n\n```",
"```\n\n<details>\n<summary>Examples</summary>\n\n```"
"```\n\n</details>\n \n[⬆ Back to top](#table-of-contents)\n\n### levenshteinDistance\n\nCalculates the [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance) between two strings.\n\nCalculates the number of changes (substitutions, deletions or additions) required to convert `string1` to `string2`. \nCan also be used to compare two strings as shown in the second example.\n\n```",
"``` \n\n<details>\n <summary>Examples</summary>\n \n```",
"```\n\n</details>\n \n[⬆ Back to top](#table-of-contents)\n\n### quickSort\n\nQuickSort an Array (ascending sort by default).\n\nUse recursion. \nUse `Array.filter` and spread operator (`...`) to create an array that all elements with values less than the pivot come before the pivot, and all elements with values greater than the pivot come after it. \nIf the parameter `desc` is truthy, return array sorts in descending order.\n\n```",
"``` \n\n<details>\n <summary>Examples</summary>\n \n```",
"```\n\n</details>\n \n[⬆ Back to top](#table-of-contents)\n\n### removeVowels\n\nReturns all the vowels in a `str` replaced by `repl`.\n\nUse `String.replace()` with a regexp to replace all vowels in `str`.\nOmot `repl` to use a default value of `''`.\n\n```",
"``` \n\n<details>\n <summary>Examples</summary>\n \n```",
"```\n\n</details>\n \n[⬆ Back to top](#table-of-contents)\n\n### solveRPN\n\nSolves the given mathematical expression in [reverse polish notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation).\nThrows appropriate errors if there are unrecognized symbols or the expression is wrong. The valid operators are :- `+`,`-`,`*`,`/`,`^`,`**` (`^`&`**` are the exponential symbols and are same). This snippet does not supports any unary operators.\n\nUse a dictionary, `OPERATORS` to specify each operator's matching mathematical operation.\nUse `String.replace()` with a regular expression to replace `^` with `**`, `String.split()` to tokenize the string and `Array.filter()` to remove empty tokens.\nUse `Array.forEach()` to parse each `symbol`, evaluate it as a numeric value or operator and solve the mathematical expression.\nNumeric values are converted to floating point numbers and pushed to a `stack`, while operators are evaluated using the `OPERATORS` dictionary and pop elements from the `stack` to apply operations.\n\n```",
"``` \n\n<details>\n <summary>Examples</summary>\n \n```",
"```\n\n</details>\n \n[⬆ Back to top](#table-of-contents)\n\n### howManyTimes\n\nReturns the number of times `num` can be divided by `divisor` (integer or fractional) without getting a fractional answer.\nWorks for both negative and positive integers.\n\nIf `divisor` is `-1` or `1` return `Infinity`.\nIf `divisor` is `-0` or `0` return `0`.\nOtherwise, keep dividing `num` with `divisor` and incrementing `i`, while the result is an integer.\nReturn the number of times the loop was executed, `i`.\n\n```",
"``` \n\n<details>\n <summary>Examples</summary>\n \n```"
],
"tags": []
},
"meta": {
"archived": true,
"hash": "878970d0bdefe60f7f61db64b85bbb36b6869e2875a2c278fb269b8cff3b42b4"
"hash": "4c776a716fd3fd197ce7d6bf3f18e73e647f0363a8668b72cb980b53d355fe20"
}
},
{

View File

@ -1,11 +1,7 @@
![Logo](/logo.png)
# Snippets Archive
These snippets, while useful and interesting, didn't quite make it into the repository due to either having very specific use-cases or being outdated. However we felt like they might still be useful to some readers, so here they are.
## Table of Contents
![Logo](/logo.png)
# Snippets Archive
These snippets, while useful and interesting, didn't quite make it into the repository due to either having very specific use-cases or being outdated. However we felt like they might still be useful to some readers, so here they are.
## Table of Contents
* [`JSONToDate`](#jsontodate)
* [`speechSynthesis`](#speechsynthesis)
* [`binarySearch`](#binarysearch)
@ -24,9 +20,8 @@ These snippets, while useful and interesting, didn't quite make it into the repo
* [`removeVowels`](#removevowels)
* [`solveRPN`](#solverpn)
* [`howManyTimes`](#howmanytimes)
---
---
### JSONToDate
Converts a JSON object to a date.
@ -38,19 +33,18 @@ const JSONToDate = arr => {
const dt = new Date(parseInt(arr.toString().substr(6)));
return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
JSONToDate(/Date(1489525200000)/); // "14/3/2017"
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### speechSynthesis
@ -67,19 +61,18 @@ const speechSynthesis = message => {
msg.voice = window.speechSynthesis.getVoices()[0];
window.speechSynthesis.speak(msg);
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
speechSynthesis('Hello, World'); // // plays the message
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### binarySearch
@ -99,20 +92,19 @@ const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {
if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end);
return mid;
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
binarySearch([1, 4, 6, 7, 12, 13, 15, 18, 19, 20, 22, 24], 6); // 2
binarySearch([1, 4, 6, 7, 12, 13, 15, 18, 19, 20, 22, 24], 21); // -1
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### cleanObj
@ -132,20 +124,19 @@ const cleanObj = (obj, keysToKeep = [], childIndicator) => {
});
return obj;
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
const testObj = { a: 1, b: 2, children: { a: 1, b: 2 } };
cleanObj(testObj, ['a'], 'children'); // { a: 1, children : { a: 1}}
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### collatz
@ -155,19 +146,18 @@ If `n` is even, return `n/2`. Otherwise, return `3n+1`.
```js
const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1);
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
collatz(8); // 4
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### countVowels
@ -177,20 +167,19 @@ Use a regular expression to count the number of vowels `(A, E, I, O, U)` in a `s
```js
const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
countVowels('foobar'); // 3
countVowels('gym'); // 0
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### factors
@ -226,12 +215,12 @@ const factors = (num, primes = false) => {
}, []);
return primes ? array.filter(isPrime) : array;
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
factors(12); // [2,3,4,6,12]
factors(12, true); // [2,3]
factors(-12); // [2, -2, 3, -3, 4, -4, 6, -6, 12, -12]
@ -239,9 +228,8 @@ factors(-12, true); // [2,3]
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### fibonacciCountUntilNum
@ -252,19 +240,18 @@ Use a mathematical formula to calculate the number of fibonacci numbers until `n
```js
const fibonacciCountUntilNum = num =>
Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
fibonacciCountUntilNum(10); // 7
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### fibonacciUntilNum
@ -282,19 +269,18 @@ const fibonacciUntilNum = num => {
[]
);
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
fibonacciUntilNum(10); // [ 0, 1, 1, 2, 3, 5, 8 ]
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### httpDelete
@ -313,21 +299,20 @@ const httpDelete = (url, callback, err = console.error) => {
request.onerror = () => err(request);
request.send();
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
httpDelete('https://website.com/users/123', request => {
console.log(request.responseText);
}); // 'Deletes a user from the database'
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### httpPut
@ -348,12 +333,12 @@ const httpPut = (url, data, callback, err = console.error) => {
request.onerror = () => err(request);
request.send(data);
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
const password = "fooBaz";
const data = JSON.stringify(password);
httpPut('https://website.com/users/123', data, request => {
@ -362,9 +347,8 @@ httpPut('https://website.com/users/123', data, request => {
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### isArmstrongNumber
@ -377,20 +361,19 @@ const isArmstrongNumber = digits =>
(arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)(
(digits + '').split('')
);
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
isArmstrongNumber(1634); // true
isArmstrongNumber(56); // false
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### isSimilar
@ -399,26 +382,24 @@ Determines if the `pattern` matches with `str`.
Use `String.toLowerCase()` to convert both strings to lowercase, then loop through `str` and determine if it contains all characters of `pattern` and in the correct order.
Adapted from [here](https://github.com/forrestthewoods/lib_fts/blob/80f3f8c52db53428247e741b9efe2cde9667050c/code/fts_fuzzy_match.js#L18).
``` js
```js
const isSimilar = (pattern, str) =>
[...str].reduce(
(matchIndex, char) => char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() ? matchIndex + 1 : matchIndex, 0
) === pattern.length ? true : false;
```
```
``` js
<details>
<summary>Examples</summary>
```js
isSimilar('rt','Rohit'); // true
isSimilar('tr','Rohit'); // false
```<details>
<summary>Examples</summary>
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### levenshteinDistance
@ -445,21 +426,20 @@ const levenshteinDistance = (string1, string2) => {
}
return matrix[string2.length][string1.length];
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
levenshteinDistance('30-seconds-of-code','30-seconds-of-python-code'); // 7
const compareStrings = (string1,string2) => (100 - levenshteinDistance(string1,string2) / Math.max(string1.length,string2.length));
compareStrings('30-seconds-of-code', '30-seconds-of-python-code'); // 99.72 (%)
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### quickSort
@ -478,20 +458,19 @@ const quickSort = ([n, ...nums], desc) =>
n,
...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
];
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
quickSort([4, 1, 3, 2]); // [1,2,3,4]
quickSort([4, 1, 3, 2], true); // [4,3,2,1]
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### removeVowels
@ -502,20 +481,19 @@ Omot `repl` to use a default value of `''`.
```js
const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi,repl);
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
removeVowels("foobAr"); // "fbr"
removeVowels("foobAr","*"); // "f**b*r"
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### solveRPN
@ -556,20 +534,19 @@ const solveRPN = rpn => {
if (stack.length === 1) return stack.pop();
else throw `${rpn} is not a proper RPN. Please check it and try again`;
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
solveRPN('15 7 1 1 + - / 3 * 2 1 1 + + -'); // 5
solveRPN('2 3 ^'); // 8
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)
### howManyTimes
@ -592,12 +569,12 @@ const howManyTimes = (num, divisor) => {
}
return i;
};
```
```
<details>
<summary>Examples</summary>
```js
<summary>Examples</summary>
```js
howManyTimes(100, 2); // 2
howManyTimes(100, 2.5); // 2
howManyTimes(100, 0); // 0
@ -605,6 +582,6 @@ howManyTimes(100, -1); // Infinity
```
</details>
<br>[⬆ Back to top](#table-of-contents)
[⬆ Back to top](#table-of-contents)

View File

@ -5,15 +5,14 @@ Determines if the `pattern` matches with `str`.
Use `String.toLowerCase()` to convert both strings to lowercase, then loop through `str` and determine if it contains all characters of `pattern` and in the correct order.
Adapted from [here](https://github.com/forrestthewoods/lib_fts/blob/80f3f8c52db53428247e741b9efe2cde9667050c/code/fts_fuzzy_match.js#L18).
``` js
```js
const isSimilar = (pattern, str) =>
[...str].reduce(
(matchIndex, char) => char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase() ? matchIndex + 1 : matchIndex, 0
) === pattern.length ? true : false;
```
``` js
```js
isSimilar('rt','Rohit'); // true
isSimilar('tr','Rohit'); // false
```

File diff suppressed because it is too large Load Diff