Skip to content

Commit c7d8d29

Browse files
authored
Merge branch 'main' into chore/set-seed-directly
2 parents 6db0399 + 1b08de8 commit c7d8d29

File tree

7 files changed

+247
-15
lines changed

7 files changed

+247
-15
lines changed

.github/.codecov.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ coverage:
1111
default:
1212
target: 95%
1313
threshold: 2%
14+
patch:
15+
default:
16+
target: 95%
17+
threshold: 1%

docs/.vitepress/config.mjs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,10 @@ const sidebar = {
4040
],
4141
};
4242

43-
// grab from process.env once this is building on netlify
4443
const algolia = {
45-
apiKey: '',
46-
indexName: '',
47-
searchParameters: {
48-
facetFilters: [''],
49-
},
44+
apiKey: process.env.API_KEY,
45+
appId: process.env.APP_ID,
46+
indexName: 'fakerjs',
5047
};
5148

5249
const description =
@@ -62,27 +59,42 @@ export default defineConfig({
6259
[
6360
'meta',
6461
{
65-
property: 'og:description',
62+
name: 'og:description',
6663
content: description,
6764
},
65+
],
66+
[
67+
'meta',
6868
{
6969
name: 'twitter:description',
7070
content: description,
7171
},
72+
],
73+
[
74+
'meta',
7275
{
7376
name: 'description',
7477
content: description,
7578
},
79+
],
80+
[
81+
'meta',
7682
{
77-
property: 'og:image',
83+
name: 'og:image',
7884
content: image,
7985
},
86+
],
87+
[
88+
'meta',
8089
{
81-
property: 'twitter:image',
90+
name: 'twitter:image',
8291
content: image,
8392
},
93+
],
94+
[
95+
'meta',
8496
{
85-
property: 'twitter:card',
97+
name: 'twitter:card',
8698
content: 'summary_large_image',
8799
},
88100
],
@@ -96,7 +108,6 @@ export default defineConfig({
96108
editLinkText: 'Suggest changes to this page',
97109
nav,
98110
sidebar,
99-
// TODO 2022-03-06: https://github.com/faker-js/faker/issues/222
100-
// algolia,
111+
algolia,
101112
},
102113
});

scripts/apidoc.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import * as TypeDoc from 'typedoc';
33
import { writeApiPagesIndex } from './apidoc/apiDocsWriter';
44
import { processDirectMethods } from './apidoc/directMethods';
55
import { processModuleMethods } from './apidoc/moduleMethods';
6+
import {
7+
DefaultParameterAwareSerializer,
8+
parameterDefaultReader,
9+
patchProjectParameterDefaults,
10+
} from './apidoc/parameterDefaults';
611
import type { PageIndex } from './apidoc/utils';
712
import { pathOutputDir } from './apidoc/utils';
813

@@ -15,6 +20,14 @@ async function build(): Promise<void> {
1520
// If you want TypeDoc to load typedoc.json files
1621
//app.options.addReader(new TypeDoc.TypeDocReader());
1722

23+
// Read parameter defaults
24+
app.converter.on(
25+
TypeDoc.Converter.EVENT_CREATE_DECLARATION,
26+
parameterDefaultReader
27+
);
28+
// Add to debug json output
29+
app.serializer.addSerializer(new DefaultParameterAwareSerializer(undefined));
30+
1831
app.bootstrap({
1932
entryPoints: ['src/index.ts'],
2033
pretty: true,
@@ -31,6 +44,8 @@ async function build(): Promise<void> {
3144
await app.generateJson(project, pathOutputJson);
3245
console.log(pathOutputDir);
3346

47+
patchProjectParameterDefaults(project);
48+
3449
const modulesPages: PageIndex = [];
3550
modulesPages.push({ text: 'Localization', link: '/api/localization.html' });
3651
modulesPages.push(...processModuleMethods(project));

scripts/apidoc/parameterDefaults.ts

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import type {
2+
Context,
3+
DeclarationReflection,
4+
EventCallback,
5+
JSONOutput,
6+
ProjectReflection,
7+
SignatureReflection,
8+
} from 'typedoc';
9+
import {
10+
Reflection,
11+
ReflectionKind,
12+
SerializerComponent,
13+
TypeScript,
14+
} from 'typedoc';
15+
16+
const reflectionKindFunctionOrMethod =
17+
ReflectionKind.Function | ReflectionKind.Method;
18+
19+
interface ParameterDefaultsAware extends Reflection {
20+
implementationDefaultParameters: string[];
21+
}
22+
23+
/**
24+
* TypeDoc EventCallback for EVENT_CREATE_DECLARATION events that reads the default parameters from the implementation.
25+
*/
26+
export const parameterDefaultReader: EventCallback = (
27+
context: Context,
28+
reflection: Reflection
29+
): void => {
30+
const symbol = context.project.getSymbolFromReflection(reflection);
31+
if (!symbol) return;
32+
33+
if (
34+
reflection.kindOf(reflectionKindFunctionOrMethod) &&
35+
symbol.declarations?.length
36+
) {
37+
const lastDeclaration = symbol.declarations[symbol.declarations.length - 1];
38+
if (TypeScript.isFunctionLike(lastDeclaration)) {
39+
(reflection as ParameterDefaultsAware).implementationDefaultParameters =
40+
lastDeclaration.parameters.map((param) =>
41+
cleanParameterDefault(param.initializer?.getText())
42+
);
43+
}
44+
}
45+
};
46+
47+
/**
48+
* Removes compile expressions that don't add any value for readers.
49+
*
50+
* @param value The default value to clean.
51+
* @returns The cleaned default value.
52+
*/
53+
function cleanParameterDefault(value?: string): string {
54+
if (value == null) {
55+
return undefined;
56+
}
57+
// Strip type casts: "'foobar' as unknown as T" => "'foobar'"
58+
return value.replace(/ as unknown as [A-Za-z<>]+/, '');
59+
}
60+
61+
/**
62+
* Serializer that adds the `implementationDefaultParameters` to the JSON output.
63+
*/
64+
export class DefaultParameterAwareSerializer extends SerializerComponent<Reflection> {
65+
serializeGroup(instance: unknown): boolean {
66+
return instance instanceof Reflection;
67+
}
68+
69+
supports(item: unknown): boolean {
70+
return true;
71+
}
72+
73+
toObject(item: Reflection, obj?: object): Partial<JSONOutput.Reflection> {
74+
(obj as ParameterDefaultsAware).implementationDefaultParameters = (
75+
item as ParameterDefaultsAware
76+
).implementationDefaultParameters;
77+
return obj;
78+
}
79+
}
80+
81+
/**
82+
* Replaces all methods' last signature's parameter's default value with the default value read from the implementation.
83+
*
84+
* @param project The project to patch.
85+
*/
86+
export function patchProjectParameterDefaults(
87+
project: ProjectReflection
88+
): void {
89+
const functionOrMethods = project.getReflectionsByKind(
90+
reflectionKindFunctionOrMethod
91+
) as DeclarationReflection[];
92+
for (const functionOrMethod of functionOrMethods) {
93+
patchMethodParameterDefaults(functionOrMethod);
94+
}
95+
}
96+
97+
/**
98+
* Replaces the last signature's parameter's default value with the default value read from the implementation.
99+
*
100+
* @param method The method to patch.
101+
*/
102+
function patchMethodParameterDefaults(method: DeclarationReflection): void {
103+
const signatures = method.signatures;
104+
const signature = signatures[signatures.length - 1];
105+
const parameterDefaults = (method as unknown as ParameterDefaultsAware)
106+
.implementationDefaultParameters;
107+
if (parameterDefaults) {
108+
patchSignatureParameterDefaults(signature, parameterDefaults);
109+
}
110+
}
111+
112+
/**
113+
* Replaces the given signature's parameter's default value with the given default values.
114+
*
115+
* @param signature The signature to patch.
116+
* @param parameterDefaults The defaults to add.
117+
*/
118+
function patchSignatureParameterDefaults(
119+
signature: SignatureReflection,
120+
parameterDefaults: string[]
121+
): void {
122+
const signatureParameters = signature.parameters;
123+
if (signatureParameters.length !== parameterDefaults.length) {
124+
throw new Error('Unexpected parameter length mismatch');
125+
}
126+
signatureParameters.forEach(
127+
(param, index) =>
128+
(param.defaultValue = parameterDefaults[index] || param.defaultValue)
129+
);
130+
}

scripts/apidoc/signature.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ function analyzeParameter(parameter: ParameterReflection): {
162162
const name = parameter.name;
163163
const declarationName = name + (isOptional(parameter) ? '?' : '');
164164
const type = parameter.type;
165-
const defaultValue = parameter.defaultValue;
165+
const commentDefault = extractDefaultFromComment(parameter.comment);
166+
const defaultValue = parameter.defaultValue ?? commentDefault;
166167

167168
let signatureText = '';
168169
if (defaultValue) {
@@ -200,6 +201,7 @@ function analyzeParameterOptions(
200201
return properties.map((property) => ({
201202
name: `${name}.${property.name}${isOptional(property) ? '?' : ''}`,
202203
type: declarationTypeToText(property),
204+
default: extractDefaultFromComment(property.comment),
203205
description: mdToHtml(
204206
toBlock(property.comment ?? property.signatures?.[0].comment)
205207
),
@@ -284,3 +286,25 @@ function signatureTypeToText(signature: SignatureReflection): string {
284286
.map((p) => `${p.name}: ${typeToText(p.type)}`)
285287
.join(', ')}) => ${typeToText(signature.type)}`;
286288
}
289+
290+
/**
291+
* Extracts and removed the parameter default from the comments.
292+
*
293+
* @param comment The comment to extract the default from.
294+
* @returns The extracted default value.
295+
*/
296+
function extractDefaultFromComment(comment?: Comment): string {
297+
if (!comment) {
298+
return;
299+
}
300+
const text = comment.shortText;
301+
if (!text || text.trim() === '') {
302+
return;
303+
}
304+
const result = /(.*)[ \n]Defaults to `([^`]+)`./.exec(text);
305+
if (!result) {
306+
return;
307+
}
308+
comment.shortText = result[1];
309+
return result[2];
310+
}

src/iban.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,12 @@ export = {
206206
},
207207
{
208208
country: 'CR',
209-
total: 21,
209+
total: 22,
210210
bban: [
211+
{
212+
type: 'n',
213+
count: 1,
214+
},
211215
{
212216
type: 'n',
213217
count: 3,
@@ -217,7 +221,7 @@ export = {
217221
count: 14,
218222
},
219223
],
220-
format: 'CRkk bbbc cccc cccc cccc c',
224+
format: 'CRkk xbbb cccc cccc cccc cc',
221225
},
222226
{
223227
country: 'HR',

test/finance_iban.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,50 @@ describe('finance_iban', () => {
255255
'the result should be equal to 1'
256256
).toBe(1);
257257
});
258+
259+
it('IBAN for Costa Rica is correct', () => {
260+
// Costa Rica
261+
// https://wise.com/us/iban/costa-rica
262+
// Length 22
263+
// BBAN 1n,3n,14n
264+
// CRkk xbbb cccc cccc cccc cccc cccc
265+
// x = reserve digit
266+
// b = National bank code (digits)
267+
// c = Account number (digits)
268+
269+
// example IBAN CR05 0152 0200 1026 2840 66
270+
271+
const iban = faker.finance.iban(false, 'CR');
272+
273+
expect(iban).satisfy(validator.isIBAN);
274+
275+
const ibanFormated = iban.match(/.{1,4}/g).join(' ');
276+
const bban = iban.substring(4) + iban.substring(0, 4);
277+
278+
expect(
279+
22,
280+
`CR IBAN would be 22 chars length, given is ${iban.length}`
281+
).toBe(iban.length);
282+
283+
expect(
284+
iban.substring(0, 2),
285+
iban.substring(0, 2) +
286+
"must start with 'CR' in CR IBAN " +
287+
ibanFormated
288+
).to.eq('CR');
289+
290+
expect(
291+
iban.substring(2, 22),
292+
iban.substring(2, 22) +
293+
' must contains only digit in AZ IBAN ' +
294+
ibanFormated
295+
).match(/^\d{20}$/);
296+
297+
expect(
298+
ibanLib.mod97(ibanLib.toDigitString(bban)),
299+
'the result should be equal to 1'
300+
).toBe(1);
301+
});
258302
});
259303
}
260304
});

0 commit comments

Comments
 (0)