Compare commits

...

3 Commits

Author SHA1 Message Date
sharevb
ffd5a9d98c
Merge 2a4462ccaf into b430baef40 2024-07-07 10:26:12 +00:00
ShareVB
2a4462ccaf chore: fix strange corepack message
Fix corepack claiming strange thing : UsageError: This project is configured to use yarn because /home/runner/work/it-tools/it-tools/package.json has a "packageManager" field
2024-07-07 12:26:05 +02:00
sharevb
a465baf86d feat(Lorem Ipsum Generator): generate multi language/script
Fix #1080
2024-07-07 12:25:54 +02:00
9 changed files with 350 additions and 195 deletions

2
components.d.ts vendored
View File

@ -144,7 +144,9 @@ declare module '@vue/runtime-core' {
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
NMenu: typeof import('naive-ui')['NMenu']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSlider: typeof import('naive-ui')['NSlider']
NSpin: typeof import('naive-ui')['NSpin']
NSwitch: typeof import('naive-ui')['NSwitch']
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']

View File

@ -49,6 +49,7 @@
"@vueuse/router": "^10.0.0",
"bcryptjs": "^2.4.3",
"change-case": "^4.1.2",
"chinesegen": "^0.3.3",
"colord": "^2.9.3",
"composerize-ts": "^0.6.2",
"country-code-lookup": "^0.1.0",
@ -69,6 +70,7 @@
"jwt-decode": "^3.1.2",
"libphonenumber-js": "^1.10.28",
"lodash": "^4.17.21",
"lorem-ipsum-japanese": "^1.0.1",
"marked": "^10.0.0",
"mathjs": "^11.9.1",
"mime-types": "^2.1.35",
@ -138,5 +140,6 @@
"vitest": "^0.34.0",
"workbox-window": "^7.0.0",
"zx": "^7.2.1"
}
},
"packageManager": "pnpm@8.15.3"
}

View File

@ -47,6 +47,9 @@ dependencies:
change-case:
specifier: ^4.1.2
version: 4.1.2
chinesegen:
specifier: ^0.3.3
version: 0.3.3
colord:
specifier: ^2.9.3
version: 2.9.3
@ -107,6 +110,9 @@ dependencies:
lodash:
specifier: ^4.17.21
version: 4.17.21
lorem-ipsum-japanese:
specifier: ^1.0.1
version: 1.0.1
marked:
specifier: ^10.0.0
version: 10.0.0
@ -3354,7 +3360,7 @@ packages:
dependencies:
'@unhead/dom': 0.5.1
'@unhead/schema': 0.5.1
'@vueuse/shared': 10.8.0(vue@3.3.4)
'@vueuse/shared': 10.11.0(vue@3.3.4)
unhead: 0.5.1
vue: 3.3.4
transitivePeerDependencies:
@ -3987,19 +3993,19 @@ packages:
- vue
dev: false
/@vueuse/shared@10.3.0(vue@3.3.4):
resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==}
/@vueuse/shared@10.11.0(vue@3.3.4):
resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==}
dependencies:
vue-demi: 0.14.5(vue@3.3.4)
vue-demi: 0.14.8(vue@3.3.4)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
dev: false
/@vueuse/shared@10.8.0(vue@3.3.4):
resolution: {integrity: sha512-dUdy6zwHhULGxmr9YUg8e+EnB39gcM4Fe2oKBSrh3cOsV30JcMPtsyuspgFCUo5xxFNaeMf/W2yyKfST7Bg8oQ==}
/@vueuse/shared@10.3.0(vue@3.3.4):
resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==}
dependencies:
vue-demi: 0.14.7(vue@3.3.4)
vue-demi: 0.14.5(vue@3.3.4)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@ -4447,6 +4453,13 @@ packages:
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
dev: true
/chinesegen@0.3.3:
resolution: {integrity: sha512-iwWTX4sPT8BwYaZr3SFr4D1tkToc1SXQ90AwnW8prCcGhv2nrOW38LStV27HtbHPUYTEhYbfG1KHoXRtqVBUFg==}
hasBin: true
dependencies:
minimist: 1.2.8
dev: false
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@ -6720,6 +6733,13 @@ packages:
is-unicode-supported: 0.1.0
dev: true
/lorem-ipsum-japanese@1.0.1:
resolution: {integrity: sha512-lL4XsigcYfSIsuUmHuoLB4wa71teS7XCx5tDgyZh6SoQmtwn0NTTMM54F69hy5aT8dkExH41hKmmOh1cET6I/w==}
hasBin: true
dependencies:
optimist: 0.3.7
dev: false
/loupe@2.3.6:
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
dependencies:
@ -6932,7 +6952,6 @@ packages:
/minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true
/mlly@1.4.0:
resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==}
@ -7179,6 +7198,12 @@ packages:
is-wsl: 2.2.0
dev: true
/optimist@0.3.7:
resolution: {integrity: sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==}
dependencies:
wordwrap: 0.0.3
dev: false
/optionator@0.9.3:
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
engines: {node: '>= 0.8.0'}
@ -9158,8 +9183,8 @@ packages:
vue: 3.3.4
dev: false
/vue-demi@0.14.7(vue@3.3.4):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
/vue-demi@0.14.8(vue@3.3.4):
resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
@ -9371,6 +9396,11 @@ packages:
stackback: 0.0.2
dev: true
/wordwrap@0.0.3:
resolution: {integrity: sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==}
engines: {node: '>=0.4.0'}
dev: false
/workbox-background-sync@7.0.0:
resolution: {integrity: sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==}
dependencies:
@ -9449,6 +9479,7 @@ packages:
/workbox-google-analytics@7.0.0:
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
dependencies:
workbox-background-sync: 7.0.0
workbox-core: 7.0.0

