run:R W Run
5.94 KB
2026-03-11 16:18:51
R W Run
2.83 KB
2026-03-11 16:18:51
R W Run
error_log
📄plugin.js
1/**
2 * WordPress View plugin.
3 */
4( function( tinymce ) {
5 tinymce.PluginManager.add( 'wpview', function( editor ) {
6 function noop () {}
7
8 // Set this here as wp-tinymce.js may be loaded too early.
9 var wp = window.wp;
10
11 if ( ! wp || ! wp.mce || ! wp.mce.views ) {
12 return {
13 getView: noop
14 };
15 }
16
17 // Check if a node is a view or not.
18 function isView( node ) {
19 return editor.dom.hasClass( node, 'wpview' );
20 }
21
22 // Replace view tags with their text.
23 function resetViews( content ) {
24 function callback( match, $1 ) {
25 return '<p>' + window.decodeURIComponent( $1 ) + '</p>';
26 }
27
28 if ( ! content || content.indexOf( ' data-wpview-' ) === -1 ) {
29 return content;
30 }
31
32 return content
33 .replace( /<div[^>]+data-wpview-text="([^"]+)"[^>]*>(?:\.|[\s\S]+?wpview-end[^>]+>\s*<\/span>\s*)?<\/div>/g, callback )
34 .replace( /<p[^>]+data-wpview-marker="([^"]+)"[^>]*>[\s\S]*?<\/p>/g, callback );
35 }
36
37 editor.on( 'init', function() {
38 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
39
40 if ( MutationObserver ) {
41 new MutationObserver( function() {
42 editor.fire( 'wp-body-class-change' );
43 } )
44 .observe( editor.getBody(), {
45 attributes: true,
46 attributeFilter: ['class']
47 } );
48 }
49
50 // Pass on body class name changes from the editor to the wpView iframes.
51 editor.on( 'wp-body-class-change', function() {
52 var className = editor.getBody().className;
53
54 editor.$( 'iframe[class="wpview-sandbox"]' ).each( function( i, iframe ) {
55 // Make sure it is a local iframe.
56 // jshint scripturl: true
57 if ( ! iframe.src || iframe.src === 'javascript:""' ) {
58 try {
59 iframe.contentWindow.document.body.className = className;
60 } catch( er ) {}
61 }
62 });
63 } );
64 });
65
66 // Scan new content for matching view patterns and replace them with markers.
67 editor.on( 'beforesetcontent', function( event ) {
68 var node;
69
70 if ( ! event.selection ) {
71 wp.mce.views.unbind();
72 }
73
74 if ( ! event.content ) {
75 return;
76 }
77
78 if ( ! event.load ) {
79 node = editor.selection.getNode();
80
81 if ( node && node !== editor.getBody() && /^\s*https?:\/\/\S+\s*$/i.test( event.content ) ) {
82 // When a url is pasted or inserted, only try to embed it when it is in an empty paragraph.
83 node = editor.dom.getParent( node, 'p' );
84
85 if ( node && /^[\s\uFEFF\u00A0]*$/.test( editor.$( node ).text() || '' ) ) {
86 // Make sure there are no empty inline elements in the <p>.
87 node.innerHTML = '';
88 } else {
89 return;
90 }
91 }
92 }
93
94 event.content = wp.mce.views.setMarkers( event.content, editor );
95 } );
96
97 // Replace any new markers nodes with views.
98 editor.on( 'setcontent', function() {
99 wp.mce.views.render();
100 } );
101
102 // Empty view nodes for easier processing.
103 editor.on( 'preprocess hide', function( event ) {
104 editor.$( 'div[data-wpview-text], p[data-wpview-marker]', event.node ).each( function( i, node ) {
105 node.innerHTML = '.';
106 } );
107 }, true );
108
109 // Replace views with their text.
110 editor.on( 'postprocess', function( event ) {
111 event.content = resetViews( event.content );
112 } );
113
114 // Prevent adding of undo levels when replacing wpview markers
115 // or when there are changes only in the (non-editable) previews.
116 editor.on( 'beforeaddundo', function( event ) {
117 var lastContent;
118 var newContent = event.level.content || ( event.level.fragments && event.level.fragments.join( '' ) );
119
120 if ( ! event.lastLevel ) {
121 lastContent = editor.startContent;
122 } else {
123 lastContent = event.lastLevel.content || ( event.lastLevel.fragments && event.lastLevel.fragments.join( '' ) );
124 }
125
126 if (
127 ! newContent ||
128 ! lastContent ||
129 newContent.indexOf( ' data-wpview-' ) === -1 ||
130 lastContent.indexOf( ' data-wpview-' ) === -1
131 ) {
132 return;
133 }
134
135 if ( resetViews( lastContent ) === resetViews( newContent ) ) {
136 event.preventDefault();
137 }
138 } );
139
140 // Make sure views are copied as their text.
141 editor.on( 'drop objectselected', function( event ) {
142 if ( isView( event.targetClone ) ) {
143 event.targetClone = editor.getDoc().createTextNode(
144 window.decodeURIComponent( editor.dom.getAttrib( event.targetClone, 'data-wpview-text' ) )
145 );
146 }
147 } );
148
149 // Clean up URLs for easier processing.
150 editor.on( 'pastepreprocess', function( event ) {
151 var content = event.content;
152
153 if ( content ) {
154 content = tinymce.trim( content.replace( /<[^>]+>/g, '' ) );
155
156 if ( /^https?:\/\/\S+$/i.test( content ) ) {
157 event.content = content;
158 }
159 }
160 } );
161
162 // Show the view type in the element path.
163 editor.on( 'resolvename', function( event ) {
164 if ( isView( event.target ) ) {
165 event.name = editor.dom.getAttrib( event.target, 'data-wpview-type' ) || 'object';
166 }
167 } );
168
169 // See `media` plugin.
170 editor.on( 'click keyup', function() {
171 var node = editor.selection.getNode();
172
173 if ( isView( node ) ) {
174 if ( editor.dom.getAttrib( node, 'data-mce-selected' ) ) {
175 node.setAttribute( 'data-mce-selected', '2' );
176 }
177 }
178 } );
179
180 editor.addButton( 'wp_view_edit', {
181 tooltip: 'Edit|button', // '|button' is not displayed, only used for context.
182 icon: 'dashicon dashicons-edit',
183 onclick: function() {
184 var node = editor.selection.getNode();
185
186 if ( isView( node ) ) {
187 wp.mce.views.edit( editor, node );
188 }
189 }
190 } );
191
192 editor.addButton( 'wp_view_remove', {
193 tooltip: 'Remove',
194 icon: 'dashicon dashicons-no',
195 onclick: function() {
196 editor.fire( 'cut' );
197 }
198 } );
199
200 editor.once( 'preinit', function() {
201 var toolbar;
202
203 if ( editor.wp && editor.wp._createToolbar ) {
204 toolbar = editor.wp._createToolbar( [
205 'wp_view_edit',
206 'wp_view_remove'
207 ] );
208
209 editor.on( 'wptoolbar', function( event ) {
210 if ( ! event.collapsed && isView( event.element ) ) {
211 event.toolbar = toolbar;
212 }
213 } );
214 }
215 } );
216
217 editor.wp = editor.wp || {};
218 editor.wp.getView = noop;
219 editor.wp.setViewCursor = noop;
220
221 return {
222 getView: noop
223 };
224 } );
225} )( window.tinymce );
226