Skip to content

Commit 5e4aa59

Browse files
authored
Merge branch 'next' into fix/bigint
2 parents 66b002b + ece4f16 commit 5e4aa59

File tree

85 files changed

+2475
-1973
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2475
-1973
lines changed

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
33
{
44
"name": "FakerJs",
5-
"image": "mcr.microsoft.com/devcontainers/typescript-node:22@sha256:dc2c3654370fe92a55daeefe9d2d95839d85bdc1f68f7fd4ab86621f49e5818a",
5+
"image": "mcr.microsoft.com/devcontainers/typescript-node:22@sha256:9791f4aa527774bc370c6bd2f6705ce5a686f1e6f204badd8dfaacce28c631ae",
66

77
// Features to add to the dev container. More info: https://containers.dev/features.
88
// "features": {},

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ jobs:
211211
run: pnpm vitest run --coverage
212212

213213
- name: Upload coverage to Codecov
214-
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7
214+
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303 # v5.1.2
215215
with:
216216
token: ${{ secrets.CODECOV_TOKEN }}
217217
fail_ci_if_error: true

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ versions.json
8080
/dist
8181
/docs/.vitepress/cache
8282
/docs/.vitepress/dist
83+
/docs/api/*.ts
84+
!/docs/api/api-types.ts
85+
/docs/api/*.md
86+
!/docs/api/index.md
87+
/docs/api/api-search-index.json
8388
/docs/public/api-diff-index.json
8489

8590
# Faker

LICENSE

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,6 @@
1-
Faker - Copyright (c) 2022-2024
1+
MIT License
22

3-
This software consists of voluntary contributions made by many individuals.
4-
For exact contribution history, see the revision history
5-
available at https://github.com/faker-js/faker
6-
7-
Permission is hereby granted, free of charge, to any person obtaining
8-
a copy of this software and associated documentation files (the
9-
"Software"), to deal in the Software without restriction, including
10-
without limitation the rights to use, copy, modify, merge, publish,
11-
distribute, sublicense, and/or sell copies of the Software, and to
12-
permit persons to whom the Software is furnished to do so, subject to
13-
the following conditions:
14-
15-
The above copyright notice and this permission notice shall be
16-
included in all copies or substantial portions of the Software.
17-
18-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25-
26-
===
27-
28-
From: https://github.com/faker-js/faker/commit/a9f98046c7d5eeaabe12fc587024c06d683800b8
29-
To: https://github.com/faker-js/faker/commit/29234378807c4141588861f69421bf20b5ac635e
30-
31-
Based on faker.js, copyright Marak Squires and contributor, what follows below is the original license.
32-
33-
===
34-
35-
faker.js - Copyright (c) 2020
36-
Marak Squires
37-
http://github.com/marak/faker.js/
38-
39-
faker.js was inspired by and has used data definitions from:
40-
41-
* https://github.com/stympy/faker/ - Copyright (c) 2007-2010 Benjamin Curtis
42-
* http://search.cpan.org/~jasonk/Data-Faker-0.07/ - Copyright 2004-2005 by Jason Kohles
3+
Copyright 2022-2025 FakerJS Contributors
434

445
Permission is hereby granted, free of charge, to any person obtaining
456
a copy of this software and associated documentation files (the

cypress/e2e/example-refresh.cy.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
describe('example-refresh', () => {
2+
it('should refresh the example', () => {
3+
// given
4+
cy.visit('/api/faker.html#constructor');
5+
cy.get('.refresh').first().as('refresh');
6+
cy.get('@refresh').next().find('code').as('codeBlock');
7+
cy.get('@codeBlock').then(($el) => {
8+
const originalCodeText = $el.text();
9+
10+
cy.get('@refresh')
11+
.click()
12+
.should('not.be.disabled') // stays disabled on error
13+
.then(() => {
14+
cy.get('@codeBlock').then(($el) => {
15+
const newCodeText = $el.text();
16+
expect(newCodeText).not.to.equal(originalCodeText);
17+
18+
cy.get('@refresh')
19+
.click()
20+
.should('not.be.disabled') // stays disabled on error
21+
.then(() => {
22+
cy.get('@codeBlock').then(($el) => {
23+
const newCodeText2 = $el.text();
24+
expect(newCodeText2).not.to.equal(originalCodeText);
25+
expect(newCodeText2).not.to.equal(newCodeText);
26+
});
27+
});
28+
});
29+
});
30+
});
31+
});
32+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export function formatResult(result: unknown): string {
2+
return result === undefined
3+
? 'undefined'
4+
: typeof result === 'bigint'
5+
? `${result}n`
6+
: JSON.stringify(result, undefined, 2)
7+
.replaceAll('\\r', '')
8+
.replaceAll('<', '&lt;')
9+
.replaceAll(
10+
/(^ *|: )"([^'\n]*?)"(?=,?$|: )/gm,
11+
(_, p1, p2) => `${p1}'${p2.replace(/\\"/g, '"')}'`
12+
)
13+
.replaceAll(/\n */g, ' ');
14+
}

