From 3946df788fdf1e69848e9b6044fced29f52316f2 Mon Sep 17 00:00:00 2001 From: Shinigami Date: Tue, 22 Mar 2022 20:38:53 +0100 Subject: [PATCH 1/6] ci: configure codecov patch threshold (#647) --- .github/.codecov.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/.codecov.yml b/.github/.codecov.yml index d782656df33..21bd0ca39a9 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -11,3 +11,7 @@ coverage: default: target: 95% threshold: 2% + patch: + default: + target: 95% + threshold: 1% From 7f32614702f569d70a8a7744bd3aeb31279599fd Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Wed, 23 Mar 2022 08:11:00 +0100 Subject: [PATCH 2/6] docs: fix page meta (#659) --- docs/.vitepress/config.mjs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 60799a0eb4f..83f5b0fb700 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -62,27 +62,42 @@ export default defineConfig({ [ 'meta', { - property: 'og:description', + name: 'og:description', content: description, }, + ], + [ + 'meta', { name: 'twitter:description', content: description, }, + ], + [ + 'meta', { name: 'description', content: description, }, + ], + [ + 'meta', { - property: 'og:image', + name: 'og:image', content: image, }, + ], + [ + 'meta', { - property: 'twitter:image', + name: 'twitter:image', content: image, }, + ], + [ + 'meta', { - property: 'twitter:card', + name: 'twitter:card', content: 'summary_large_image', }, ], From a759c8707c2e3758e64e1c174c2de7aad51cd64b Mon Sep 17 00:00:00 2001 From: Daniel Bannert Date: Wed, 23 Mar 2022 09:06:00 +0100 Subject: [PATCH 3/6] fix: enable algolia search (#641) --- docs/.vitepress/config.mjs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 83f5b0fb700..8c15b49db9f 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -40,13 +40,10 @@ const sidebar = { ], }; -// grab from process.env once this is building on netlify const algolia = { - apiKey: '', - indexName: '', - searchParameters: { - facetFilters: [''], - }, + apiKey: process.env.API_KEY, + appId: process.env.APP_ID, + indexName: 'fakerjs', }; const description = @@ -111,7 +108,6 @@ export default defineConfig({ editLinkText: 'Suggest changes to this page', nav, sidebar, - // TODO 2022-03-06: https://github.com/faker-js/faker/issues/222 - // algolia, + algolia, }, }); From 3f3de78c83ae919fd44531ac7ae9caed885800d4 Mon Sep 17 00:00:00 2001 From: Jelle Hulter Date: Wed, 23 Mar 2022 09:29:48 +0100 Subject: [PATCH 4/6] fix: corrected the Costa Rican IBAN format (#646) --- src/iban.ts | 8 +++++-- test/finance_iban.spec.ts | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/iban.ts b/src/iban.ts index 3f10e91be2e..b608357ee93 100644 --- a/src/iban.ts +++ b/src/iban.ts @@ -206,8 +206,12 @@ export = { }, { country: 'CR', - total: 21, + total: 22, bban: [ + { + type: 'n', + count: 1, + }, { type: 'n', count: 3, @@ -217,7 +221,7 @@ export = { count: 14, }, ], - format: 'CRkk bbbc cccc cccc cccc c', + format: 'CRkk xbbb cccc cccc cccc cc', }, { country: 'HR', diff --git a/test/finance_iban.spec.ts b/test/finance_iban.spec.ts index 23768387d85..5c3fb9c9b6b 100644 --- a/test/finance_iban.spec.ts +++ b/test/finance_iban.spec.ts @@ -255,6 +255,50 @@ describe('finance_iban', () => { 'the result should be equal to 1' ).toBe(1); }); + + it('IBAN for Costa Rica is correct', () => { + // Costa Rica + // https://wise.com/us/iban/costa-rica + // Length 22 + // BBAN 1n,3n,14n + // CRkk xbbb cccc cccc cccc cccc cccc + // x = reserve digit + // b = National bank code (digits) + // c = Account number (digits) + + // example IBAN CR05 0152 0200 1026 2840 66 + + const iban = faker.finance.iban(false, 'CR'); + + expect(iban).satisfy(validator.isIBAN); + + const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const bban = iban.substring(4) + iban.substring(0, 4); + + expect( + 22, + `CR IBAN would be 22 chars length, given is ${iban.length}` + ).toBe(iban.length); + + expect( + iban.substring(0, 2), + iban.substring(0, 2) + + "must start with 'CR' in CR IBAN " + + ibanFormated + ).to.eq('CR'); + + expect( + iban.substring(2, 22), + iban.substring(2, 22) + + ' must contains only digit in AZ IBAN ' + + ibanFormated + ).match(/^\d{20}$/); + + expect( + ibanLib.mod97(ibanLib.toDigitString(bban)), + 'the result should be equal to 1' + ).toBe(1); + }); }); } }); From e6438353dbcb89055ef4ddb5c7cc8318d3f7a0f1 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Wed, 23 Mar 2022 12:54:47 +0100 Subject: [PATCH 5/6] docs: extract defaults from the comments if absent otherwise (#657) Co-authored-by: Daniel Bannert --- scripts/apidoc/signature.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/scripts/apidoc/signature.ts b/scripts/apidoc/signature.ts index bfeb01e6cb6..926b5a7c38d 100644 --- a/scripts/apidoc/signature.ts +++ b/scripts/apidoc/signature.ts @@ -162,7 +162,8 @@ function analyzeParameter(parameter: ParameterReflection): { const name = parameter.name; const declarationName = name + (isOptional(parameter) ? '?' : ''); const type = parameter.type; - const defaultValue = parameter.defaultValue; + const commentDefault = extractDefaultFromComment(parameter.comment); + const defaultValue = parameter.defaultValue ?? commentDefault; let signatureText = ''; if (defaultValue) { @@ -200,6 +201,7 @@ function analyzeParameterOptions( return properties.map((property) => ({ name: `${name}.${property.name}${isOptional(property) ? '?' : ''}`, type: declarationTypeToText(property), + default: extractDefaultFromComment(property.comment), description: mdToHtml( toBlock(property.comment ?? property.signatures?.[0].comment) ), @@ -284,3 +286,25 @@ function signatureTypeToText(signature: SignatureReflection): string { .map((p) => `${p.name}: ${typeToText(p.type)}`) .join(', ')}) => ${typeToText(signature.type)}`; } + +/** + * Extracts and removed the parameter default from the comments. + * + * @param comment The comment to extract the default from. + * @returns The extracted default value. + */ +function extractDefaultFromComment(comment?: Comment): string { + if (!comment) { + return; + } + const text = comment.shortText; + if (!text || text.trim() === '') { + return; + } + const result = /(.*)[ \n]Defaults to `([^`]+)`./.exec(text); + if (!result) { + return; + } + comment.shortText = result[1]; + return result[2]; +} From 1b08de821588a1d5a2436c177c20d60a66e8a977 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Wed, 23 Mar 2022 14:41:33 +0100 Subject: [PATCH 6/6] docs: read (complex) defaults from implementation signature (#656) Co-authored-by: Shinigami Co-authored-by: Daniel Bannert --- scripts/apidoc.ts | 15 ++++ scripts/apidoc/parameterDefaults.ts | 130 ++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 scripts/apidoc/parameterDefaults.ts diff --git a/scripts/apidoc.ts b/scripts/apidoc.ts index cb4ed2a4e12..4ac4fbf9776 100644 --- a/scripts/apidoc.ts +++ b/scripts/apidoc.ts @@ -3,6 +3,11 @@ import * as TypeDoc from 'typedoc'; import { writeApiPagesIndex } from './apidoc/apiDocsWriter'; import { processDirectMethods } from './apidoc/directMethods'; import { processModuleMethods } from './apidoc/moduleMethods'; +import { + DefaultParameterAwareSerializer, + parameterDefaultReader, + patchProjectParameterDefaults, +} from './apidoc/parameterDefaults'; import type { PageIndex } from './apidoc/utils'; import { pathOutputDir } from './apidoc/utils'; @@ -15,6 +20,14 @@ async function build(): Promise { // If you want TypeDoc to load typedoc.json files //app.options.addReader(new TypeDoc.TypeDocReader()); + // Read parameter defaults + app.converter.on( + TypeDoc.Converter.EVENT_CREATE_DECLARATION, + parameterDefaultReader + ); + // Add to debug json output + app.serializer.addSerializer(new DefaultParameterAwareSerializer(undefined)); + app.bootstrap({ entryPoints: ['src/index.ts'], pretty: true, @@ -31,6 +44,8 @@ async function build(): Promise { await app.generateJson(project, pathOutputJson); console.log(pathOutputDir); + patchProjectParameterDefaults(project); + const modulesPages: PageIndex = []; modulesPages.push({ text: 'Localization', link: '/api/localization.html' }); modulesPages.push(...processModuleMethods(project)); diff --git a/scripts/apidoc/parameterDefaults.ts b/scripts/apidoc/parameterDefaults.ts new file mode 100644 index 00000000000..9342d7b21cf --- /dev/null +++ b/scripts/apidoc/parameterDefaults.ts @@ -0,0 +1,130 @@ +import type { + Context, + DeclarationReflection, + EventCallback, + JSONOutput, + ProjectReflection, + SignatureReflection, +} from 'typedoc'; +import { + Reflection, + ReflectionKind, + SerializerComponent, + TypeScript, +} from 'typedoc'; + +const reflectionKindFunctionOrMethod = + ReflectionKind.Function | ReflectionKind.Method; + +interface ParameterDefaultsAware extends Reflection { + implementationDefaultParameters: string[]; +} + +/** + * TypeDoc EventCallback for EVENT_CREATE_DECLARATION events that reads the default parameters from the implementation. + */ +export const parameterDefaultReader: EventCallback = ( + context: Context, + reflection: Reflection +): void => { + const symbol = context.project.getSymbolFromReflection(reflection); + if (!symbol) return; + + if ( + reflection.kindOf(reflectionKindFunctionOrMethod) && + symbol.declarations?.length + ) { + const lastDeclaration = symbol.declarations[symbol.declarations.length - 1]; + if (TypeScript.isFunctionLike(lastDeclaration)) { + (reflection as ParameterDefaultsAware).implementationDefaultParameters = + lastDeclaration.parameters.map((param) => + cleanParameterDefault(param.initializer?.getText()) + ); + } + } +}; + +/** + * Removes compile expressions that don't add any value for readers. + * + * @param value The default value to clean. + * @returns The cleaned default value. + */ +function cleanParameterDefault(value?: string): string { + if (value == null) { + return undefined; + } + // Strip type casts: "'foobar' as unknown as T" => "'foobar'" + return value.replace(/ as unknown as [A-Za-z<>]+/, ''); +} + +/** + * Serializer that adds the `implementationDefaultParameters` to the JSON output. + */ +export class DefaultParameterAwareSerializer extends SerializerComponent { + serializeGroup(instance: unknown): boolean { + return instance instanceof Reflection; + } + + supports(item: unknown): boolean { + return true; + } + + toObject(item: Reflection, obj?: object): Partial { + (obj as ParameterDefaultsAware).implementationDefaultParameters = ( + item as ParameterDefaultsAware + ).implementationDefaultParameters; + return obj; + } +} + +/** + * Replaces all methods' last signature's parameter's default value with the default value read from the implementation. + * + * @param project The project to patch. + */ +export function patchProjectParameterDefaults( + project: ProjectReflection +): void { + const functionOrMethods = project.getReflectionsByKind( + reflectionKindFunctionOrMethod + ) as DeclarationReflection[]; + for (const functionOrMethod of functionOrMethods) { + patchMethodParameterDefaults(functionOrMethod); + } +} + +/** + * Replaces the last signature's parameter's default value with the default value read from the implementation. + * + * @param method The method to patch. + */ +function patchMethodParameterDefaults(method: DeclarationReflection): void { + const signatures = method.signatures; + const signature = signatures[signatures.length - 1]; + const parameterDefaults = (method as unknown as ParameterDefaultsAware) + .implementationDefaultParameters; + if (parameterDefaults) { + patchSignatureParameterDefaults(signature, parameterDefaults); + } +} + +/** + * Replaces the given signature's parameter's default value with the given default values. + * + * @param signature The signature to patch. + * @param parameterDefaults The defaults to add. + */ +function patchSignatureParameterDefaults( + signature: SignatureReflection, + parameterDefaults: string[] +): void { + const signatureParameters = signature.parameters; + if (signatureParameters.length !== parameterDefaults.length) { + throw new Error('Unexpected parameter length mismatch'); + } + signatureParameters.forEach( + (param, index) => + (param.defaultValue = parameterDefaults[index] || param.defaultValue) + ); +}