View File

@ -1,7 +1,8 @@
import { useRouteQuery } from '@vueuse/router';
import { computed } from 'vue';
import { useStorage } from '@vueuse/core';
export { useQueryParam };
export { useQueryParam, useQueryParamOrStorage };
const transformers = {
number: {
@ -16,6 +17,12 @@ const transformers = {
fromQuery: (value: string) => value.toLowerCase() === 'true',
toQuery: (value: boolean) => (value ? 'true' : 'false'),
},
object: {
fromQuery: (value: string) => {
return JSON.parse(value);
},
toQuery: (value: object) => JSON.stringify(value),
},
};
function useQueryParam<T>({ name, defaultValue }: { name: string; defaultValue: T }) {
@ -33,3 +40,27 @@ function useQueryParam<T>({ name, defaultValue }: { name: string; defaultValue:
},
});
}
function useQueryParamOrStorage<T>({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue: T }) {
const type = typeof defaultValue;
const transformer = transformers[type as keyof typeof transformers] ?? transformers.string;
const storageRef = useStorage(storageName, defaultValue);
const proxyDefaultValue = transformer.toQuery(defaultValue as never);
const proxy = useRouteQuery(name, proxyDefaultValue);
const r = ref(defaultValue);
watch(r,
(value) => {
proxy.value = transformer.toQuery(value as never);
storageRef.value = value as never;
},
{ deep: true });
r.value = (proxy.value && proxy.value !== proxyDefaultValue
? transformer.fromQuery(proxy.value) as unknown as T
: storageRef.value as T) as never;
return r;
}

View File

@ -0,0 +1,7 @@
declare module 'chinesegen' {
export default function lorem(config: {
count: number,
}): {
text: string
};
}

View File

@ -1,185 +1,39 @@
import _ from 'lodash';
import loremIpsumJapanese from 'lorem-ipsum-japanese';
import chinesegen from 'chinesegen';
import languageLorems from './lorem-ipsum.i18n.json';
import { randFromArray } 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.';
function generateSentence(length: number) {
export function getSupportedLanguages() {
return _.union(
_.flatten(_.chain(languageLorems).map(l => l.languages).value()),
['Japanese', 'Chinese'])
.sort();
}
function generateSentence(language: string, length: number) {
if (language === 'Japanese') {
return loremIpsumJapanese({
count: length,
units: 'words',
});
}
if (language === 'Chinese') {
return chinesegen({ count: length }).text;
}
if (language === 'Emoticon') {
const loremIcons = _.find(languageLorems, ({ languages }) => languages.includes(language))?.loremIpsum || '';
const iconsChars = [...loremIcons];
return Array.from({ length })
.map(() => randFromArray(iconsChars))
.join(' ');
}
const vocabulary = _.find(languageLorems, ({ languages }) => languages.includes(language))?.loremIpsum?.split(' ') || [];
const sentence = Array.from({ length })
.map(() => randFromArray(vocabulary))
.join(' ');
@ -193,15 +47,17 @@ export function generateLoremIpsum({
wordCount = 10,
startWithLoremIpsum = true,
asHTML = false,
language = 'English',
}: {
paragraphCount?: number
sentencePerParagraph?: number
wordCount?: number
startWithLoremIpsum?: boolean
asHTML?: boolean
language?: string
}) {
const paragraphs = Array.from({ length: paragraphCount }).map(() =>
Array.from({ length: sentencePerParagraph }).map(() => generateSentence(wordCount)),
Array.from({ length: sentencePerParagraph }).map(() => generateSentence(language, wordCount)),
);
if (startWithLoremIpsum) {

View File

@ -1,14 +1,17 @@
<script setup lang="ts">
import { generateLoremIpsum } from './lorem-ipsum-generator.service';
import { generateLoremIpsum, getSupportedLanguages } from './lorem-ipsum-generator.service';
import { useCopy } from '@/composable/copy';
import { useQueryParamOrStorage } from '@/composable/queryParams';
import { randIntFromInterval } from '@/utils/random';
const paragraphs = ref(1);
const sentences = ref([3, 8]);
const words = ref([8, 15]);
const paragraphs = useStorage('lorem:paragraphs', 1);
const sentences = useStorage('lorem:sentences', [3, 8]);
const words = useStorage('lorem:words', [8, 15]);
const startWithLoremIpsum = ref(true);
const asHTML = ref(false);
const language = useQueryParamOrStorage({ defaultValue: 'English', storageName: 'lorem:lang', name: 'lang' });
const supportedLanguages = getSupportedLanguages();
const loremIpsumText = computed(() =>
generateLoremIpsum({
paragraphCount: paragraphs.value,
@ -16,6 +19,7 @@ const loremIpsumText = computed(() =>
sentencePerParagraph: randIntFromInterval(sentences.value[0], sentences.value[1]),
wordCount: randIntFromInterval(words.value[0], words.value[1]),
startWithLoremIpsum: startWithLoremIpsum.value,
language: language.value,
}),
);
const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to the clipboard' });
@ -23,6 +27,13 @@ const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to
<template>
<c-card>
<c-select
v-model:value="language"
searchable
label="Language:"
:options="Object.values(supportedLanguages)"
mb-2
/>
<n-form-item label="Paragraphs" :show-feedback="false" label-width="200" label-placement="left">
<n-slider v-model:value="paragraphs" :step="1" :min="1" :max="20" />
</n-form-item>

View File

@ -0,0 +1,6 @@
declare module 'lorem-ipsum-japanese' {
export default function lorem(config: {
count: number,
units: 'words' | 'sentences' | 'paragraphs',
}): string;
}

File diff suppressed because one or more lines are too long