From f3fcedc8645dff750bc47c7d2280a2cae176b612 Mon Sep 17 00:00:00 2001 From: Scott Aslan Date: Fri, 11 Oct 2024 07:30:40 -0600 Subject: [PATCH] [NIFI-13844] add copy button to markdown code syntax highlighting (#9348) * [NIFI-13844] add copy button to markdown code syntax highlighting * only show copy button on code block hover * update markdown-clipboard-toolbar position and prism padding This closes #9348 --- .../src/main/frontend/apps/nifi/project.json | 3 ++- .../frontend/apps/nifi/src/app/app.module.ts | 13 ++++++--- .../additional-details.component.html | 2 +- .../libs/shared/src/assets/styles/_app.scss | 9 +++++++ .../src/assets/styles/_prism-theme.scss | 5 ++++ .../copy-button/copy-button.component.ts | 27 +++++++++++++++++++ .../libs/shared/src/components/index.ts | 1 + .../src/main/frontend/package-lock.json | 18 +++++-------- nifi-frontend/src/main/frontend/package.json | 1 + 9 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 nifi-frontend/src/main/frontend/libs/shared/src/components/copy-button/copy-button.component.ts diff --git a/nifi-frontend/src/main/frontend/apps/nifi/project.json b/nifi-frontend/src/main/frontend/apps/nifi/project.json index 1c5ce7ce48..32c08c5c4a 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/project.json +++ b/nifi-frontend/src/main/frontend/apps/nifi/project.json @@ -43,7 +43,8 @@ "node_modules/prismjs/components/prism-xml-doc.min.js", "node_modules/prismjs/components/prism-yaml.min.js", "node_modules/prismjs/components/prism-sql.min.js", - "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.js" + "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.js", + "node_modules/clipboard/dist/clipboard.min.js" ], "allowedCommonJsDependencies": ["codemirror"], "preserveSymlinks": true diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/app.module.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/app.module.ts index a3ba23189b..270f8c989f 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/app.module.ts +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/app.module.ts @@ -47,7 +47,7 @@ import { FlowConfigurationEffects } from './state/flow-configuration/flow-config import { ComponentStateEffects } from './state/component-state/component-state.effects'; import { ErrorEffects } from './state/error/error.effects'; import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { PipesModule } from '@nifi/shared'; +import { CopyButtonComponent, PipesModule } from '@nifi/shared'; import { DocumentationEffects } from './state/documentation/documentation.effects'; import { ClusterSummaryEffects } from './state/cluster-summary/cluster-summary.effects'; import { PropertyVerificationEffects } from './state/property-verification/property-verification.effects'; @@ -55,7 +55,7 @@ import { loadingInterceptor } from './service/interceptors/loading.interceptor'; import { LoginConfigurationEffects } from './state/login-configuration/login-configuration.effects'; import { BannerTextEffects } from './state/banner-text/banner-text.effects'; import { MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipDefaultOptions } from '@angular/material/tooltip'; -import { provideMarkdown } from 'ngx-markdown'; +import { CLIPBOARD_OPTIONS, provideMarkdown } from 'ngx-markdown'; const entry = localStorage.getItem('disable-animations'); let disableAnimations: string = entry !== null ? JSON.parse(entry).item : ''; @@ -121,7 +121,14 @@ export const customTooltipDefaults: MatTooltipDefaultOptions = { }) ), { provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: customTooltipDefaults }, - provideMarkdown() + provideMarkdown({ + clipboardOptions: { + provide: CLIPBOARD_OPTIONS, + useValue: { + buttonComponent: CopyButtonComponent + } + } + }) ] }) export class AppModule {} diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/documentation/ui/common/additional-details/additional-details.component.html b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/documentation/ui/common/additional-details/additional-details.component.html index 2c43459bfa..1f5df02bcd 100644 --- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/documentation/ui/common/additional-details/additional-details.component.html +++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/documentation/ui/common/additional-details/additional-details.component.html @@ -26,7 +26,7 @@ } @else { @if (additionalDetailsState.additionalDetails; as additionalDetails) { - + } @else if (additionalDetailsState.error) {
{{ additionalDetailsState.error }} diff --git a/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss b/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss index 5f9ed4fd16..08633e1431 100644 --- a/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss +++ b/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss @@ -825,4 +825,13 @@ ngx-skeleton-loader .skeleton-loader { background: $border-color; } + + .markdown-clipboard-toolbar { + opacity: 0; + transition: opacity 250ms ease-out; + } + + .markdown-clipboard-toolbar.hover { + opacity: 1; + } } diff --git a/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_prism-theme.scss b/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_prism-theme.scss index 55623bc659..b31efb2b5b 100644 --- a/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_prism-theme.scss +++ b/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_prism-theme.scss @@ -42,6 +42,11 @@ ); $selected-color: $material-theme-tertiary-palette-variant; + pre[class*='language-'] { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + } + code[class*='language-'], pre[class*='language-'] { color: if($is-material-dark, #f07178, #ec000c); diff --git a/nifi-frontend/src/main/frontend/libs/shared/src/components/copy-button/copy-button.component.ts b/nifi-frontend/src/main/frontend/libs/shared/src/components/copy-button/copy-button.component.ts new file mode 100644 index 0000000000..6486be9310 --- /dev/null +++ b/nifi-frontend/src/main/frontend/libs/shared/src/components/copy-button/copy-button.component.ts @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { MatIconButton } from '@angular/material/button'; + +@Component({ + selector: 'copy-button', + template: ` `, + imports: [MatIconButton], + standalone: true +}) +export class CopyButtonComponent {} diff --git a/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts b/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts index 9f61252dbc..642ee0104b 100644 --- a/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts +++ b/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts @@ -19,6 +19,7 @@ export * from './close-on-escape-dialog/close-on-escape-dialog.component'; export * from './component-context/component-context.component'; export * from './map-table/editors/text-editor/text-editor.component'; export * from './map-table/map-table.component'; +export * from './copy-button/copy-button.component'; export * from './new-map-table-entry-dialog/new-map-table-entry-dialog.component'; export * from './resizable/resizable.component'; export * from './tooltips/text-tip/text-tip.component'; diff --git a/nifi-frontend/src/main/frontend/package-lock.json b/nifi-frontend/src/main/frontend/package-lock.json index cc435fad1e..7ada930dec 100644 --- a/nifi-frontend/src/main/frontend/package-lock.json +++ b/nifi-frontend/src/main/frontend/package-lock.json @@ -27,6 +27,7 @@ "@ngrx/store": "18.0.2", "@ngrx/store-devtools": "18.0.2", "@types/js-beautify": "^1.14.3", + "clipboard": "^2.0.11", "codemirror": "^5.65.16", "d3": "^7.8.5", "font-awesome": "4.7.0", @@ -10799,7 +10800,6 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", - "optional": true, "dependencies": { "good-listener": "^1.2.2", "select": "^1.1.2", @@ -12430,8 +12430,7 @@ "node_modules/delegate": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "optional": true + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" }, "node_modules/delegates": { "version": "1.0.0", @@ -12756,9 +12755,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.35", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.35.tgz", - "integrity": "sha512-hOSRInrIDm0Brzp4IHW2F/VM+638qOL2CzE0DgpnGzKW27C95IqqeqgKz/hxHGnvPxvQGpHUGD5qRVC9EZY2+A==", + "version": "1.5.36", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.36.tgz", + "integrity": "sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==", "dev": true }, "node_modules/emittery": { @@ -14540,7 +14539,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", - "optional": true, "dependencies": { "delegate": "^3.1.2" } @@ -22388,8 +22386,7 @@ "node_modules/select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", - "optional": true + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==" }, "node_modules/select-hose": { "version": "2.0.0", @@ -23793,8 +23790,7 @@ "node_modules/tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "optional": true + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" }, "node_modules/tinyexec": { "version": "0.3.0", diff --git a/nifi-frontend/src/main/frontend/package.json b/nifi-frontend/src/main/frontend/package.json index 7ef830da6e..171c9421b7 100644 --- a/nifi-frontend/src/main/frontend/package.json +++ b/nifi-frontend/src/main/frontend/package.json @@ -33,6 +33,7 @@ "@ngrx/store": "18.0.2", "@ngrx/store-devtools": "18.0.2", "@types/js-beautify": "^1.14.3", + "clipboard": "^2.0.11", "codemirror": "^5.65.16", "d3": "^7.8.5", "font-awesome": "4.7.0",