@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 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/words.js');
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
- import * as lorem from './lorem.js';
2
- import { imageUrl, sample } from './utils.js';
3
- import * as md from './markdown.js';
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 function image({ size = 300 } = {}) {
16
- return imageUrl(size);
17
- }
5
+ export class Fields {
18
6
 
19
- export function authors({ size = [1, 3] } = {}) {
20
- return lorem.lorem({
21
- size,
22
- decorates: ['title'],
23
- output: 'array',
24
- });
25
- }
7
+ constructor(lorem) {
8
+ this._prng = lorem._prng;
9
+ this._words = lorem.words;
10
+ this._markdown = lorem.markdown;
11
+ }
26
12
 
27
- export function tags({ size = [1, 4] } = {}) {
28
- return lorem.lorem({
29
- size,
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
- // TODO: categories
17
+ image({ size = 300 } = {}) {
18
+ return this._imageUrl(size);
19
+ }
35
20
 
36
- export function title({ size = [2, 6] } = {}) {
37
- return lorem.lorem({
38
- size,
39
- decorates: ['title'],
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
- export function term({ field }) {
44
- const random = Math.random();
45
- const size = random < 0.7 ? 1 : random < 0.9 ? 2 : 3;
46
- return lorem.lorem({
47
- size,
48
- decorates: ['title'],
49
- });
50
- }
29
+ tags({ size = [1, 4] } = {}) {
30
+ return this._words.words({
31
+ size,
32
+ output: 'array',
33
+ });
34
+ }
51
35
 
52
- export function description({ size = [10, 20], ...options } = {}) {
53
- const decorator = Object.keys(options).length ? ['description', options] : 'description';
54
- return lorem.lorem({
55
- size,
56
- decorates: [decorator],
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
- export function html({ paragraphs = 8, sections, paragraph, image: imageOptions } = {}) {
61
- paragraph = {
62
- size: [30, 60],
63
- ...paragraph,
64
- };
65
- imageOptions = {
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
- sections = Math.max(1, Math.min(sections, paragraphs));
73
- const content = [];
74
- const pps = paragraphs / sections;
75
- let j = 0;
76
- for (let i = 0; i < sections; i++) {
77
- if (i > 0) {
78
- content.push(`<h4>${title()}</h4>`);
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
- while (j++ < (i + 1) * pps) {
81
- content.push(`<p>${description(paragraph)}</p>`);
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.push(`<div class="image-container"><img src="${image(imageOptions)}"></div>`);
87
+ return content.join('');
84
88
  }
85
- return content.join('');
86
- }
87
89
 
88
- export function availability() {
89
- return Math.random() > 0.3 ? 'IN_STOCK' : 'OUT_OF_STOCK';
90
- }
90
+ availability() {
91
+ return this._prng.random() > 0.3 ? 'IN_STOCK' : 'OUT_OF_STOCK';
92
+ }
91
93
 
92
- export function price() {
93
- return Math.floor(Math.random() * 10000) / 100;
94
- }
94
+ price() {
95
+ return Math.floor(this._prng.random() * 10000) / 100;
96
+ }
95
97
 
96
- export function rating() {
97
- return Math.floor(Math.random() * 500) / 100 + 1;
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
- export function answer({ sources, format, citation, sampling, features }) {
101
- switch (format) {
102
- case 'markdown':
103
- let index = 1;
104
- sources = sources.map(({ url }) => ({ url, index: index++ }));
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
- import * as md from './markdown.js';
2
- import * as lorem from './lorem.js';
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
- export { md, lorem, utils, fields };
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 { randomInt, gaussRandom, iterateWithLastItemSignal as iterateWithLastItemSignal } from './utils.js';
2
- import DEFAULT_WORDS from './words.js';
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({ decorates = [], output = 'string', size, min, max, ...options } = {}) {
5
- let iterator = limit(size || [min, max])(base(options));
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
- const FNS = {
13
- string,
14
- array,
15
- title,
16
- description,
17
- multiline,
18
- }
12
+ class Lorem {
19
13
 
20
- function lookup(fn) {
21
- switch (typeof fn) {
22
- case 'string':
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
- // base //
36
- export function *base({ words = DEFAULT_WORDS, fixedStarts = 0 } = {}) {
37
- const wordsLength = words.length;
38
- for (let i = 0; ; i++) {
39
- yield words[i < fixedStarts ? i : Math.floor(Math.random() * wordsLength)];
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
- export function multiline({
53
- wordsPerLine = {
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
- export function title({} = {}) {
92
- return function *(iterator) {
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
- if (max !== undefined) {
142
- n = Math.min(max, n);
143
- }
144
- return Math.round(n);
35
+
145
36
  }