Skip to content

Commit f9e0873

Browse files
committed
WYSIWYG: Added text direction support for code editor popup
Editor popup will now reflect the direction of the opened code block. This also updates in-editor codemirror instances to correcly reflect/use the direction if set on the inner code elem. This also defaults new code blocks, when in RTL languages, to be started in LTR, which can then be changed via in-editor direction controls if needed. This is on the assumption that most code will be LTR (could not find much examples of RTL code use). Fixes #4943
1 parent 4c1c315 commit f9e0873

File tree

4 files changed

+43
-11
lines changed

4 files changed

+43
-11
lines changed

resources/js/code/index.mjs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ function addCopyIcon(editorView) {
3838
});
3939
}
4040

41+
/**
42+
* @param {HTMLElement} codeElem
43+
* @returns {String}
44+
*/
45+
function getDirectionFromCodeBlock(codeElem) {
46+
let dir = '';
47+
const innerCodeElem = codeElem.querySelector('code');
48+
49+
if (innerCodeElem && innerCodeElem.hasAttribute('dir')) {
50+
dir = innerCodeElem.getAttribute('dir');
51+
} else if (codeElem.hasAttribute('dir')) {
52+
dir = codeElem.getAttribute('dir');
53+
}
54+
55+
return dir;
56+
}
57+
4158
/**
4259
* Add code highlighting to a single element.
4360
* @param {HTMLElement} elem
@@ -48,16 +65,14 @@ function highlightElem(elem) {
4865
const content = elem.textContent.trimEnd();
4966

5067
let langName = '';
51-
let innerCodeDirection = '';
5268
if (innerCodeElem !== null) {
5369
langName = innerCodeElem.className.replace('language-', '');
54-
innerCodeDirection = innerCodeElem.getAttribute('dir');
5570
}
5671

5772
const wrapper = document.createElement('div');
5873
elem.parentNode.insertBefore(wrapper, elem);
5974

60-
const direction = innerCodeDirection || elem.getAttribute('dir') || '';
75+
const direction = getDirectionFromCodeBlock(elem);
6176
if (direction) {
6277
wrapper.setAttribute('dir', direction);
6378
}

resources/js/components/code-editor.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,15 @@ export class CodeEditor extends Component {
129129
this.hide();
130130
}
131131

132-
async open(code, language, saveCallback, cancelCallback) {
132+
async open(code, language, direction, saveCallback, cancelCallback) {
133133
this.languageInput.value = language;
134134
this.saveCallback = saveCallback;
135135
this.cancelCallback = cancelCallback;
136136

137137
await this.show();
138138
this.languageInputChange(language);
139139
this.editor.setContent(code);
140+
this.setDirection(direction);
140141
}
141142

142143
async show() {
@@ -156,6 +157,15 @@ export class CodeEditor extends Component {
156157
});
157158
}
158159

160+
setDirection(direction) {
161+
const target = this.editorInput.parentElement;
162+
if (direction) {
163+
target.setAttribute('dir', direction);
164+
} else {
165+
target.removeAttribute('dir');
166+
}
167+
}
168+
159169
hide() {
160170
this.getPopup().hide();
161171
this.addHistory();

resources/js/wysiwyg/plugin-codeeditor.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ function elemIsCodeBlock(elem) {
66
* @param {Editor} editor
77
* @param {String} code
88
* @param {String} language
9+
* @param {String} direction
910
* @param {function(string, string)} callback (Receives (code: string,language: string)
1011
*/
11-
function showPopup(editor, code, language, callback) {
12+
function showPopup(editor, code, language, direction, callback) {
1213
/** @var {CodeEditor} codeEditor * */
1314
const codeEditor = window.$components.first('code-editor');
1415
const bookMark = editor.selection.getBookmark();
15-
codeEditor.open(code, language, (newCode, newLang) => {
16+
codeEditor.open(code, language, direction, (newCode, newLang) => {
1617
callback(newCode, newLang);
1718
editor.focus();
1819
editor.selection.moveToBookmark(bookMark);
@@ -27,7 +28,8 @@ function showPopup(editor, code, language, callback) {
2728
* @param {CodeBlockElement} codeBlock
2829
*/
2930
function showPopupForCodeBlock(editor, codeBlock) {
30-
showPopup(editor, codeBlock.getContent(), codeBlock.getLanguage(), (newCode, newLang) => {
31+
const direction = codeBlock.getAttribute('dir') || '';
32+
showPopup(editor, codeBlock.getContent(), codeBlock.getLanguage(), direction, (newCode, newLang) => {
3133
codeBlock.setContent(newCode, newLang);
3234
});
3335
}
@@ -179,13 +181,17 @@ function register(editor) {
179181
showPopupForCodeBlock(editor, selectedNode);
180182
} else {
181183
const textContent = editor.selection.getContent({format: 'text'});
182-
showPopup(editor, textContent, '', (newCode, newLang) => {
184+
const direction = document.dir === 'rtl' ? 'ltr' : '';
185+
showPopup(editor, textContent, '', direction, (newCode, newLang) => {
183186
const pre = doc.createElement('pre');
184187
const code = doc.createElement('code');
185188
code.classList.add(`language-${newLang}`);
186189
code.innerText = newCode;
187-
pre.append(code);
190+
if (direction) {
191+
pre.setAttribute('dir', direction);
192+
}
188193

194+
pre.append(code);
189195
editor.insertContent(pre.outerHTML);
190196
});
191197
}
@@ -205,7 +211,8 @@ function register(editor) {
205211
contenteditable: 'false',
206212
});
207213

208-
const direction = el.attr('dir');
214+
const childCodeBlock = el.children().filter(child => child.name === 'code')[0] || null;
215+
const direction = el.attr('dir') || (childCodeBlock && childCodeBlock.attr('dir')) || '';
209216
if (direction) {
210217
wrapper.attr('dir', direction);
211218
}

resources/sass/_components.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@
182182
flex: 0;
183183
.popup-title {
184184
color: #FFF;
185-
margin-right: auto;
185+
margin-inline-end: auto;
186186
padding: 8px $-m;
187187
}
188188
&.flex-container-row {

0 commit comments

Comments
 (0)