@miso.ai/lorem 0.9.1-beta.19 → 0.10.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/data.js +1 -1
- package/lib/fields.js +111 -96
- package/lib/index.js +8 -5
- package/lib/lorem.js +25 -134
- package/lib/markdown.js +295 -253
- package/lib/prng.js +97 -0
- package/lib/utils.js +20 -63
- package/lib/wordbank.js +182 -0
- package/lib/words.js +168 -181
- package/package.json +3 -2
- package/test/prng.test.js +86 -0
package/bin/data.js
CHANGED
|
@@ -6,7 +6,7 @@ import yaml from 'js-yaml';
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
7
|
|
|
8
8
|
const WORDS_YAML = resolve(__dirname, '../data/words.yaml');
|
|
9
|
-
const WORDS_JS = resolve(__dirname, '../lib/
|
|
9
|
+
const WORDS_JS = resolve(__dirname, '../lib/wordbank.js');
|
|
10
10
|
|
|
11
11
|
const words = yaml.load(readFileSync(WORDS_YAML, 'utf8'));
|
|
12
12
|
writeFileSync(WORDS_JS, `
|
package/lib/fields.js
CHANGED
|
@@ -1,114 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const DAY = 1000 * 60 * 60 * 24;
|
|
6
|
-
const WEEK = DAY * 7;
|
|
7
|
-
|
|
8
|
-
export function date({} = {}) {
|
|
9
|
-
const now = Date.now();
|
|
10
|
-
const max = now - DAY;
|
|
11
|
-
const min = max - WEEK * 8;
|
|
12
|
-
return new Date(min + Math.random() * (max - min)).toISOString();
|
|
13
|
-
}
|
|
1
|
+
// 2025 date range for random date generation
|
|
2
|
+
const DATE_MIN = Date.UTC(2025, 0, 1); // 2025-01-01
|
|
3
|
+
const DATE_MAX = Date.UTC(2025, 11, 31, 23, 59, 59, 999); // 2025-12-31
|
|
14
4
|
|
|
15
|
-
export
|
|
16
|
-
return imageUrl(size);
|
|
17
|
-
}
|
|
5
|
+
export class Fields {
|
|
18
6
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
});
|
|
25
|
-
}
|
|
7
|
+
constructor(lorem) {
|
|
8
|
+
this._prng = lorem._prng;
|
|
9
|
+
this._words = lorem.words;
|
|
10
|
+
this._markdown = lorem.markdown;
|
|
11
|
+
}
|
|
26
12
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
output: 'array',
|
|
31
|
-
});
|
|
32
|
-
}
|
|
13
|
+
date({} = {}) {
|
|
14
|
+
return new Date(DATE_MIN + this._prng.random() * (DATE_MAX - DATE_MIN)).toISOString();
|
|
15
|
+
}
|
|
33
16
|
|
|
34
|
-
|
|
17
|
+
image({ size = 300 } = {}) {
|
|
18
|
+
return this._imageUrl(size);
|
|
19
|
+
}
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
21
|
+
authors({ size = [1, 3] } = {}) {
|
|
22
|
+
return this._words.words({
|
|
23
|
+
size,
|
|
24
|
+
decorates: ['title'],
|
|
25
|
+
output: 'array',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
42
28
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
}
|
|
29
|
+
tags({ size = [1, 4] } = {}) {
|
|
30
|
+
return this._words.words({
|
|
31
|
+
size,
|
|
32
|
+
output: 'array',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
51
35
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
36
|
+
// TODO: categories
|
|
37
|
+
|
|
38
|
+
title({ size = [2, 6] } = {}) {
|
|
39
|
+
return this._words.words({
|
|
40
|
+
size,
|
|
41
|
+
decorates: ['title'],
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
term({ field } = {}) {
|
|
46
|
+
const random = this._prng.random();
|
|
47
|
+
const size = random < 0.7 ? 1 : random < 0.9 ? 2 : 3;
|
|
48
|
+
return this._words.words({
|
|
49
|
+
size,
|
|
50
|
+
decorates: ['title'],
|
|
51
|
+
});
|
|
52
|
+
}
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
size: [480, 270],
|
|
67
|
-
...imageOptions,
|
|
68
|
-
};
|
|
69
|
-
if (sections === undefined) {
|
|
70
|
-
sections = Math.floor(paragraphs * (1 + Math.random()) / 4);
|
|
54
|
+
description({ size = [10, 20], ...options } = {}) {
|
|
55
|
+
const decorator = Object.keys(options).length ? ['description', options] : 'description';
|
|
56
|
+
return this._words.words({
|
|
57
|
+
size,
|
|
58
|
+
decorates: [decorator],
|
|
59
|
+
});
|
|
71
60
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
61
|
+
|
|
62
|
+
html({ paragraphs = 8, sections, paragraph, image: imageOptions } = {}) {
|
|
63
|
+
paragraph = {
|
|
64
|
+
size: [30, 60],
|
|
65
|
+
...paragraph,
|
|
66
|
+
};
|
|
67
|
+
imageOptions = {
|
|
68
|
+
size: [480, 270],
|
|
69
|
+
...imageOptions,
|
|
70
|
+
};
|
|
71
|
+
if (sections === undefined) {
|
|
72
|
+
sections = Math.floor(paragraphs * (1 + this._prng.random()) / 4);
|
|
79
73
|
}
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
sections = Math.max(1, Math.min(sections, paragraphs));
|
|
75
|
+
const content = [];
|
|
76
|
+
const pps = paragraphs / sections;
|
|
77
|
+
let j = 0;
|
|
78
|
+
for (let i = 0; i < sections; i++) {
|
|
79
|
+
if (i > 0) {
|
|
80
|
+
content.push(`<h4>${this.title()}</h4>`);
|
|
81
|
+
}
|
|
82
|
+
while (j++ < (i + 1) * pps) {
|
|
83
|
+
content.push(`<p>${this.description(paragraph)}</p>`);
|
|
84
|
+
}
|
|
85
|
+
content.push(`<div class="image-container"><img src="${this.image(imageOptions)}"></div>`);
|
|
82
86
|
}
|
|
83
|
-
content.
|
|
87
|
+
return content.join('');
|
|
84
88
|
}
|
|
85
|
-
return content.join('');
|
|
86
|
-
}
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
90
|
+
availability() {
|
|
91
|
+
return this._prng.random() > 0.3 ? 'IN_STOCK' : 'OUT_OF_STOCK';
|
|
92
|
+
}
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
94
|
+
price() {
|
|
95
|
+
return Math.floor(this._prng.random() * 10000) / 100;
|
|
96
|
+
}
|
|
95
97
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
98
|
+
rating() {
|
|
99
|
+
return Math.floor(this._prng.random() * 500) / 100 + 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
answer({ sources, format, citation, sampling, features }) {
|
|
103
|
+
switch (format) {
|
|
104
|
+
case 'markdown':
|
|
105
|
+
let index = 1;
|
|
106
|
+
sources = sources.map(({ url }) => ({ url, index: index++ }));
|
|
107
|
+
return this._markdown.markdown({ sources, citation, sampling, features });
|
|
108
|
+
case 'plaintext':
|
|
109
|
+
default:
|
|
110
|
+
return this._words.words({
|
|
111
|
+
min: this._sample(50, sampling),
|
|
112
|
+
max: this._sample(50, sampling),
|
|
113
|
+
decorates: ['description'],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
99
117
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return md.markdown({ sources, citation, sampling, features });
|
|
106
|
-
case 'plaintext':
|
|
107
|
-
default:
|
|
108
|
-
return lorem.lorem({
|
|
109
|
-
min: sample(50, sampling),
|
|
110
|
-
max: sample(50, sampling),
|
|
111
|
-
decorates: ['description'],
|
|
112
|
-
});
|
|
118
|
+
// helpers //
|
|
119
|
+
_imageUrl(size) {
|
|
120
|
+
const seed = this._prng.randomInt(0, 999);
|
|
121
|
+
const sizePath = Array.isArray(size) ? size.length > 1 ? `${size[0]}/${size[1]}` : `${size[0]}` : `${size}`;
|
|
122
|
+
return `https://picsum.photos/seed/${seed}/${sizePath}`;
|
|
113
123
|
}
|
|
124
|
+
|
|
125
|
+
_sample(size, sampling) {
|
|
126
|
+
return sampling !== undefined ? Math.ceil(size * sampling) : size;
|
|
127
|
+
}
|
|
128
|
+
|
|
114
129
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import * as utils from './utils.js';
|
|
4
|
-
import * as fields from './fields.js';
|
|
1
|
+
// Main entry point - creates a seeded Lorem instance with all utilities attached
|
|
2
|
+
export * from './lorem.js';
|
|
5
3
|
|
|
6
|
-
|
|
4
|
+
// Export classes for direct use if needed
|
|
5
|
+
export { Words } from './words.js';
|
|
6
|
+
export { Markdown as Md } from './markdown.js';
|
|
7
|
+
export { Fields } from './fields.js';
|
|
8
|
+
export { Utils } from './utils.js';
|
|
9
|
+
export { randomSeed } from './prng.js';
|
package/lib/lorem.js
CHANGED
|
@@ -1,145 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { prng } from './prng.js';
|
|
2
|
+
import { Words } from './words.js';
|
|
3
|
+
import { Markdown } from './markdown.js';
|
|
4
|
+
import { Fields } from './fields.js';
|
|
5
|
+
import { Utils } from './utils.js';
|
|
6
|
+
import { randomSeed } from './prng.js';
|
|
3
7
|
|
|
4
|
-
export function lorem(
|
|
5
|
-
|
|
6
|
-
for (const decorate of decorates) {
|
|
7
|
-
iterator = lookup(decorate)(iterator);
|
|
8
|
-
}
|
|
9
|
-
return lookup(output)(iterator);
|
|
8
|
+
export function lorem(options) {
|
|
9
|
+
return new Lorem(options);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
string,
|
|
14
|
-
array,
|
|
15
|
-
title,
|
|
16
|
-
description,
|
|
17
|
-
multiline,
|
|
18
|
-
}
|
|
12
|
+
class Lorem {
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return FNS[fn]();
|
|
24
|
-
case 'function':
|
|
25
|
-
return fn;
|
|
26
|
-
case 'object':
|
|
27
|
-
if (Array.isArray(fn)) {
|
|
28
|
-
const [name, options = {}] = fn;
|
|
29
|
-
return FNS[name](options);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
throw new Error(`Unrecognized decorator/output form: ${fn}`);
|
|
33
|
-
}
|
|
14
|
+
constructor({ seed = randomSeed() } = {}) {
|
|
15
|
+
this._seed = seed;
|
|
16
|
+
this._prng = prng({ seed });
|
|
34
17
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
18
|
+
// Initialize in dependency order:
|
|
19
|
+
// utils and words have no dependencies on other classes
|
|
20
|
+
// markdown depends on words
|
|
21
|
+
// fields depends on words and markdown
|
|
22
|
+
this.utils = new Utils(this);
|
|
23
|
+
this.words = new Words(this);
|
|
24
|
+
this.markdown = new Markdown(this);
|
|
25
|
+
this.fields = new Fields(this);
|
|
40
26
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// output //
|
|
44
|
-
export function string({ separator = ' ' } = {}) {
|
|
45
|
-
return iterator => [...iterator].join(separator);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function array() {
|
|
49
|
-
return iterator => [...iterator];
|
|
50
|
-
}
|
|
51
27
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
avg: 10,
|
|
55
|
-
std: 3,
|
|
56
|
-
min: 1,
|
|
57
|
-
},
|
|
58
|
-
} = {}) {
|
|
59
|
-
return iterator => {
|
|
60
|
-
let slen = gaussMS(wordsPerLine);
|
|
61
|
-
let result = '';
|
|
62
|
-
for (let word of iterator) {
|
|
63
|
-
if (result) {
|
|
64
|
-
if (slen-- === 0) {
|
|
65
|
-
result += '\n';
|
|
66
|
-
slen = gaussMS(wordsPerLine);
|
|
67
|
-
} else {
|
|
68
|
-
result += ' ';
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
result += word;
|
|
72
|
-
}
|
|
73
|
-
return result;
|
|
28
|
+
get prng() {
|
|
29
|
+
return this._prng;
|
|
74
30
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// decorators //
|
|
78
|
-
export function limit(size = [5, 10]) {
|
|
79
|
-
const n = typeof size === 'number' ? size : randomInt(...size);
|
|
80
|
-
return function *(iterator) {
|
|
81
|
-
let i = 0;
|
|
82
|
-
for (let word of iterator) {
|
|
83
|
-
if (i++ >= n) {
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
yield word;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
31
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
for (let word of iterator) {
|
|
94
|
-
yield capitalize(word);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function description({
|
|
100
|
-
wordsPerSentence = {
|
|
101
|
-
avg: 24,
|
|
102
|
-
std: 5,
|
|
103
|
-
min: 1,
|
|
104
|
-
},
|
|
105
|
-
punctuation = '.',
|
|
106
|
-
} = {}) {
|
|
107
|
-
return function *(iterator) {
|
|
108
|
-
let slen = 0;
|
|
109
|
-
|
|
110
|
-
yield* iterateWithLastItemSignal(iterator, function *(word, last) {
|
|
111
|
-
if (slen === 0) {
|
|
112
|
-
word = capitalize(word);
|
|
113
|
-
slen = gaussMS(wordsPerSentence);
|
|
114
|
-
}
|
|
115
|
-
if (--slen === 0 || last) {
|
|
116
|
-
word += punctuation;
|
|
117
|
-
}
|
|
118
|
-
yield word;
|
|
119
|
-
});
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// helpers //
|
|
124
|
-
function capitalize(word) {
|
|
125
|
-
return word[0].toUpperCase() + word.substring(1);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// TODO: have a random variable expression
|
|
129
|
-
function gaussMS(args) {
|
|
130
|
-
if (typeof args === 'number') {
|
|
131
|
-
return Math.round(avg);
|
|
132
|
-
}
|
|
133
|
-
let { avg, std, min, max } = args;
|
|
134
|
-
if (std === undefined) {
|
|
135
|
-
std = avg / 4;
|
|
136
|
-
}
|
|
137
|
-
let n = gaussRandom() * std + avg;
|
|
138
|
-
if (min !== undefined) {
|
|
139
|
-
n = Math.max(min, n);
|
|
32
|
+
get seed() {
|
|
33
|
+
return this._seed;
|
|
140
34
|
}
|
|
141
|
-
|
|
142
|
-
n = Math.min(max, n);
|
|
143
|
-
}
|
|
144
|
-
return Math.round(n);
|
|
35
|
+
|
|
145
36
|
}
|