docs/.vitepress/components/api-docs/method.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface ApiDocsMethod {
88
readonly throws: string | undefined; // HTML
99
readonly signature: string; // HTML
1010
readonly examples: string; // HTML
11+
readonly refresh: (() => Promise<unknown[]>) | undefined;
1112
readonly seeAlsos: string[];
1213
readonly sourcePath: string; // URL-Suffix
1314
}

docs/.vitepress/components/api-docs/method.vue

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
<script setup lang="ts">
2+
import { computed, ref, useTemplateRef } from 'vue';
23
import { sourceBaseUrl } from '../../../api/source-base-url';
34
import { slugify } from '../../shared/utils/slugify';
5+
import { formatResult } from './format';
46
import type { ApiDocsMethod } from './method';
57
import MethodParameters from './method-parameters.vue';
8+
import RefreshButton from './refresh-button.vue';
69
710
const { method } = defineProps<{ method: ApiDocsMethod }>();
811
const {
@@ -14,10 +17,113 @@ const {
1417
throws,
1518
signature,
1619
examples,
20+
refresh,
1721
seeAlsos,
1822
sourcePath,
1923
} = method;
2024
25+
const code = useTemplateRef('code');
26+
const codeBlock = computed(() => code.value?.querySelector('div pre code'));
27+
const codeLines = ref<Element[]>();
28+
29+
function initRefresh(): Element[] {
30+
if (codeBlock.value == null) {
31+
return [];
32+
}
33+
const domLines = codeBlock.value.querySelectorAll('.line');
34+
let lineIndex = 0;
35+
const result: Element[] = [];
36+
while (lineIndex < domLines.length) {
37+
// Skip empty and preparatory lines (no '^faker.' invocation)
38+
if (
39+
domLines[lineIndex]?.children.length === 0 ||
40+
!/^\w*faker\w*\./i.test(domLines[lineIndex]?.textContent ?? '')
41+
) {
42+
lineIndex++;
43+
continue;
44+
}
45+
46+
// Skip to end of the invocation (if multiline)
47+
while (
48+
domLines[lineIndex] != null &&
49+
!/^([^ ].*)?\)(\.\w+)?;? ?(\/\/|$)/.test(
50+
domLines[lineIndex]?.textContent ?? ''
51+
)
52+
) {
53+
lineIndex++;
54+
}
55+
56+
if (lineIndex >= domLines.length) {
57+
break;
58+
}
59+
60+
const domLine = domLines[lineIndex];
61+
result.push(domLine);
62+
lineIndex++;
63+
64+
// Purge old results
65+
if (domLine.lastElementChild?.textContent?.startsWith('//')) {
66+
// Inline comments
67+
domLine.lastElementChild.remove();
68+
} else {
69+
// Multiline comments
70+
while (domLines[lineIndex]?.children[0]?.textContent?.startsWith('//')) {
71+
domLines[lineIndex].previousSibling?.remove(); // newline
72+
domLines[lineIndex].remove(); // comment
73+
lineIndex++;
74+
}
75+
}
76+
77+
// Add space between invocation and comment (if missing)
78+
const lastElementChild = domLine.lastElementChild;
79+
if (
80+
lastElementChild != null &&
81+
!lastElementChild.textContent?.endsWith(' ')
82+
) {
83+
lastElementChild.textContent += ' ';
84+
}
85+
}
86+
87+
return result;
88+
}
89+
90+
async function onRefresh(): Promise<void> {
91+
if (refresh != null && codeBlock.value != null) {
92+
codeLines.value ??= initRefresh();
93+
94+
const results = await refresh();
95+
96+
// Remove old comments
97+
codeBlock.value
98+
.querySelectorAll('.comment-delete-marker')
99+
.forEach((el) => el.remove());
100+
101+
// Insert new comments
102+
for (let i = 0; i < results.length; i++) {
103+
const result = results[i];
104+
const domLine = codeLines.value[i];
105+
const prettyResult = formatResult(result);
106+
const resultLines = prettyResult.split('\\n');
107+
108+
if (resultLines.length === 1) {
109+
domLine.insertAdjacentHTML('beforeend', newCommentSpan(resultLines[0]));
110+
} else {
111+
for (const line of resultLines.reverse()) {
112+
domLine.insertAdjacentHTML('afterend', newCommentLine(line));
113+
}
114+
}
115+
}
116+
}
117+
}
118+
119+
function newCommentLine(content: string): string {
120+
return `<span class="line comment-delete-marker">\n${newCommentSpan(content)}</span>`;
121+
}
122+
123+
function newCommentSpan(content: string): string {
124+
return `<span class="comment-delete-marker" style="--shiki-light:#6A737D;--shiki-dark:#6A737D">// ${content}</span>`;
125+
}
126+
21127
function seeAlsoToUrl(see: string): string {
22128
const [, module, methodName] = see.replace(/\(.*/, '').split('\.');
23129
@@ -51,8 +157,14 @@ function seeAlsoToUrl(see: string): string {
51157

52158
<div v-html="signature" />
53159

54-
<h3>Examples</h3>
55-
<div v-html="examples" />
160+
<h3 class="inline">Examples</h3>
161+
<RefreshButton
162+
class="refresh"
163+
v-if="refresh != null"
164+
style="margin-left: 0.5em"
165+
:refresh="onRefresh"
166+
/>
167+
<div ref="code" v-html="examples" />
56168

57169
<div v-if="seeAlsos.length > 0">
58170
<h3>See Also</h3>
@@ -107,4 +219,8 @@ svg.source-link-icon {
107219
display: inline;
108220
margin-left: 0.3em;
109221
}
222+
223+
h3.inline {
224+
display: inline-block;
225+
}
110226
</style>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue';
3+
4+
// This should probably use emit instead, but emit cannot be awaited
5+
const { refresh } = defineProps<{ refresh: () => Promise<void> }>();
6+
7+
const spinning = ref(false);
8+
9+
async function onRefresh() {
10+
spinning.value = true;
11+
await Promise.all([refresh(), delay(100)]);
12+
spinning.value = false;
13+
}
14+
15+
// Extra delay to make the spinning effect more visible
16+
// Some examples barely/don't change, so the spinning is the only visible effect
17+
function delay(ms: number) {
18+
return new Promise((resolve) => setTimeout(resolve, ms));
19+
}
20+
</script>
21+
22+
<template>
23+
<button
24+
class="refresh"
25+
title="Refresh Examples"
26+
:disabled="spinning"
27+
@click="onRefresh"
28+
>
29+
<div :class="{ spinning: spinning }" />
30+
</button>
31+
</template>
32+
33+
<style scoped>
34+
button.refresh {
35+
border: 1px solid var(--vp-code-copy-code-border-color);
36+
border-radius: 4px;
37+
width: 40px;
38+
height: 40px;
39+
font-size: 25px;
40+
vertical-align: middle;
41+
}
42+
43+
button.refresh div {
44+
background-image: url('refresh.svg');
45+
background-position: 50%;
46+
background-size: 20px;
47+
background-repeat: no-repeat;
48+
width: 100%;
49+
height: 100%;
50+
}
51+
52+
button.refresh:hover {
53+
background-color: var(--vp-code-copy-code-bg);
54+
opacity: 1;
55+
}
56+
57+
div.spinning {
58+
animation: spin 1s linear infinite;
59+
}
60+
61+
@keyframes spin {
62+
from {
63+
transform: rotate(0deg);
64+
}
65+
to {
66+
transform: rotate(360deg);
67+
}
68+
}
69+
</style>
Lines changed: 1 addition & 0 deletions
Loading

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ async function enableFaker() {
133133
e.g. 'faker.food.description()' or 'fakerZH_CN.person.firstName()'
134134
For other languages please refer to https://fakerjs.dev/guide/localization.html#available-locales
135135
For a full list of all methods please refer to https://fakerjs.dev/api/\`, logStyle);
136+
enableFaker = () => imported; // Init only once
136137
return imported;
137138
}
138139
`,

docs/api/.gitignore

Lines changed: 0 additions & 10 deletions
This file was deleted.

eslint.config.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const config: ReturnType<typeof tseslint.config> = tseslint.config(
2424
'.github/workflows/commentCodeGeneration.ts',
2525
'.prettierrc.js',
2626
'docs/.vitepress/components/shims.d.ts',
27+
'docs/.vitepress/components/api-docs/format.ts',
2728
'docs/.vitepress/shared/utils/slugify.ts',
2829
'docs/.vitepress/theme/index.ts',
2930
'eslint.config.js',
@@ -159,10 +160,7 @@ const config: ReturnType<typeof tseslint.config> = tseslint.config(
159160
'unicorn/prefer-string-raw': 'off', // The additional prefix doesn't help readability
160161
'unicorn/prefer-string-slice': 'off', // string.substring is sometimes easier to use
161162
'unicorn/prefer-ternary': 'off', // ternaries aren't always better
162-
163-
// TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code.
164-
// Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently.
165-
'unicorn/prevent-abbreviations': 'off',
163+
'unicorn/prevent-abbreviations': 'off', // if abbreviations don't reduce readability, they're fine
166164
},
167165
},
168166
//#endregion

0 commit comments

Comments
 (0)