From eb659d5ed8c06017df04539251047876f1bda11a Mon Sep 17 00:00:00 2001 From: splincode Date: Fri, 24 Nov 2023 13:32:02 +0300 Subject: [PATCH] feat(addon-copy): add type reference handler for improve documentation --- .../documentation/documentation.module.ts | 6 +- .../documentation/documentation.style.less | 27 +++++++++ .../documentation/documentation.template.html | 32 +++++----- .../pipes/content-tooltip.pipe.ts | 8 --- .../pipes/type-reference.pipe.ts | 31 ++++++++++ projects/addon-doc/components/index.ts | 2 +- .../addon-doc/components/main/main.style.less | 5 +- projects/addon-doc/tokens/index.ts | 1 + .../tokens/type-reference-handler.ts | 12 ++++ projects/addon-doc/utils/index.ts | 1 + .../utils/test/type-reference-parser.spec.ts | 58 +++++++++++++++++++ .../addon-doc/utils/type-reference-parser.ts | 30 ++++++++++ .../demo/src/modules/app/app.providers.ts | 30 ++++++++++ .../components/link/link.template.html | 6 +- 14 files changed, 215 insertions(+), 34 deletions(-) delete mode 100644 projects/addon-doc/components/documentation/pipes/content-tooltip.pipe.ts create mode 100644 projects/addon-doc/components/documentation/pipes/type-reference.pipe.ts create mode 100644 projects/addon-doc/tokens/type-reference-handler.ts create mode 100644 projects/addon-doc/utils/test/type-reference-parser.spec.ts create mode 100644 projects/addon-doc/utils/type-reference-parser.ts diff --git a/projects/addon-doc/components/documentation/documentation.module.ts b/projects/addon-doc/components/documentation/documentation.module.ts index 4e7e9a494cc3..c44f584b0f17 100644 --- a/projects/addon-doc/components/documentation/documentation.module.ts +++ b/projects/addon-doc/components/documentation/documentation.module.ts @@ -12,7 +12,6 @@ import { TuiNotificationModule, TuiPrimitiveTextfieldModule, TuiTextfieldControllerModule, - TuiTooltipModule, } from '@taiga-ui/core'; import { TuiBadgeModule, @@ -27,12 +26,12 @@ import {TuiDocDocumentationComponent} from './documentation.component'; import {TuiDocDocumentationPropertyConnectorDirective} from './documentation-property-connector.directive'; import {TuiShowCleanerPipe} from './pipes/cleaner.pipe'; import {TuiGetColorPipe} from './pipes/color.pipe'; -import {TuiShowContentTooltip} from './pipes/content-tooltip.pipe'; import {TuiInspectPipe} from './pipes/inspect.pipe'; import {TuiGetOpacityPipe} from './pipes/opacity.pipe'; import {TuiIsOptionalPipe} from './pipes/optional.pipe'; import {TuiIsPrimitivePolymorpheusContentPipe} from './pipes/primitive-polymorpheus-content.pipe'; import {TuiStripOptionalPipe} from './pipes/strip-optional.pipe'; +import {TuiDocTypeReferencePipe} from './pipes/type-reference.pipe'; @NgModule({ imports: [ @@ -42,7 +41,6 @@ import {TuiStripOptionalPipe} from './pipes/strip-optional.pipe'; TuiBadgeModule, TuiSelectModule, TuiToggleModule, - TuiTooltipModule, TuiLinkModule, TuiInputNumberModule, TuiModeModule, @@ -63,7 +61,7 @@ import {TuiStripOptionalPipe} from './pipes/strip-optional.pipe'; TuiIsOptionalPipe, TuiShowCleanerPipe, TuiStripOptionalPipe, - TuiShowContentTooltip, + TuiDocTypeReferencePipe, TuiDocDocumentationComponent, TuiIsPrimitivePolymorpheusContentPipe, TuiDocDocumentationPropertyConnectorDirective, diff --git a/projects/addon-doc/components/documentation/documentation.style.less b/projects/addon-doc/components/documentation/documentation.style.less index 1ed56c806a46..2a931f9441b4 100644 --- a/projects/addon-doc/components/documentation/documentation.style.less +++ b/projects/addon-doc/components/documentation/documentation.style.less @@ -110,3 +110,30 @@ .t-heading { font: var(--tui-font-heading-4); } + +.t-code-type { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: start; +} + +.t-code-reference { + display: inline-flex; + color: var(--tui-link); + text-decoration: none; + align-items: center; + justify-content: center; + gap: 3px; + + &:after { + content: ''; + font-size: 1rem; + width: 1rem; + height: 1rem; + background: currentColor; + // TODO: migrate to in v4.0 + mask: url('data:image/svg+xml,') + center/100%; + } +} diff --git a/projects/addon-doc/components/documentation/documentation.template.html b/projects/addon-doc/components/documentation/documentation.template.html index 2e535d5a4f33..341128501022 100644 --- a/projects/addon-doc/components/documentation/documentation.template.html +++ b/projects/addon-doc/components/documentation/documentation.template.html @@ -49,25 +49,27 @@ - {{ propertyConnector.documentationPropertyType }} - - - {{ texts[4] }} + + - ng-polymorpheus + {{ item.type }} - - + + {{ item.type }} + +  |  + + , + @Inject(TUI_DOC_TYPE_REFERENCE_HANDLER) + private readonly linkHandler?: TuiStringHandler | null, + ) {} + + transform(original: string): ReadonlyArray<{ + type: string; + extracted: string; + reference: string | null; + }> { + return this.parser(original) + .map(({type, extracted}) => ({ + type, + extracted, + reference: this.linkHandler?.(extracted) ?? null, + })) + .sort((a, b) => b.reference?.localeCompare(a.reference ?? ``) ?? -1); + } +} diff --git a/projects/addon-doc/components/index.ts b/projects/addon-doc/components/index.ts index 0804d364fc13..6dd67cae8878 100644 --- a/projects/addon-doc/components/index.ts +++ b/projects/addon-doc/components/index.ts @@ -9,12 +9,12 @@ export * from './documentation/documentation.module'; export * from './documentation/documentation-property-connector.directive'; export * from './documentation/pipes/cleaner.pipe'; export * from './documentation/pipes/color.pipe'; -export * from './documentation/pipes/content-tooltip.pipe'; export * from './documentation/pipes/inspect.pipe'; export * from './documentation/pipes/opacity.pipe'; export * from './documentation/pipes/optional.pipe'; export * from './documentation/pipes/primitive-polymorpheus-content.pipe'; export * from './documentation/pipes/strip-optional.pipe'; +export * from './documentation/pipes/type-reference.pipe'; export * from './example/example.component'; export * from './example/example.module'; export * from './example/example.options'; diff --git a/projects/addon-doc/components/main/main.style.less b/projects/addon-doc/components/main/main.style.less index dd3b7aeeb874..2cae7eba3d06 100644 --- a/projects/addon-doc/components/main/main.style.less +++ b/projects/addon-doc/components/main/main.style.less @@ -57,9 +57,10 @@ code:not(pre code) { align-items: center; border-radius: 0.25rem; font-weight: 500; - border: 1px solid var(--tui-base-04); + outline: 1px solid var(--tui-base-04); font-size: 0.75rem; - padding: 0 0.125rem; + padding: 0 0.3125rem; + margin: 0.125rem 0; //noinspection CssInvalidPropertyValue text-wrap: wrap; diff --git a/projects/addon-doc/tokens/index.ts b/projects/addon-doc/tokens/index.ts index e410fd95f758..06256437a3a4 100644 --- a/projects/addon-doc/tokens/index.ts +++ b/projects/addon-doc/tokens/index.ts @@ -12,4 +12,5 @@ export * from './scroll-behavior'; export * from './see-also'; export * from './source-code'; export * from './title'; +export * from './type-reference-handler'; export * from './url-state-handler'; diff --git a/projects/addon-doc/tokens/type-reference-handler.ts b/projects/addon-doc/tokens/type-reference-handler.ts new file mode 100644 index 000000000000..8ebf176e1c45 --- /dev/null +++ b/projects/addon-doc/tokens/type-reference-handler.ts @@ -0,0 +1,12 @@ +import { + TuiDocTypeReferenceParsed, + tuiTypeReferenceParser, +} from '@taiga-ui/addon-doc/utils'; +import {tuiCreateToken, TuiHandler, TuiStringHandler} from '@taiga-ui/cdk'; + +export const TUI_DOC_TYPE_REFERENCE_HANDLER = tuiCreateToken | null>(null); + +export const TUI_DOC_TYPE_REFERENCE_PARSER = + tuiCreateToken>(tuiTypeReferenceParser); diff --git a/projects/addon-doc/utils/index.ts b/projects/addon-doc/utils/index.ts index 220f7ea1a983..cfa1afa6dad8 100644 --- a/projects/addon-doc/utils/index.ts +++ b/projects/addon-doc/utils/index.ts @@ -9,3 +9,4 @@ export * from './raw-load-record'; export * from './sort-pages'; export * from './to-flat-map-pages'; export * from './transliterate-keyboard-layout'; +export * from './type-reference-parser'; diff --git a/projects/addon-doc/utils/test/type-reference-parser.spec.ts b/projects/addon-doc/utils/test/type-reference-parser.spec.ts new file mode 100644 index 000000000000..7009a4c4c110 --- /dev/null +++ b/projects/addon-doc/utils/test/type-reference-parser.spec.ts @@ -0,0 +1,58 @@ +import {tuiTypeReferenceParser} from '@taiga-ui/addon-doc'; + +describe(`tuiTypeReferenceParser`, () => { + it(`parse`, () => { + expect( + tuiTypeReferenceParser(` + PolymorpheusContent> + | Map + | ReadonlyArray + | readonly string[] + | T + | ReadonlyArray + | [TuiDay, number][] + | TuiStringHandler + | null + | readonly [number, number] + | 'positive' + | 'negative' + | -1 + | 2 + | 0 + | void + | CustomEvent + | TuiComparator + | readonly T[] + | TuiDay + | [TuiTime, TuiTime] + | T[][] + `), + ).toEqual([ + { + type: `PolymorpheusContent>`, + extracted: `PolymorpheusContent`, + }, + {type: `Map`, extracted: `Map`}, + {type: `ReadonlyArray`, extracted: `string`}, + {type: `readonly string[]`, extracted: `string`}, + {type: `T`, extracted: `unknown`}, + {type: `ReadonlyArray`, extracted: `number`}, + {type: `[TuiDay, number][]`, extracted: `TuiDay`}, + {type: `TuiStringHandler`, extracted: `TuiStringHandler`}, + {type: `null`, extracted: `null`}, + {type: `readonly [number, number]`, extracted: `number`}, + {type: `'positive'`, extracted: `string`}, + {type: `'negative'`, extracted: `string`}, + {type: `-1`, extracted: `number`}, + {type: `2`, extracted: `number`}, + {type: `0`, extracted: `number`}, + {type: `void`, extracted: `void`}, + {type: `CustomEvent`, extracted: `CustomEvent`}, + {type: `TuiComparator`, extracted: `TuiComparator`}, + {type: `readonly T[]`, extracted: `unknown`}, + {type: `TuiDay`, extracted: `TuiDay`}, + {type: `[TuiTime, TuiTime]`, extracted: `TuiTime`}, + {type: `T[][]`, extracted: `unknown`}, + ]); + }); +}); diff --git a/projects/addon-doc/utils/type-reference-parser.ts b/projects/addon-doc/utils/type-reference-parser.ts new file mode 100644 index 000000000000..e1e0ca6075d4 --- /dev/null +++ b/projects/addon-doc/utils/type-reference-parser.ts @@ -0,0 +1,30 @@ +export type TuiDocTypeReferenceParsed = ReadonlyArray<{type: string; extracted: string}>; + +export function tuiTypeReferenceParser(types: string): TuiDocTypeReferenceParsed { + const generics = types.match(/<([^>]+)>/g) ?? []; + + const escaped = generics + .reduce( + (result, current) => result.replace(current, current.replace(/\|/g, `&`)), + types, + ) + .split(`|`) + .map(item => item.trim()); + + return escaped.reduce((result, type) => { + let extracted = type + .trim() + .replace(/readonly /g, ``) + .replace(/\[\]/g, ``); + + extracted = + extracted.match(/ReadonlyArray<([^>]+)>/)?.[1]?.split(`&`)?.[0] ?? extracted; + extracted = extracted.match(/\[([^\]]+)\]/)?.[1]?.split(`,`)?.[0] ?? extracted; + extracted = (extracted.split(`<`)?.[0] ?? extracted)?.trim() ?? ``; + extracted = Number.isNaN(parseFloat(extracted)) ? extracted : `number`; + extracted = /^'(.+)'$|^"(.+)"$|^`(.+)`$/.test(extracted) ? `string` : extracted; + extracted = extracted.length === 1 ? `unknown` : extracted; + + return result.concat({type: type.replace(/&/g, `|`), extracted}); + }, []); +} diff --git a/projects/demo/src/modules/app/app.providers.ts b/projects/demo/src/modules/app/app.providers.ts index 328d44305fe5..5b948c73ab23 100644 --- a/projects/demo/src/modules/app/app.providers.ts +++ b/projects/demo/src/modules/app/app.providers.ts @@ -20,6 +20,7 @@ import { TUI_DOC_SEE_ALSO, TUI_DOC_SOURCE_CODE, TUI_DOC_TITLE, + TUI_DOC_TYPE_REFERENCE_HANDLER, TUI_DOC_URL_STATE_HANDLER, tuiDocExampleOptionsProvider, TuiDocSourceCodePathOptions, @@ -197,6 +198,35 @@ export const APP_PROVIDERS: Provider[] = [ useFactory: (baseHref: string) => (tree: UrlTree) => String(tree).replace(baseHref, ``), }, + { + provide: TUI_DOC_TYPE_REFERENCE_HANDLER, + useValue: (type: string) => { + switch (type) { + case `any`: + case `null`: + case `unknown`: + case `undefined`: + case `boolean`: + case `string`: + case `void`: + case `number`: + case `Map`: + case `Set`: + return null; + case `CustomEvent`: + case `Element`: + return `https://developer.mozilla.org/en-US/docs/Web/API/${type}`; + case `PolymorpheusContent`: + return `https://github.com/taiga-family/ng-polymorpheus`; + case `TrackByFunction`: + return `https://angular.dev/api/core/TrackByFunction`; + case `SafeResourceUrl`: + return `https://angular.dev/api/platform-browser/SafeResourceUrl`; + default: + return `https://github.com/search?q=%2F%28enum%7Ctype%7Cinterface%7Cclass%7Cfunction%7Cconst%29+${type}%28%3C%7C%5Cs%29%2F+language%3ATypeScript+org%3Ataiga-family&type=code`; + } + }, + }, tuiDocExampleOptionsProvider({fullsize: false}), tuiLanguageSwitcher( async (language: TuiLanguageName): Promise => diff --git a/projects/demo/src/modules/components/link/link.template.html b/projects/demo/src/modules/components/link/link.template.html index d2e3d5f80f27..b5bbd7745647 100644 --- a/projects/demo/src/modules/components/link/link.template.html +++ b/projects/demo/src/modules/components/link/link.template.html @@ -72,8 +72,7 @@ @@ -82,8 +81,7 @@