- {__( - 'All background images in your stories will be scaled to fill the screen for all mobile devices.', - 'web-stories' - )} -
-- {__( - 'Use this option if resizing the background image is not an issue.', - 'web-stories' - )} -
-- {createInterpolateElement( - __( - 'Your story will be centered vertically on the device. The page’s background color will cover any additional space. For better visual results, set the page background color to match the color of the background image.', - 'web-stories' - ), - { - b: , - mark: , - } - )} -
-- {__( - 'Use this option if you need elements to be precisely aligned to the background.', - 'web-stories' - )} -
-${getValidHTML(s)}
`; + }) + .join(''); + return stateFromHTML(htmlWithBreaks, { customInlineFn }); +} + +export default importHTML; diff --git a/assets/src/edit-story/components/richText/customInlineDisplay.js b/assets/src/edit-story/components/richText/customInlineDisplay.js new file mode 100644 index 000000000000..8e75fb6297a4 --- /dev/null +++ b/assets/src/edit-story/components/richText/customInlineDisplay.js @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed 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 + * + * https://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. + */ + +/** + * Internal dependencies + */ +import formatters from './formatters'; +import { fauxStylesToCSS } from './fauxSelection'; + +function customInlineDisplay(styles) { + const stylesToCSSConverters = [ + ...formatters.map(({ stylesToCSS }) => stylesToCSS), + fauxStylesToCSS, + ]; + + return stylesToCSSConverters.reduce( + (css, stylesToCSS) => ({ ...css, ...stylesToCSS(styles) }), + {} + ); +} + +export default customInlineDisplay; diff --git a/assets/src/edit-story/components/richText/draftUtils.js b/assets/src/edit-story/components/richText/draftUtils.js new file mode 100644 index 000000000000..356c9a05b85d --- /dev/null +++ b/assets/src/edit-story/components/richText/draftUtils.js @@ -0,0 +1,75 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed 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 + * + * https://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. + */ + +/* Ignore reason: This is lifted from elsewhere - a combo of these basically: + * + * https://github.com/webdeveloperpr/draft-js-custom-styles/blob/f3e6b533905de8eee6da54f9727b5e5803d53fc4/src/index.js#L8-L52 + * https://github.com/facebook/draft-js/issues/602#issuecomment-584676405 + */ +/* istanbul ignore next */ + +/** + * This returns *an array of sets of styles* for all currently selected + * characters. + * + * If you have the following states with html tags representing styles + * and [] representing selection),you get the following returns: + * + *${draftMarkupToContent(s, bold)}
`; - }) - .join(''); - let state = EditorState.createWithContent(stateFromHTML(contentWithBreaks)); - if (clearContent) { - // If `clearContent` is specified, push the update to clear content so that - // it can be undone. - state = EditorState.push(state, stateFromHTML(''), 'remove-range'); - } - let selection; - if (selectAll) { - selection = getSelectionForAll(state.getCurrentContent()); - } else if (offset) { - selection = getSelectionForOffset(state.getCurrentContent(), offset); - } - if (selection) { - state = EditorState.forceSelection(state, selection); - } - return state; - }, [content, clearContent, selectAll, offset, bold]); - const [editorState, setEditorState] = useState(initialState); + const wrapperRef = useRef(null); + const textBoxRef = useRef(null); + const editorRef = useRef(null); + const contentRef = useRef(); const editorHeightRef = useRef(0); - // This is to allow the finalizing useEffect to *not* depend on editorState, - // as would otherwise be a lint error. - const lastKnownState = useRef(null); - - // This filters out illegal content (see `getFilteredState`) - // on paste and updates state accordingly. - // Furthermore it also sets initial selection if relevant. - const updateEditorState = useCallback( - (newEditorState) => { - const filteredState = getFilteredState(newEditorState, editorState); - lastKnownState.current = filteredState.getCurrentContent(); - setEditorState(filteredState); - }, - [editorState] - ); - - // Handle basic key commands such as bold, italic and underscore. - const handleKeyCommand = getHandleKeyCommand(updateEditorState); - // Make sure to allow the user to click in the text box while working on the text. const onClick = (evt) => { const editor = editorRef.current; // Refocus the editor if the container outside it is clicked. - if (!editor.editorContainer.contains(evt.target)) { + if (!editor.getNode().contains(evt.target)) { editor.focus(); } evt.stopPropagation(); }; + // Set focus when initially rendered. + useLayoutEffect(() => { + if (editorRef.current) { + editorRef.current.focus(); + } + }, []); + const updateContent = useCallback(() => { - const newState = lastKnownState.current; const newHeight = editorHeightRef.current; wrapperRef.current.style.height = ''; - if (newState) { + if (contentRef.current) { // Remove manual line breaks and remember to trim any trailing non-breaking space. - const properties = { - content: stateToHTML(lastKnownState.current, { - defaultBlockTag: null, - }) - .replace(/