feat: externalized tool configuration

This commit is contained in:
Corentin Thomasset 2021-05-28 19:44:27 +02:00
parent c3adfe30ec
commit 690bd099ef
No known key found for this signature in database
GPG key ID: DBD997E935996158
31 changed files with 387 additions and 300 deletions

View file

@ -0,0 +1,103 @@
<template>
<ToolWrapper :config="$toolConfig">
<v-slider v-model="paragraphs" min="1" max="20" label="Paragraphs" thumb-label />
<v-range-slider
v-model="sentencePerParagraph"
min="1"
max="50"
label="Sentences per paragraph"
thumb-label
/>
<v-range-slider
v-model="wordPerSentence"
min="1"
max="50"
label="Words per sentence"
thumb-label
hide-details
/>
<v-checkbox v-model="startWithLoremIpsum" label="Start with 'Lorem ipsum ...'" hide-details />
<v-checkbox v-model="asHTML" label="As HTML" />
<v-textarea
v-model="loremIpsum"
outlined
readonly
hide-details="auto"
rows="15"
class="text-justify"
/>
<div class="text-center mt-4">
<v-btn depressed @click="copy(loremIpsum)">
Copy
</v-btn>
</div>
</ToolWrapper>
</template>
<tool>
title: 'Lorem ipsum generator'
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.'
icon: 'mdi-comment-text'
keywords: ['Lorem', 'ipsum', 'dolor', 'sit', 'amet']
path: '/lorem-ipsum-generator'
</tool>
<script lang="ts">
import {Component} from 'nuxt-property-decorator'
import {CopyableMixin} from '~/mixins/copyable.mixin'
import Tool from '~/components/Tool.vue'
import {randFromArray, randIntFromInterval} from '~/utils/random'
const vocabulary = ['a', 'ac', 'accumsan', 'ad', 'adipiscing', 'aenean', 'aliquam', 'aliquet', 'amet', 'ante', 'aptent', 'arcu', 'at', 'auctor', 'bibendum', 'blandit', 'class', 'commodo', 'condimentum', 'congue', 'consectetur', 'consequat', 'conubia', 'convallis', 'cras', 'cubilia', 'cum', 'curabitur', 'curae', 'dapibus', 'diam', 'dictum', 'dictumst', 'dignissim', 'dolor', 'donec', 'dui', 'duis', 'egestas', 'eget', 'eleifend', 'elementum', 'elit', 'enim', 'erat', 'eros', 'est', 'et', 'etiam', 'eu', 'euismod', 'facilisi', 'faucibus', 'felis', 'fermentum', 'feugiat', 'fringilla', 'fusce', 'gravida', 'habitant', 'habitasse', 'hac', 'hendrerit', 'himenaeos', 'iaculis', 'id', 'imperdiet', 'in', 'inceptos', 'integer', 'interdum', 'ipsum', 'justo', 'lacinia', 'lacus', 'laoreet', 'lectus', 'leo', 'ligula', 'litora', 'lobortis', 'lorem', 'luctus', 'maecenas', 'magna', 'magnis', 'malesuada', 'massa', 'mattis', 'mauris', 'metus', 'mi', 'molestie', 'mollis', 'montes', 'morbi', 'mus', 'nam', 'nascetur', 'natoque', 'nec', 'neque', 'netus', 'nisi', 'nisl', 'non', 'nostra', 'nulla', 'nullam', 'nunc', 'odio', 'orci', 'ornare', 'parturient', 'pellentesque', 'penatibus', 'per', 'pharetra', 'phasellus', 'placerat', 'platea', 'porta', 'porttitor', 'posuere', 'potenti', 'praesent', 'pretium', 'primis', 'proin', 'pulvinar', 'purus', 'quam', 'quis', 'quisque', 'rhoncus', 'ridiculus', 'risus', 'rutrum', 'sagittis', 'sapien', 'scelerisque', 'sed', 'sem', 'semper', 'senectus', 'sit', 'sociis', 'sociosqu', 'sodales', 'sollicitudin', 'suscipit', 'suspendisse', 'taciti', 'tellus', 'tempor', 'tempus', 'tincidunt', 'torquent', 'tortor', 'turpis', 'ullamcorper', 'ultrices', 'ultricies', 'urna', 'varius', 'vehicula', 'vel', 'velit', 'venenatis', 'vestibulum', 'vitae', 'vivamus', 'viverra', 'volutpat', 'vulputate']
const firstSentence = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
const generateSentence = (length: number) => {
let sentence = Array.from({length}).map(() => randFromArray(vocabulary)).join(' ')
sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1) + '.'
return sentence
}
@Component({
mixins: [CopyableMixin]
})
export default class LoremIpsumGenerator extends Tool {
paragraphs = 1
sentencePerParagraph = [3, 8]
wordPerSentence = [8, 15]
startWithLoremIpsum = true
asHTML = false
get loremIpsum() {
const lorem = Array
.from({length: this.paragraphs})
.map(() => {
const length = randIntFromInterval(this.sentencePerParagraph[0], this.sentencePerParagraph[1])
return Array.from({length}).map(() => {
const wordCount = randIntFromInterval(this.wordPerSentence[0], this.wordPerSentence[1])
return generateSentence(wordCount)
})
})
if (this.startWithLoremIpsum) {
lorem[0][0] = firstSentence
}
let result
if (this.asHTML) {
result = `<p>${lorem.map(s => s.join(' ')).join('</p>\n\n<p>')}</p>`
} else {
result = lorem.map(s => s.join(' ')).join('\n\n')
}
return result
}
}
</script>
<style scoped lang="less">
::v-deep {
.v-label {
// To align labels
min-width: 200px !important;
}
}
</style>

93
tools/text/text-stats.vue Normal file
View file

@ -0,0 +1,93 @@
<template>
<ToolWrapper :config="$toolConfig">
<v-textarea
v-model="text"
outlined
label="Input text"
hide-details
auto-grow
/>
<div>{{ $toolListFlat }}</div>
<table>
<tbody>
<tr>
<td><strong>Character count:</strong></td>
<td>{{ textLength }}</td>
</tr>
<tr>
<td><strong>Word count:</strong></td>
<td>{{ textWordCount }}</td>
</tr>
<tr>
<td><strong>Line count:</strong></td>
<td>{{ textLineCount }}</td>
</tr>
<tr>
<td><strong>Byte size:</strong></td>
<td>{{ textSize }}</td>
</tr>
</tbody>
</table>
</ToolWrapper>
</template>
<tool>
title: 'Text stats'
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.'
icon: mdi-text
keywords: [ length, character, count ]
path: '/text-stats'
</tool>
<script lang="ts">
import {Component} from 'nuxt-property-decorator'
import {CopyableMixin} from '~/mixins/copyable.mixin'
import Tool from '~/components/Tool.vue'
import {formatBytes} from '~/utils/convert'
@Component({
mixins: [CopyableMixin]
})
export default class TextStats extends Tool {
text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.'
created() {
}
get textLength() {
return this.text.length
}
get textWordCount() {
return this.text.split(/\s+/).length
}
get textLineCount() {
return this.text.split(/\r\n|\r|\n/).length
}
get textSize() {
return formatBytes(Uint8Array.from(this.text as unknown as ArrayLike<number>).buffer.byteLength, 3)
}
}
</script>
<style scoped lang="less">
table {
width: 100%;
tr {
td {
width: 50%;
padding: 5px;
&:first-child {
text-align: right;
}
}
}
}
</style>