Skip to content

Commit 52c46d4

Browse files
authored
Merge pull request #139 from Automattic/fix/alternate-visual-text
Fix alternating visual and text mode in the classic editor
2 parents 503e579 + 991b49c commit 52c46d4

File tree

1 file changed

+79
-21
lines changed

1 file changed

+79
-21
lines changed

syntaxhighlighter.js

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
( function($) {
2-
var shortcodes = window.syntaxHLcodes || 'sourcecode',
1+
( function( $ ) {
2+
const shortcodes = window.syntaxHLcodes || 'sourcecode',
33
regex = new RegExp( '(?:<pre>\\s*)?(\\[(' + shortcodes + ')[^\\]]*\\][\\s\\S]*?\\[\\/\\2\\])(?:\\s*<\\/pre>)?', 'gi' );
44

55
window.syntaxHLescape = {};
@@ -8,24 +8,82 @@
88
return;
99
}
1010

11-
$( document ).on( 'afterPreWpautop.syntaxhighlighter', function( event, obj ) {
12-
if ( obj.data && obj.data.indexOf( '[' ) !== -1 ) {
11+
// Constants.
12+
const $DOC = $( document );
13+
const PRESERVE = 'PRESERVE';
14+
const RESTORE = 'RESTORE';
15+
16+
// Tags that are removed by the core and their replacement to prevent being removed.
17+
const tagsToPreserve = [
18+
[ 'p', 'wp-p' ],
19+
[ 'br', 'wp-br' ],
20+
];
21+
22+
function replaceTag( code, from, to ) {
23+
const tagRegex = new RegExp( `<(\/?)${ from }([>\\s\/]+)`, 'gi' );
24+
return code.replace( tagRegex, `<$1${ to }$2` );
25+
}
26+
27+
function replaceTagsToPreserve( code, action ) {
28+
const indexReplaced = action === PRESERVE ? 0 : 1;
29+
const indexReplacement = action === PRESERVE ? 1 : 0;
30+
let newCode = code;
31+
32+
tagsToPreserve.forEach( function( tags ) {
33+
newCode = replaceTag( newCode, tags[ indexReplaced ], tags[ indexReplacement ] );
34+
} );
35+
36+
return newCode;
37+
}
38+
39+
function preserveTags( code ) {
40+
return replaceTagsToPreserve( code, PRESERVE );
41+
}
42+
43+
function restoreTags( code ) {
44+
return replaceTagsToPreserve( code, RESTORE );
45+
}
46+
47+
function unescapeTags( code ) {
48+
return code.replace( /&lt;/g, '<' ).replace( /&gt;/g, '>' ).replace( /&amp;/g, '&' );
49+
}
50+
51+
const events = {
52+
afterPreWpautop: function( event, obj ) {
53+
if ( obj.data && obj.data.indexOf( '[' ) === -1 ) {
54+
return;
55+
}
56+
1357
obj.data = obj.data.replace( regex, function( match, shortcode ) {
14-
return '\n' + shortcode.replace( /&lt;/g, '<' ).replace( /&gt;/g, '>' ).replace( /&amp;/g, '&' ) + '\n';
15-
}
16-
);
17-
}
18-
}).on( 'beforeWpautop.syntaxhighlighter', function( event, obj ) {
19-
if ( obj.data && obj.data.indexOf( '[' ) !== -1 ) {
20-
obj.data = obj.data.replace( regex, '<pre>$1</pre>' );
21-
}
22-
}).ready( function() {
23-
$( '.wp-editor-wrap.html-active' ).each( function( i, element ) {
24-
var id = $( element ).find( 'textarea.wp-editor-area' ).attr( 'id' );
25-
26-
if ( id ) {
27-
window.syntaxHLescape[id] = true;
58+
return '\n' + restoreTags( unescapeTags( shortcode ) ) + '\n';
59+
} );
60+
},
61+
afterWpautop: function( event, obj ) {
62+
if ( obj.data && obj.data.indexOf( '[' ) === -1 ) {
63+
return;
2864
}
29-
});
30-
});
31-
}( window.jQuery ));
65+
66+
const unfilteredCodes = obj.unfiltered.match( regex );
67+
let i = 0;
68+
69+
obj.data = obj.data.replace( regex, function() {
70+
// Replace by the unfiltered code piece.
71+
const unfilteredCode = unfilteredCodes[ i++ ];
72+
return `<pre>${ preserveTags( unfilteredCode ) }</pre>`;
73+
} );
74+
},
75+
documentReady: function() {
76+
$( '.wp-editor-wrap.html-active' ).each( function( i, element ) {
77+
const id = $( element ).find( 'textarea.wp-editor-area' ).attr( 'id' );
78+
79+
if ( id ) {
80+
window.syntaxHLescape[ id ] = true;
81+
}
82+
} );
83+
},
84+
};
85+
86+
$DOC.on( 'afterPreWpautop.syntaxhighlighter', events.afterPreWpautop );
87+
$DOC.on( 'afterWpautop.syntaxhighlighter', events.afterWpautop );
88+
$DOC.ready( events.documentReady );
89+
}( window.jQuery ) );

0 commit comments

Comments
 (0)