From f2d115ee4da1485dc821312db2562b344662f83c Mon Sep 17 00:00:00 2001 From: Klaxon Date: Sat, 29 Dec 2018 00:44:59 +1000 Subject: [PATCH 1/2] add lorem ipsum generator --- src/core/config/Categories.json | 3 +- src/core/lib/LoremIpsum.mjs | 221 ++++++++++++++++++++ src/core/operations/LoremIpsumGenerator.mjs | 70 +++++++ 3 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 src/core/lib/LoremIpsum.mjs create mode 100644 src/core/operations/LoremIpsumGenerator.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 686c9842..3678a88b 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -375,7 +375,8 @@ "Parse QR Code", "Haversine distance", "Numberwang", - "XKCD Random Number" + "XKCD Random Number", + "Lorem Ipsum Generator" ] }, { diff --git a/src/core/lib/LoremIpsum.mjs b/src/core/lib/LoremIpsum.mjs new file mode 100644 index 00000000..9712a429 --- /dev/null +++ b/src/core/lib/LoremIpsum.mjs @@ -0,0 +1,221 @@ +/** + * Lorem Ipsum generator. + * + * @author Klaxon [klaxon@veyr.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + + /** + * generate lorem ipsum paragraphs. + * + * @param {number} length + * @returns {string} + */ +export function GenerateParagraphs(length=3) { + const paragraphs = []; + while (paragraphs.length < length) { + const paragraphLength = getRandomLength(PARAGRAPH_LENGTH_MEAN, PARAGRAPH_LENGTH_STD_DEV); + const sentences = []; + while (sentences.length < paragraphLength) { + const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV); + const sentence = getWords(sentenceLength); + sentences.push(formatSentence(sentence)); + } + paragraphs.push(formatParagraph(sentences)); + } + paragraphs[paragraphs.length-1] = paragraphs[paragraphs.length-1].slice(0, -2); + paragraphs[0] = replaceStart(paragraphs[0]); + return paragraphs.join(""); +} + +/** +* generate lorem ipsum sentences. +* +* @param {number} length +* @returns {string} +*/ +export function GenerateSentences(length=3) { + const sentences = []; + while (sentences.length < length) { + const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV); + const sentence = getWords(sentenceLength); + sentences.push(formatSentence(sentence)); + } + const paragraphs = sentencesToParagraphs(sentences); + return paragraphs.join(""); +} + +/** +* generate lorem ipsum words. +* +* @param {number} length +* @returns {string} +*/ +export function GenerateWords(length=3) { + const words = getWords(length); + const sentences = wordsToSentences(words); + const paragraphs = sentencesToParagraphs(sentences); + return paragraphs.join(""); +} + + /** + * generate lorem ipsum bytes. + * + * @param {number} length + * @returns {string} + */ +export function GenerateBytes(length=3) { + const str = GenerateWords(length/3); + return str.slice(0, length); +} + +/** + * get array of randomly selected words from the lorem ipsum wordList. + * + * @param {number} length + * @returns {string[]} + * @private + */ +function getWords(length=3) { + const words = []; + let word; + let previousWord; + while (words.length < length){ + do { + word = wordList[Math.floor(Math.random() * wordList.length)]; + } + while (previousWord === word); + words.push(word); + previousWord = word; + } + return words; +} + +/** + * convert an array or words into an array of sentences" + * + * @param {string[]} words + * @returns {string[]} + * @private + */ +function wordsToSentences(words) { + const sentences = []; + while (words.length > 0) { + const sentenceLength = getRandomLength(SENTENCE_LENGTH_MEAN, SENTENCE_LENGTH_STD_DEV); + if (sentenceLength <= words.length) { + sentences.push(formatSentence(words.splice(0, sentenceLength))); + } else { + sentences.push(formatSentence(words.splice(0, words.length))); + } + } + return sentences; +} + +/** + * convert an array or sentences into an array of paragraphs" + * + * @param {string[]} sentences + * @returns {string[]} + * @private + */ +function sentencesToParagraphs(sentences) { + const paragraphs = []; + while (sentences.length > 0) { + const paragraphLength = getRandomLength(PARAGRAPH_LENGTH_MEAN, PARAGRAPH_LENGTH_STD_DEV); + paragraphs.push(formatParagraph(sentences.splice(0, paragraphLength))); + } + paragraphs[paragraphs.length-1] = paragraphs[paragraphs.length-1].slice(0, -1); + paragraphs[0] = replaceStart(paragraphs[0]); + return paragraphs; +} + +/** + * format an array of words into a sentence. + * + * @param {string[]} words + * @returns {string} + * @private + */ +function formatSentence(words) { + //0.35 chance of a comma being added randomly to the sentence. + if (Math.random() < PROBABILITY_OF_A_COMMA) { + const pos = Math.round(Math.random()*(words.length-1)); + words[pos] +=","; + } + let sentence = words.join(" "); + sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1); + sentence += "."; + return sentence; +} + +/** + * format an array of sentences into a paragraph + * + * @param {string[]} sentences + * @returns {string} + * @private + */ +function formatParagraph(sentences) { + let paragraph = sentences.join(" "); + paragraph += "\n\n"; + return paragraph; +} + +/** + * get a random number based on a mean and standard deviation. + * + * @param {number} Mean + * @param {number} stdDev + * @returns {number} + * @private + */ +function getRandomLength(mean, stdDev) { + let length; + do { + length = Math.round((Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1)*stdDev+mean); + } + while (length <= 0); + return length; +} + +/** + * replace first 5 words with "Lorem ipsum dolor sit amet" + * + * @param {string[]} str + * @returns {string[]} + * @private + */ +function replaceStart(str) { + let words = str.split(" "); + if (words.length > 5) { + words.splice(0, 5, "Lorem", "ipsum", "dolor", "sit", "amet"); + return words.join(" "); + } else { + const lorem = ["Lorem", "ipsum", "dolor", "sit", "amet"]; + words = lorem.slice(0, words.length); + str = words.join(" "); + str += "."; + return str; + } +} + +const SENTENCE_LENGTH_MEAN = 15; +const SENTENCE_LENGTH_STD_DEV = 9; +const PARAGRAPH_LENGTH_MEAN = 5; +const PARAGRAPH_LENGTH_STD_DEV = 2; +const PROBABILITY_OF_A_COMMA = 0.35; + +const wordList = [ + "ad", "adipisicing", "aliqua", "aliquip", "amet", "anim", + "aute", "cillum", "commodo", "consectetur", "consequat", "culpa", + "cupidatat", "deserunt", "do", "dolor", "dolore", "duis", + "ea", "eiusmod", "elit", "enim", "esse", "est", + "et", "eu", "ex", "excepteur", "exercitation", "fugiat", + "id", "in", "incididunt", "ipsum", "irure", "labore", + "laboris", "laborum", "Lorem", "magna", "minim", "mollit", + "nisi", "non", "nostrud", "nulla", "occaecat", "officia", + "pariatur", "proident", "qui", "quis", "reprehenderit", "sint", + "sit", "sunt", "tempor", "ullamco", "ut", "velit", + "veniam", "voluptate", +]; diff --git a/src/core/operations/LoremIpsumGenerator.mjs b/src/core/operations/LoremIpsumGenerator.mjs new file mode 100644 index 00000000..228daaa1 --- /dev/null +++ b/src/core/operations/LoremIpsumGenerator.mjs @@ -0,0 +1,70 @@ +/** + * @author klaxon [klaxon@veyr.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import OperationError from "../errors/OperationError"; +import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum"; + +/** + * Lorem Ipsum Generator operation + */ +class LoremIpsumGenerator extends Operation { + + /** + * LoremIpsumGenerator constructor + */ + constructor() { + super(); + + this.name = "Lorem Ipsum Generator"; + this.module = "Default"; + this.description = "Generate varying length lorem ipsum placeholder text."; + this.infoURL = "https://wikipedia.org/wiki/Lorem_ipsum"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Length", + "type": "number", + "value": "3" + }, + { + "name": "Length in", + "type": "option", + "value": ["Paragraphs", "Sentences", "Words", "Bytes"] + } + + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [length, lengthType] = args; + if (length < 1){ + throw new OperationError("Length must be greater than 0"); + } + switch (lengthType) { + case "Paragraphs": + return GenerateParagraphs(length); + case "Sentences": + return GenerateSentences(length); + case "Words": + return GenerateWords(length); + case "Bytes": + return GenerateBytes(length); + default: + throw new OperationError("invalid lengthType"); + + } + } + +} + +export default LoremIpsumGenerator; From c49a770c59adb28cfd082dc2c935f7c900902625 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Wed, 9 Jan 2019 16:36:34 +0000 Subject: [PATCH 2/2] Tidied up Lorem Ipsum op --- CHANGELOG.md | 5 ++ src/core/config/Categories.json | 4 +- src/core/lib/LoremIpsum.mjs | 81 ++++++++++--------- ...umGenerator.mjs => GenerateLoremIpsum.mjs} | 12 +-- 4 files changed, 58 insertions(+), 44 deletions(-) rename src/core/operations/{LoremIpsumGenerator.mjs => GenerateLoremIpsum.mjs} (85%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a71bb41..d9b8eff0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master). +### [8.20.0] - 2019-01-09 +- 'Generate Lorem Ipsum' operation added [@klaxon1] | [#455] + ### [8.19.0] - 2018-12-30 - UI test suite added to confirm that the app loads correctly in a reasonable time and that various operations from each module can be run [@n1474335] | [#458] @@ -88,6 +91,7 @@ All major and minor version changes will be documented in this file. Details of +[8.20.0]: https://github.com/gchq/CyberChef/releases/tag/v8.20.0 [8.19.0]: https://github.com/gchq/CyberChef/releases/tag/v8.19.0 [8.18.0]: https://github.com/gchq/CyberChef/releases/tag/v8.18.0 [8.17.0]: https://github.com/gchq/CyberChef/releases/tag/v8.17.0 @@ -159,4 +163,5 @@ All major and minor version changes will be documented in this file. Details of [#446]: https://github.com/gchq/CyberChef/pull/446 [#448]: https://github.com/gchq/CyberChef/pull/448 [#449]: https://github.com/gchq/CyberChef/pull/449 +[#455]: https://github.com/gchq/CyberChef/pull/455 [#458]: https://github.com/gchq/CyberChef/pull/458 diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 3678a88b..3e792b99 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -374,9 +374,9 @@ "Generate QR Code", "Parse QR Code", "Haversine distance", + "Generate Lorem Ipsum", "Numberwang", - "XKCD Random Number", - "Lorem Ipsum Generator" + "XKCD Random Number" ] }, { diff --git a/src/core/lib/LoremIpsum.mjs b/src/core/lib/LoremIpsum.mjs index 9712a429..d7fff69b 100644 --- a/src/core/lib/LoremIpsum.mjs +++ b/src/core/lib/LoremIpsum.mjs @@ -2,16 +2,16 @@ * Lorem Ipsum generator. * * @author Klaxon [klaxon@veyr.com] - * @copyright Crown Copyright 2016 + * @copyright Crown Copyright 2018 * @license Apache-2.0 */ - /** - * generate lorem ipsum paragraphs. - * - * @param {number} length - * @returns {string} - */ +/** + * Generate lorem ipsum paragraphs. + * + * @param {number} length + * @returns {string} + */ export function GenerateParagraphs(length=3) { const paragraphs = []; while (paragraphs.length < length) { @@ -29,12 +29,13 @@ export function GenerateParagraphs(length=3) { return paragraphs.join(""); } + /** -* generate lorem ipsum sentences. -* -* @param {number} length -* @returns {string} -*/ + * Generate lorem ipsum sentences. + * + * @param {number} length + * @returns {string} + */ export function GenerateSentences(length=3) { const sentences = []; while (sentences.length < length) { @@ -46,12 +47,13 @@ export function GenerateSentences(length=3) { return paragraphs.join(""); } + /** -* generate lorem ipsum words. -* -* @param {number} length -* @returns {string} -*/ + * Generate lorem ipsum words. + * + * @param {number} length + * @returns {string} + */ export function GenerateWords(length=3) { const words = getWords(length); const sentences = wordsToSentences(words); @@ -59,19 +61,21 @@ export function GenerateWords(length=3) { return paragraphs.join(""); } - /** - * generate lorem ipsum bytes. - * - * @param {number} length - * @returns {string} - */ + +/** + * Generate lorem ipsum bytes. + * + * @param {number} length + * @returns {string} + */ export function GenerateBytes(length=3) { const str = GenerateWords(length/3); return str.slice(0, length); } + /** - * get array of randomly selected words from the lorem ipsum wordList. + * Get array of randomly selected words from the lorem ipsum wordList. * * @param {number} length * @returns {string[]} @@ -84,16 +88,16 @@ function getWords(length=3) { while (words.length < length){ do { word = wordList[Math.floor(Math.random() * wordList.length)]; - } - while (previousWord === word); + } while (previousWord === word); words.push(word); previousWord = word; } return words; } + /** - * convert an array or words into an array of sentences" + * Convert an array of words into an array of sentences * * @param {string[]} words * @returns {string[]} @@ -112,8 +116,9 @@ function wordsToSentences(words) { return sentences; } + /** - * convert an array or sentences into an array of paragraphs" + * Convert an array of sentences into an array of paragraphs * * @param {string[]} sentences * @returns {string[]} @@ -130,15 +135,16 @@ function sentencesToParagraphs(sentences) { return paragraphs; } + /** - * format an array of words into a sentence. + * Format an array of words into a sentence. * * @param {string[]} words * @returns {string} * @private */ function formatSentence(words) { - //0.35 chance of a comma being added randomly to the sentence. + // 0.35 chance of a comma being added randomly to the sentence. if (Math.random() < PROBABILITY_OF_A_COMMA) { const pos = Math.round(Math.random()*(words.length-1)); words[pos] +=","; @@ -149,8 +155,9 @@ function formatSentence(words) { return sentence; } + /** - * format an array of sentences into a paragraph + * Format an array of sentences into a paragraph. * * @param {string[]} sentences * @returns {string} @@ -162,10 +169,11 @@ function formatParagraph(sentences) { return paragraph; } + /** - * get a random number based on a mean and standard deviation. + * Get a random number based on a mean and standard deviation. * - * @param {number} Mean + * @param {number} mean * @param {number} stdDev * @returns {number} * @private @@ -174,13 +182,13 @@ function getRandomLength(mean, stdDev) { let length; do { length = Math.round((Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1)*stdDev+mean); - } - while (length <= 0); + } while (length <= 0); return length; } + /** - * replace first 5 words with "Lorem ipsum dolor sit amet" + * Replace first 5 words with "Lorem ipsum dolor sit amet" * * @param {string[]} str * @returns {string[]} @@ -200,6 +208,7 @@ function replaceStart(str) { } } + const SENTENCE_LENGTH_MEAN = 15; const SENTENCE_LENGTH_STD_DEV = 9; const PARAGRAPH_LENGTH_MEAN = 5; diff --git a/src/core/operations/LoremIpsumGenerator.mjs b/src/core/operations/GenerateLoremIpsum.mjs similarity index 85% rename from src/core/operations/LoremIpsumGenerator.mjs rename to src/core/operations/GenerateLoremIpsum.mjs index 228daaa1..fb5ecd17 100644 --- a/src/core/operations/LoremIpsumGenerator.mjs +++ b/src/core/operations/GenerateLoremIpsum.mjs @@ -9,17 +9,17 @@ import OperationError from "../errors/OperationError"; import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum"; /** - * Lorem Ipsum Generator operation + * Generate Lorem Ipsum operation */ -class LoremIpsumGenerator extends Operation { +class GenerateLoremIpsum extends Operation { /** - * LoremIpsumGenerator constructor + * GenerateLoremIpsum constructor */ constructor() { super(); - this.name = "Lorem Ipsum Generator"; + this.name = "Generate Lorem Ipsum"; this.module = "Default"; this.description = "Generate varying length lorem ipsum placeholder text."; this.infoURL = "https://wikipedia.org/wiki/Lorem_ipsum"; @@ -60,11 +60,11 @@ class LoremIpsumGenerator extends Operation { case "Bytes": return GenerateBytes(length); default: - throw new OperationError("invalid lengthType"); + throw new OperationError("Invalid length type"); } } } -export default LoremIpsumGenerator; +export default GenerateLoremIpsum;