diff --git a/pages/src/localdev.ts b/pages/src/localdev.ts index dcc73f7e6..1c96b1644 100644 --- a/pages/src/localdev.ts +++ b/pages/src/localdev.ts @@ -37,6 +37,8 @@ import { ESLRelatedTarget } from '@exadel/esl/modules/all'; +import {ESLRandomText} from '@exadel/esl/modules/esl-random-text/core'; + import '@exadel/esl/modules/esl-media/providers/iframe-provider'; import '@exadel/esl/modules/esl-media/providers/html5/audio-provider'; import '@exadel/esl/modules/esl-media/providers/html5/video-provider'; @@ -73,6 +75,9 @@ ESLDemoBackLink.register(); ESLDemoBanner.register(); ESLDemoSwipeArea.register(); +// Test Content +ESLRandomText.register('lorem-ipsum'); + // Register ESL Components ESLImage.register(); ESLMedia.register(); diff --git a/pages/views/draft/accordion-regression.njk b/pages/views/draft/accordion-regression.njk index f7987ddce..cc40857d7 100644 --- a/pages/views/draft/accordion-regression.njk +++ b/pages/views/draft/accordion-regression.njk @@ -5,8 +5,6 @@ name: Accordion (Regression) tags: [draft] icon: examples/accordion.svg --- -{% import 'lorem.njk' as lorem %} -

Simple multiple accordion with at least 3 and simultaneously maximum open panels

