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 {