diff --git a/scripts/apps/archive/directives/HtmlPreview.ts b/scripts/apps/archive/directives/HtmlPreview.ts index 51e4e5fdcc..d6111a41ab 100644 --- a/scripts/apps/archive/directives/HtmlPreview.ts +++ b/scripts/apps/archive/directives/HtmlPreview.ts @@ -1,3 +1,4 @@ +import {adjustHTMLForPreview} from 'apps/authoring/preview/field-types/html'; import {getAnnotationsFromItem} from 'core/editor3/helpers/editor3CustomData'; import {META_FIELD_NAME} from 'core/editor3/helpers/fieldsMeta'; import ng from 'core/services/ng'; @@ -60,7 +61,7 @@ export function HtmlPreview($sce, $timeout) { templateUrl: 'scripts/apps/archive/views/html-preview.html', link: function(scope, elem, attrs) { scope.$watch('sdHtmlPreview', (html) => { - scope.html = $sce.trustAsHtml(html); + scope.html = $sce.trustAsHtml(adjustHTMLForPreview(html)); if (window.hasOwnProperty('instgrm')) { window.instgrm.Embeds.process(); diff --git a/scripts/apps/authoring/preview/field-types/html.tsx b/scripts/apps/authoring/preview/field-types/html.tsx index 76337c8200..3c2b0ef397 100644 --- a/scripts/apps/authoring/preview/field-types/html.tsx +++ b/scripts/apps/authoring/preview/field-types/html.tsx @@ -1,13 +1,41 @@ +import {sdApi} from 'api'; import React from 'react'; interface IProps { value: string; } +export function adjustHTMLForPreview(html: string): string { + const parsed: HTMLElement = + new DOMParser().parseFromString(html, 'text/html').body; + + parsed.querySelectorAll('[data-custom-block-type]').forEach((element) => { + const customBlockType = element.getAttribute('data-custom-block-type'); + const vocabulary = sdApi.vocabularies.getAll().get(customBlockType); + const separator = '
'; + + element.innerHTML = `
+ ${separator} + +
+ ${vocabulary.display_name} +
+ + ${element.innerHTML} + + ${separator} +
`; + }); + + return parsed.innerHTML; +} + export class HtmlPreview extends React.Component { render() { + const html = this.props.value; + return ( -
+
); } } diff --git a/scripts/apps/authoring/styles/themes.scss b/scripts/apps/authoring/styles/themes.scss index 47aa5a25e7..9fa13f7972 100644 --- a/scripts/apps/authoring/styles/themes.scss +++ b/scripts/apps/authoring/styles/themes.scss @@ -442,7 +442,7 @@ body, html { width: 100%; display: table; table-layout: fixed; - margin: 10px 0; + margin-top: 1.5em; &.item-association { margin: 0; } diff --git a/scripts/core/editor3/components/custom-block.scss b/scripts/core/editor3/components/custom-block.scss index d734d3f750..f1ad789ef3 100644 --- a/scripts/core/editor3/components/custom-block.scss +++ b/scripts/core/editor3/components/custom-block.scss @@ -1,6 +1,8 @@ .editor3-custom-block { .table-block table td { - border: 1px solid var(--sd-editor-colour__controls-border)!important; + border: 1px solid var(--sd-editor-colour__controls-border) !important; + border-radius: 0 var(--b-radius--large) var(--b-radius--large); + padding: var(--space--1-5) !important; } .table-inside table { @@ -15,7 +17,6 @@ .editor3-custom-block--label { font-size: 11px; font-weight: 500; - color: var(--color-text); text-transform: uppercase; letter-spacing: 0.08em; padding-block-start: 1px; // make text be vertically in the center of the bounding box @@ -26,21 +27,22 @@ --handle-height: 14px; display: flex; - padding: 4px 8px; - padding-inline-start: 4px; // less padding for drag handle - gap: 8px; + padding: var(--space--0-5) var(--space--1); + gap: var(--gap-1); align-items: center; cursor: grab; - border-start-start-radius: 2px; - border-start-end-radius: 2px; - + border-start-start-radius: var(--b-radius--medium); + border-start-end-radius: var(--b-radius--medium); background: var(--sd-editor-colour__controls-border); - + opacity: 0.8; + transition: opacity 0.2s ease; + color: currentColor; &:hover { - background: gray; + opacity: 1; } - &:active { - background:var(--sd-colour-primary); + background-color: var(--sd-colour-interactive); + color: white; + } } diff --git a/scripts/core/editor3/components/toolbar/TableControls.tsx b/scripts/core/editor3/components/toolbar/TableControls.tsx index ff2251f7cf..f2daefc503 100644 --- a/scripts/core/editor3/components/toolbar/TableControls.tsx +++ b/scripts/core/editor3/components/toolbar/TableControls.tsx @@ -111,14 +111,12 @@ const TableControlsComponent: React.FunctionComponent = (props) => { return ( <> { - editorFormat.includes('link') && ( - setTablePopup(PopupTypes.Link, payload)} - iconName="link" - tooltip={gettext('Link')} - /> - ) + setTablePopup(PopupTypes.Link, payload)} + iconName="link" + tooltip={gettext('Link')} + /> } { @@ -129,11 +127,6 @@ const TableControlsComponent: React.FunctionComponent = (props) => { /> ) } - - setTablePopup(PopupTypes.Link, payload)} - /> ); } else if (type in inlineStyles) { @@ -161,6 +154,12 @@ const TableControlsComponent: React.FunctionComponent = (props) => { } }) } + + {/* LinkToolbar must be the last node. */} + setTablePopup(PopupTypes.Link, payload)} + />
); }; diff --git a/scripts/core/editor3/html/to-html/AtomicBlockParser.ts b/scripts/core/editor3/html/to-html/AtomicBlockParser.ts index d43948a2a1..16bdaa6a95 100644 --- a/scripts/core/editor3/html/to-html/AtomicBlockParser.ts +++ b/scripts/core/editor3/html/to-html/AtomicBlockParser.ts @@ -8,6 +8,7 @@ import {CustomEditor3Entity} from 'core/editor3/constants'; import {IEditorDragDropArticleEmbed} from 'core/editor3/reducers/editor3'; import {assertNever} from 'core/helpers/typescript-helpers'; import {sdApi} from 'api'; +import {configurableAlgorithms} from 'core/ui/configurable-algorithms'; /** * @ngdoc class @@ -231,33 +232,24 @@ export class AtomicBlockParser { return ''; } - function getHighestHeadingText(el: HTMLElement): string | null { - const headings: Array = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; - - for (const tag of headings) { - const result = el.querySelector(tag); - - if (result != null) { - return result.textContent; - } - } - - return null; - } - + const vocabulary = sdApi.vocabularies.getAll().get(data.vocabularyId); + const blockId = vocabulary._id; const {cells} = data; - const blockName = sdApi.vocabularies.getAll().get(data.vocabularyId).display_name; const cellContentState: ContentState = convertFromRaw(cells[0][0]); const tableCellContentHtml = editor3StateToHtml(cellContentState); - const tableCellContentElement: HTMLElement = - new DOMParser().parseFromString(tableCellContentHtml, 'text/html').body; - const heading: string | null = getHighestHeadingText(tableCellContentElement); - const attributes = [`data-custom-block-type="${blockName}"`]; - if (heading != null) { - attributes.push(`data-custom-block-title="${heading}"`); - } + const attributes: Array<{name: string; value: string}> = [ + {name: 'data-custom-block-type', value: blockId}, + ...( + configurableAlgorithms.editor3?.customBlocks?.getAdditionalWrapperAttributes( + vocabulary, + tableCellContentHtml, + ) ?? [] + ), + ]; + + const attributesString = attributes.map(({name, value}) => `${name}="${value}"`).join(' '); - return `
${tableCellContentHtml}
`; + return `
${tableCellContentHtml}
`; } } diff --git a/scripts/core/editor3/styles.scss b/scripts/core/editor3/styles.scss index daab8a2bd3..43b9541819 100644 --- a/scripts/core/editor3/styles.scss +++ b/scripts/core/editor3/styles.scss @@ -936,7 +936,6 @@ $editor-styleButton-size: 3rem; right: auto; z-index: 10; box-shadow: 0px 1px 5px #00000066; - background-color: #f8f8f8; } .sd-input-style .Editor3-root { diff --git a/scripts/core/superdesk-api.d.ts b/scripts/core/superdesk-api.d.ts index 66fd9bff48..179d804405 100644 --- a/scripts/core/superdesk-api.d.ts +++ b/scripts/core/superdesk-api.d.ts @@ -2034,10 +2034,11 @@ declare module 'superdesk-api' { export interface IConfigurableAlgorithms { countLines?(plainText: string, lineLength: number): number; - } - - export interface IConfigurableAlgorithms { - countLines?(plainText: string, lineLength: number): number; + editor3?: { + customBlocks?: { + getAdditionalWrapperAttributes?(customBlockVocabulary: IVocabulary, html: string): Array<{name: string; value: string}>; + }; + } } export interface IListItemProps {