@@ -21,7 +19,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -31,7 +29,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -41,7 +39,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -51,7 +49,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -61,7 +59,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -71,7 +69,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -93,7 +91,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -103,7 +101,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -113,7 +111,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -141,7 +139,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -151,7 +149,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -161,7 +159,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -189,7 +187,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -199,7 +197,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
@@ -209,7 +207,7 @@ icon: examples/accordion.svg
- {{ lorem.paragraphs(1) }} +
diff --git a/src/modules/esl-random-text/README.md b/src/modules/esl-random-text/README.md new file mode 100644 index 000000000..c9d6117a3 --- /dev/null +++ b/src/modules/esl-random-text/README.md @@ -0,0 +1,59 @@ +# [ESL](../../../) Random Text + +Version: *1.0.0-beta*. + +Authors: *Alexey Stsefanovich*. + + + +**ESLRandomText** is a custom tag and utility that allows to generate random text from a given set of words `DICTIONARY`. + +### Getting Started: + +1. Register ESLRandomText component +```js + import {ESLRandomText} from '@exadel/esl'; + ESLRandomText.register(); +``` + +2. (Optionally) provide a custom dictionary using `ESLRandomText.DICTIONARY` static property: +```js + ESLRandomText.DICTIONARY = ['word1', 'word2', 'word3']; +``` + +3. Add the `` custom tag and provide text limitations (with `paragraphs` and `wordsPerParagraph` attributes): +```html + +``` +```html + +``` +```html + +``` + +### Attributes: + +- `paragraphs` \[number] - number of paragraphs to generate (can be float) +- `wordsPerParagraphs` \[number] - number of words to generate per paragraph +- `shuffle` \[boolean] - choose words randomly from the dictionary (use words in `DICTIONARY` order otherwise) + + +### Static API: + +- `ESLRandomText.DICTIONARY` - static property that contains a dictionary of words to generate random text from. + "Lorem ipsum" is used by default. + +- `ESLRandomText.WORDS_PER_PARAGRAPH` - static property that contains a default number of words per paragraph. + 100 is used by default. + +- `ESLRandomText.WORDS_PER_SENTENCE` - static property that contains a default number of words per single sentence. + 10 is used by default. + +- `ESLRandomText.generateText(words, shuffle)` - static method that generates random text from the dictionary. + Returns a string with `words` number of words. If `shuffle` is `true` words are chosen randomly from the dictionary. + Otherwise, words are chosen in the dictionary order. + +- `ESLRandomText.generateTextHTML(words, wordsPerParagraph, shuffle)` - static method that generates random text from the dictionary. + Returns an HTML string with `words` number of words and `wordsPerParagraph` number of words per paragraph. + If `shuffle` is `true` words are chosen randomly from the dictionary. Otherwise, words are chosen in the dictionary order. diff --git a/src/modules/esl-random-text/core.ts b/src/modules/esl-random-text/core.ts new file mode 100644 index 000000000..fb69d13ab --- /dev/null +++ b/src/modules/esl-random-text/core.ts @@ -0,0 +1,2 @@ +export * from './core/esl-random-text'; +export type * from './core/esl-random-text.shape'; diff --git a/src/modules/esl-random-text/core/esl-random-text.shape.ts b/src/modules/esl-random-text/core/esl-random-text.shape.ts new file mode 100644 index 000000000..b664da35a --- /dev/null +++ b/src/modules/esl-random-text/core/esl-random-text.shape.ts @@ -0,0 +1,34 @@ +import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape'; +import type {ESLRandomText} from './esl-random-text'; + +export interface ESLRandomTextShape extends ESLBaseElementShape { + /** + * Choose words randomly from {@link DICTIONARY} rather than sequentially + * @see ESLRandomText#shuffle + */ + shuffle: boolean; + + /** + * Maximum number of paragraphs in generated text + * @see ESLRandomText#paragraphs + */ + paragraphs: number; + + /** + * Maximum number of words in paragraph + * @see ESLRandomText#wordsPerParagraph + */ + wordsPerParagraph: number; + + /** No children allowed */ + children: never | []; +} + +declare global { + namespace JSX { + export interface IntrinsicElements { + /** {@link ESLRandomTextShape} custom tag */ + 'esl-random-text': ESLRandomTextShape; + } + } +} diff --git a/src/modules/esl-random-text/core/esl-random-text.ts b/src/modules/esl-random-text/core/esl-random-text.ts new file mode 100644 index 000000000..0ec28e92b --- /dev/null +++ b/src/modules/esl-random-text/core/esl-random-text.ts @@ -0,0 +1,130 @@ +import {ESLBaseElement} from '../../esl-base-element/core'; +import {attr, boolAttr} from '../../esl-utils/decorators'; +import {capitalize} from '../../esl-utils/misc/format'; + +export class ESLRandomText extends ESLBaseElement { + public static override readonly is = 'esl-random-text'; + public static readonly observedAttributes = [ + 'paragraphs', + 'words-per-paragraph', + 'shuffle' + ]; + + /** Last used word index in dictionary */ + protected static pointer: number = -1; + /** Words dictionary to use in random text generation. */ + public static DICTIONARY: string[] = [ + 'lorem', 'ipsum', 'dolor', 'sit', 'amet', + 'consectetur', 'adipiscing', 'elit', 'curabitur', + 'ultrices', 'et', 'mi', 'suscipit', 'eget', 'vulputate', 'ante', + 'proin', 'vel', 'pretium', 'enim', 'vivamus', 'venenatis', 'eu', + 'urna', 'tempor', 'blandit', 'nullam', 'pellentesque', 'metus', + 'rhoncus', 'mauris', 'mollis', 'neque', 'sed', 'tincidunt', 'tellus', + 'nunc', 'ac', 'nulla', 'ut', 'purus', 'etiam', 'id', 'dui', 'justo', + 'sapien', 'scelerisque', 'viverra', 'ligula', 'aenean', 'porta', + 'condimentum', 'nibh', 'dictum', 'congue', 'odio', 'facilisis', + 'finibus', 'mattis', 'vehicula', 'lacinia', 'risus', 'placerat', + 'augue', 'fringilla', 'at', 'facilisi', 'arcu', 'diam', 'laoreet' + ]; + + /** Number of words in sentence */ + public static readonly WORDS_PER_SENTENCE = 10; + /** Number of words in paragraph */ + public static readonly WORDS_PER_PARAGRAPH = 100; + + /** Choose words randomly from {@link DICTIONARY} rather than sequentially */ + @boolAttr() public shuffle: boolean; + /** Maximum number of paragraphs in generated text */ + @attr({parser: parseFloat, defaultValue: 1}) public paragraphs: number; + /** Maximum number of words in paragraph */ + @attr({parser: parseInt, defaultValue: 100}) public wordsPerParagraph: number; + + /** Redraws random text content */ + public refresh(): void { + // Normalize values + if (isNaN(this.paragraphs)) this.paragraphs = 1; + if (isNaN(this.wordsPerParagraph)) this.wordsPerParagraph = 100; + + const {paragraphs, wordsPerParagraph, shuffle} = this; + const words = Math.ceil(paragraphs * wordsPerParagraph); + this.style.display = 'contents'; + this.innerHTML = ESLRandomText.generateTextHTML(words, wordsPerParagraph, shuffle); + } + + protected override connectedCallback(): void { + super.connectedCallback(); + this.refresh(); + } + protected override disconnectedCallback(): void { + this.innerHTML = ''; + this.style.display = ''; + super.disconnectedCallback(); + } + protected override attributeChangedCallback(name: string, oldValue: string, newValue: string): void { + this.refresh(); + } + + /** + * Generates a dummy word. + * @param random - choose word randomly from {@link DICTIONARY} rather than sequentially + */ + protected static generateWord(random = false): string { + if (random) return this.DICTIONARY[Math.floor(Math.random() * this.DICTIONARY.length)]; + this.pointer = (this.pointer + 1) % this.DICTIONARY.length; + return this.DICTIONARY[this.pointer]; + } + + /** + * Builds a dummy text + * @param words - number of words in text + * @param shuffle - shuffle words randomly + */ + protected static buildText(words: number, shuffle: boolean = false): string { + const sentences = []; + while (words > 0) { + const count = Math.min(this.WORDS_PER_SENTENCE, words); + const buffer = Array.apply(0, new Array(count)); + const sentence = buffer.map(() => this.generateWord(shuffle)).join(' '); + sentences.push(capitalize(sentence) + '.'); + words -= this.WORDS_PER_SENTENCE; + } + return sentences.join(' '); + } + + /** + * Generates a dummy text. + * @param words - number of words in text + * @param shuffle - shuffle words randomly + */ + public static generateText(words: number, shuffle: boolean = false): string { + this.pointer = -1; + return this.buildText(words, shuffle); + } + + /** + * Generates a dummy text. + * @param words - number of words in text + * @param wordsPerParagraph - number of words in paragraph + * @param shuffle - shuffle words randomly + */ + public static generateTextHTML( + words: number = this.WORDS_PER_PARAGRAPH, + wordsPerParagraph = Math.min(this.WORDS_PER_PARAGRAPH, words), + shuffle = false + ): string { + this.pointer = -1; + const result = []; + while (words > 0) { + const text = this.buildText(Math.min(wordsPerParagraph, words), shuffle); + result.push(`

${text}

`); + words -= wordsPerParagraph; + } + return result.join(''); + } +} + +declare global { + export interface HTMLElementTagNameMap { + 'esl-random-text': ESLRandomText; + } +}