@atlaskit/adf-schema
Version:
Shared package that contains the ADF-schema (json) and ProseMirror node/mark specs
341 lines (325 loc) • 15.8 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toJSONTableHeader = exports.toJSONTableCell = exports.tableWithNestedTable = exports.tableWithCustomWidth = exports.tableToJSON = exports.tableStage0 = exports.tableRowWithNestedTable = exports.tableRow = exports.tablePrefixSelector = exports.tableHeaderWithNestedTable = exports.tableHeaderSelector = exports.tableHeader = exports.tableCellWithNestedTable = exports.tableCellSelector = exports.tableCellContentWrapperSelector = exports.tableCellContentDomSelector = exports.tableCell = exports.tableBackgroundColorPalette = exports.tableBackgroundColorNames = exports.tableBackgroundBorderColor = exports.table = exports.setGlobalTheme = exports.getCellDomAttrs = exports.getCellAttrs = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _editorPalette = require("../../utils/editor-palette");
var _colors = require("../../utils/colors");
var _uuid = require("../../utils/uuid");
var _lchColorInversion = require("../../utils/lch-color-inversion");
var _nodeTypes = require("../../next-schema/generated/nodeTypes");
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var tablePrefixSelector = exports.tablePrefixSelector = 'pm-table';
var tableCellSelector = exports.tableCellSelector = "".concat(tablePrefixSelector, "-cell-content-wrap");
var tableHeaderSelector = exports.tableHeaderSelector = "".concat(tablePrefixSelector, "-header-content-wrap");
var tableCellContentWrapperSelector = exports.tableCellContentWrapperSelector = "".concat(tablePrefixSelector, "-cell-nodeview-wrapper");
var tableCellContentDomSelector = exports.tableCellContentDomSelector = "".concat(tablePrefixSelector, "-cell-nodeview-content-dom");
var DEFAULT_TABLE_HEADER_CELL_BACKGROUND = _colors.N20.toLocaleLowerCase();
var getCellAttrs = exports.getCellAttrs = function getCellAttrs(dom) {
var defaultValues = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var widthAttr = dom.getAttribute('data-colwidth');
var width = widthAttr && /^\d+(,\d+)*$/.test(widthAttr) ? widthAttr.split(',').map(function (str) {
return Number(str);
}) : null;
var colspan = Number(dom.getAttribute('colspan') || 1);
var backgroundColor = dom.style.backgroundColor;
/**
* We have pivoted to store background color information in
* data-cell-background.
* We will have original hex code (which we map to DST token)
* stored in data-cell-background, use that.
* More details at https://product-fabric.atlassian.net/wiki/spaces/EUXQ/pages/3472556903/Tokenising+tableCell+background+colors#Update-toDom-and-parseDom-to-store-and-read-background-color-from-data-cell-background-attribute.4
*/
var dataCellBackground = dom.getAttribute('data-cell-background');
var dataCellBackgroundHexCode = dataCellBackground && (0, _colors.isHex)(dataCellBackground) ? dataCellBackground : undefined;
// ignore setting background attr if ds neutral token is detected
if (backgroundColor.includes('--ds-background-neutral')) {
backgroundColor = '';
} else {
if (backgroundColor && (0, _colors.isRgb)(backgroundColor)) {
var result = (0, _colors.rgbToHex)(backgroundColor);
if (result !== null) {
backgroundColor = result;
}
}
}
var backgroundHexCode = dataCellBackgroundHexCode || (backgroundColor && backgroundColor !== defaultValues['background'] ? backgroundColor : null);
return {
colspan: colspan,
rowspan: Number(dom.getAttribute('rowspan') || 1),
colwidth: width && width.length === colspan ? width : null,
background: backgroundHexCode
};
};
// these are for test only
var testGlobalTheme;
var setGlobalTheme = exports.setGlobalTheme = function setGlobalTheme(theme) {
testGlobalTheme = theme;
};
// This is a minimal duplication of the method from @atlaskit/tokens
// to minimise the number of dependencies required as these changes are expected
// to be patched onto CR8.
var getGlobalTheme = function getGlobalTheme() {
// This should only be hit during tests.
//
// At time of writing Jest mocks are not working in this repository.
if (testGlobalTheme) {
return {
colorMode: testGlobalTheme
};
}
var element = document.documentElement;
var colorMode = element.getAttribute('data-color-mode') || '';
return {
colorMode: colorMode
};
};
var cssVariablePattern = /^var\(--.*\)$/;
/**
* gets cell dom attributes based on node attributes
* @returns CellDomAttrs
*/
var getCellDomAttrs = exports.getCellDomAttrs = function getCellDomAttrs(node) {
var attrs = {};
var nodeType = node.type.name;
if (node.attrs.colspan !== 1) {
attrs.colspan = node.attrs.colspan;
}
if (node.attrs.rowspan !== 1) {
attrs.rowspan = node.attrs.rowspan;
}
if (node.attrs.colwidth) {
attrs['data-colwidth'] = node.attrs.colwidth.join(',');
}
if (node.attrs.background) {
var background = node.attrs.background;
// to ensure that we don't overwrite product's style:
// - it clears background color for <th> if its set to gray
// - it clears background color for <td> if its set to white
// - it clears background color for <th> if ds neutral token is detected
var ignored = nodeType === 'tableHeader' && background === tableBackgroundColorNames.get('light gray') || nodeType === 'tableCell' && background === tableBackgroundColorNames.get('white') || nodeType === 'tableHeader' && background.includes('--ds-background-neutral');
if (ignored) {
attrs.style = '';
} else {
var color = (0, _colors.isRgb)(background) && (0, _colors.rgbToHex)(background) ? (0, _colors.rgbToHex)(background) : background;
/**
* The Editor supports users pasting content from external sources with custom table cell backgrounds and having those
* backgrounds persisted.
*
* This feature predates the introduction of dark mode.
*
* Without the inversion logic below, tokenised content (ie. text), can be hard to read when the user loads the page in dark mode.
*
* This introduces inversion of the presentation of the custom background color when the user is in dark mode.
*
* This can be done without additional changes to account for users copying and pasting content inside the Editor, because of
* how we detect table cell background colors copied from external editor sources. Where we load the background color from a
* seperate attribute (data-cell-background), instead of the inline style.
*
* See the following document for more details on this behaviour
* https://hello.atlassian.net/wiki/spaces/CCECO/pages/2892247168/Unsupported+custom+table+cell+background+colors+in+dark+theme+Editor+Job+Story
*/
var tokenColor = (0, _editorPalette.hexToEditorBackgroundPaletteRawValue)(color);
if (tokenColor) {
attrs.style = "background-color: ".concat(tokenColor, ";");
} else if (
/**
* There was previously a bug in dark mode where we would attempt to invert
* a design token in `getDarkModeLCHColor` causing issues.
* If it's a design token we should return it as is.
*/
cssVariablePattern.test(color)) {
attrs.style = "background-color: ".concat(color, ";");
} else {
// if we have a custom color, we need to check if we are in dark mode
if (getGlobalTheme().colorMode === 'dark') {
// if we have a custom color, we need to check if we are in dark mode
attrs.style = "background-color: ".concat((0, _lchColorInversion.getDarkModeLCHColor)(color), ";");
} else {
// if we are in light mode, we can just set the color
attrs.style = "background-color: ".concat(background, ";");
}
}
/**
* Storing hex code in data-cell-background because
* we want to have DST token (css variable) or
* DST token value (value (hex code) of css variable) in
* inline style to correct render table cell background
* based on selected theme.
* Currently we rely on background color hex code stored in
* inline style.
* Because of that when we copy and paste table, we end up
* having DST token or DST token value in ADF instead of
* original hex code which we map to DST token.
* So, introducing data-cell-background.
* More details at https://product-fabric.atlassian.net/wiki/spaces/EUXQ/pages/3472556903/Tokenising+tableCell+background+colors#Update-toDom-and-parseDom-to-store-and-read-background-color-from-data-cell-background-attribute.4
*/
if (color) {
attrs['data-cell-background'] = color;
}
attrs.colorname = tableBackgroundColorPalette.get(color);
}
}
if (nodeType === 'tableHeader') {
attrs.class = tableHeaderSelector;
} else {
attrs.class = tableCellSelector;
}
return attrs;
};
var tableBackgroundColorPalette = exports.tableBackgroundColorPalette = new Map();
var tableBackgroundBorderColor = exports.tableBackgroundBorderColor = (0, _colors.hexToRgba)(_colors.N800, 0.12) || _colors.N0;
var tableBackgroundColorNames = exports.tableBackgroundColorNames = new Map();
[[_colors.N0, 'White'], [_colors.B50, 'Light blue'], [_colors.T50, 'Light teal'], [_colors.G50, 'Light green'], [_colors.Y50, 'Light yellow'], [_colors.R50, 'Light red'], [_colors.P50, 'Light purple'], [_colors.N20, 'Light gray'], [_colors.B75, 'Blue'], [_colors.T75, 'Teal'], [_colors.G75, 'Green'], [_colors.Y75, 'Yellow'], [_colors.R75, 'Red'], [_colors.P75, 'Purple'], [_colors.N60, 'Gray'], [_colors.B100, 'Dark blue'], [_colors.T100, 'Dark teal'], [_colors.G200, 'Dark green'], [_colors.Y200, 'Dark yellow'], [_colors.R100, 'Dark red'], [_colors.P100, 'Dark purple']].forEach(function (_ref) {
var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
colorValue = _ref2[0],
colorName = _ref2[1];
tableBackgroundColorPalette.set(colorValue.toLowerCase(), colorName);
tableBackgroundColorNames.set(colorName.toLowerCase(), colorValue.toLowerCase());
});
/**
* @name table_node
*/
/**
* @name table_row_node
*/
/**
* @name table_cell_content
* @minItems 1
* @allowUnsupportedBlock true
*/
/**
* @name table_cell_node
*/
/**
* @name table_header_node
*/
// table nodes with nested tables support
var tableNodeSpecOptions = {
parseDOM: [{
tag: 'table',
getAttrs: function getAttrs(node) {
var _dom$parentElement;
var dom = node;
var breakoutWrapper = (_dom$parentElement = dom.parentElement) === null || _dom$parentElement === void 0 ? void 0 : _dom$parentElement.parentElement;
return {
isNumberColumnEnabled: dom.getAttribute('data-number-column') === 'true',
layout:
// copying from editor
dom.getAttribute('data-layout') || (// copying from renderer
breakoutWrapper === null || breakoutWrapper === void 0 ? void 0 : breakoutWrapper.getAttribute('data-layout')) || 'default',
__autoSize: dom.getAttribute('data-autosize') === 'true',
localId: dom.getAttribute('data-table-local-id') || _uuid.uuid.generate(),
width: Number(dom.getAttribute('data-table-width')) || null,
displayMode: dom.getAttribute('data-table-display-mode') || null
};
}
}],
toDOM: function toDOM(node) {
var attrs = {
'data-number-column': node.attrs.isNumberColumnEnabled,
'data-layout': node.attrs.layout,
'data-autosize': node.attrs.__autoSize,
'data-table-local-id': node.attrs.localId,
'data-table-width': node.attrs.width,
'data-table-display-mode': node.attrs.displayMode
};
return ['table', attrs, ['tbody', 0]];
}
};
// TODO: Fix any, potential issue. ED-5048
var createTableSpec = function createTableSpec() {
return (0, _nodeTypes.table)(tableNodeSpecOptions);
};
// TODO: assuming breaking changes aren't allowed, so retaining both exports
/** Includes table width attribute */
var table = exports.table = createTableSpec();
/** @deprecated Do not use, instead use the regular `table` export */
var tableWithCustomWidth = exports.tableWithCustomWidth = createTableSpec();
var tableStage0 = exports.tableStage0 = createTableSpec();
var shouldIncludeAttribute = function shouldIncludeAttribute(key, value) {
return !key.startsWith('__') && (key !== 'localId' || !!value);
};
var tableToJSON = exports.tableToJSON = function tableToJSON(node) {
return {
attrs: Object.keys(node.attrs).filter(function (key) {
return shouldIncludeAttribute(key, node.attrs[key]);
}).reduce(function (obj, key) {
return _objectSpread(_objectSpread({}, obj), {}, (0, _defineProperty2.default)({}, key, node.attrs[key]));
}, {})
};
};
var tableRowNodeSpecOptions = {
parseDOM: [{
tag: 'tr'
}],
toDOM: function toDOM() {
return ['tr', 0];
}
};
var tableRow = exports.tableRow = (0, _nodeTypes.tableRow)(tableRowNodeSpecOptions);
var cellAttrs = {
colspan: {
default: 1
},
rowspan: {
default: 1
},
colwidth: {
default: null
},
background: {
default: null
}
};
var tableCellNodeSpecOptions = {
parseDOM: [
// Ignore number cell copied from renderer
{
tag: '.ak-renderer-table-number-column',
ignore: true
}, {
tag: 'td',
getAttrs: function getAttrs(dom) {
return getCellAttrs(dom);
}
}],
toDOM: function toDOM(node) {
return ['td', getCellDomAttrs(node), 0];
}
};
var tableCell = exports.tableCell = (0, _nodeTypes.tableCell)(tableCellNodeSpecOptions);
var toJSONTableCell = exports.toJSONTableCell = function toJSONTableCell(node) {
return {
attrs: Object.keys(node.attrs).reduce(function (obj, key) {
if (cellAttrs[key].default !== node.attrs[key]) {
obj[key] = node.attrs[key];
}
return obj;
}, {})
};
};
var tableHeaderNodeSpecOptions = {
parseDOM: [{
tag: 'th',
getAttrs: function getAttrs(dom) {
return getCellAttrs(dom, {
background: DEFAULT_TABLE_HEADER_CELL_BACKGROUND
});
}
}],
toDOM: function toDOM(node) {
return ['th', getCellDomAttrs(node), 0];
}
};
var tableHeader = exports.tableHeader = (0, _nodeTypes.tableHeader)(tableHeaderNodeSpecOptions);
var toJSONTableHeader = exports.toJSONTableHeader = toJSONTableCell;
// table nodes with nested table support
var tableWithNestedTable = exports.tableWithNestedTable = (0, _nodeTypes.tableWithNestedTable)(tableNodeSpecOptions);
var tableRowWithNestedTable = exports.tableRowWithNestedTable = (0, _nodeTypes.tableRowWithNestedTable)(tableRowNodeSpecOptions);
var tableCellWithNestedTable = exports.tableCellWithNestedTable = (0, _nodeTypes.tableCellWithNestedTable)(tableCellNodeSpecOptions);
var tableHeaderWithNestedTable = exports.tableHeaderWithNestedTable = (0, _nodeTypes.tableHeaderWithNestedTable)(tableHeaderNodeSpecOptions);
;