UPDATE 2020/5/18: When I first published this patch I forgot to include the change to the root .htaccess file. This has been fixed and the links below now point to the updated patch.
UPDATE 2020/5/24: CSS change to force the hash in the meta line to wrap.
See below for the updated embeddable codeblocks patch. This is the third iteration after the first two discussions. This patch also now contains the server-side select mechanism, including the updates to xmlrpc.php. The functionality is included in what is now the MP-WP Content Processing plugin1 so it will work across all themes without modification.
You can grab the patch from the links below or from my code shelf.
mp-wp_add-embeddable-codeblocks-and-server-side-selection.vpatch
mp-wp_add-embeddable-codeblocks-and-server-side-selection.vpatch.billymg.sig
1 | diff -uNr a/mp-wp/.htaccess b/mp-wp/.htaccess |
2 | |
3 | |
4 | |
5 | RewriteBase / |
6 | RewriteCond %{REQUEST_FILENAME} !-f |
7 | RewriteCond %{REQUEST_FILENAME} !-d |
8 | -RewriteRule . /index.php [L] |
9 | +RewriteRule . /index.php [QSA,L] |
10 | </IfModule> |
11 | |
12 | # END WordPress |
13 | diff -uNr a/mp-wp/manifest b/mp-wp/manifest |
14 | |
15 | |
16 | |
17 | 605926 mp-wp_comments_filtering diana_coman Recent comments widget should show only people's comments (no track/pingbacks); theme default changed to show trackbacks/pingbacks as last/at the bottom in an article's comments list. |
18 | 629903 mp-wp_remove-textselectionjs-pop3-etc-r2 jfw Remove the unreliable JS-based selection (reground: including wrapper spans), posting by POP3 login, and a stray .php.orig file. Neutralize and comment the example pingback updater. |
19 | 629903 mp-wp_svg-screenshots-and-errorreporting-r2 jfw Allow .svg extensions in theme screenshot search. Don't clobber the user's errorreporting level without WP_DEBUG. (Reground following antecedent.) |
20 | +631542 mp-wp_add-embeddable-codeblocks-and-server-side-selection billymg Add embeddable codeblocks and the server-side select mechanism to the "footnotes" plugin (now "mp-wp content processing") |
21 | diff -uNr a/mp-wp/wp-content/plugins/footnotes.php b/mp-wp/wp-content/plugins/footnotes.php |
22 | |
23 | |
24 | |
25 | <?php |
26 | /* |
27 | -Plugin Name: WP-Footnotes |
28 | -Plugin URI: http://www.elvery.net/drzax/more-things/wordpress-footnotes-plugin/ |
29 | -Version: 4.2 |
30 | -Description: Allows a user to easily add footnotes to a post. |
31 | -Author: Simon Elvery |
32 | -Author URI: http://www.elvery.net/drzax/ |
33 | +Plugin Name: MP-WP Content Processing |
34 | +Plugin URI: http://billymg.com/category/mp-wp/ |
35 | +Description: Allows for the custom processing of article content. Currently supports footnotes and embedded vpatch snippets. |
36 | +Author: billymg |
37 | +Author URI: http://billymg.com |
38 | */ |
39 | |
40 | -/* |
41 | - * This file is part of WP-Footnotes a plugin for Word Press |
42 | - * Copyright (C) 2007 Simon Elvery |
43 | - * |
44 | - * This program is free software; you can redistribute it and/or |
45 | - * modify it under the terms of the GNU General Public License |
46 | - * as published by the Free Software Foundation; either version 2 |
47 | - * of the License, or (at your option) any later version. |
48 | - * |
49 | - * This program is distributed in the hope that it will be useful, |
50 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
51 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
52 | - * GNU General Public License for more details. |
53 | - * |
54 | - * You should have received a copy of the GNU General Public License |
55 | - * along with this program; if not, write to the Free Software |
56 | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
57 | - */ |
58 | - |
59 | -// Some important constants |
60 | -define('WP_FOOTNOTES_OPEN', " (("); //You can change this if you really have to, but I wouldn't recommend it. |
61 | -define('WP_FOOTNOTES_CLOSE', "))"); //Same with this one. |
62 | -define('WP_FOOTNOTES_VERSION', '4.2'); |
63 | - |
64 | // Instantiate the class |
65 | -$swas_wp_footnotes = new swas_wp_footnotes(); |
66 | +$mp_wp_content_processing = new mp_wp_content_processing(); |
67 | |
68 | // Encapsulate in a class |
69 | -class swas_wp_footnotes { |
70 | - var $current_options; |
71 | +class mp_wp_content_processing { |
72 | + const MP_WP_FOOTNOTES_OPEN = " (("; |
73 | + const MP_WP_FOOTNOTES_CLOSE = "))"; |
74 | + const MP_WP_CODEBLOCKS_PRIORITY = 9; // highest value that comes before wpautop filter |
75 | + const MP_WP_FOOTNOTES_PRIORITY = 11; |
76 | + |
77 | + var $options; |
78 | var $default_options; |
79 | |
80 | /** |
81 | * Constructor. |
82 | */ |
83 | - function swas_wp_footnotes() { |
84 | + function mp_wp_content_processing() { |
85 | // Define the implemented option styles |
86 | $this->styles = array( |
87 | 'decimal' => '1,2...10', |
88 | |
89 | ); |
90 | |
91 | // Define default options |
92 | - $this->default_options = array('superscript'=>true, |
93 | - 'pre_backlink'=>' [', |
94 | - 'backlink'=>'↩', |
95 | - 'post_backlink'=>']', |
96 | - 'pre_identifier'=>'', |
97 | - 'list_style_type'=>'decimal', |
98 | - 'list_style_symbol'=>'†', |
99 | - 'post_identifier'=>'', |
100 | - 'pre_footnotes'=>'', |
101 | - 'post_footnotes'=>'', |
102 | - 'style_rules'=>'ol.footnotes{font-size:0.8em; color:#666666;}', |
103 | - 'no_display_home'=>false, |
104 | - 'no_display_archive'=>false, |
105 | - 'no_display_date'=>false, |
106 | - 'no_display_category'=>false, |
107 | - 'no_display_search'=>false, |
108 | - 'no_display_feed'=>false, |
109 | - 'combine_identical_notes'=>false, |
110 | - 'priority'=>11, |
111 | - 'version'=>WP_FOOTNOTES_VERSION); |
112 | + $this->default_options = array( |
113 | + 'pre_backlink'=>' [', |
114 | + 'backlink'=>'↩', |
115 | + 'post_backlink'=>']', |
116 | + 'pre_identifier'=>'', |
117 | + 'list_style_type'=>'decimal', |
118 | + 'list_style_symbol'=>'†', |
119 | + 'post_identifier'=>'', |
120 | + 'pre_footnotes'=>'', |
121 | + 'post_footnotes'=>'' |
122 | + ); |
123 | |
124 | // Get the current settings or setup some defaults if needed |
125 | - if (!$this->current_options = get_option('swas_footnote_options')){ |
126 | - $this->current_options = $this->default_options; |
127 | - update_option('swas_footnote_options', $this->current_options); |
128 | - } else { |
129 | + $this->options = get_option('mp_wp_cpp_options'); |
130 | + if (!$this->options) { |
131 | + $this->options = $this->default_options; |
132 | + update_option('mp_wp_cpp_options', $this->options); |
133 | + } else { |
134 | // Set any unset options |
135 | - if ($this->current_options['version'] != WP_FOOTNOTES_VERSION) { |
136 | - foreach ($this->default_options as $key => $value) { |
137 | - if (!isset($this->current_options[$key])) { |
138 | - $this->current_options[$key] = $value; |
139 | - } |
140 | + $updated = false; |
141 | + foreach ($this->default_options as $key => $value) { |
142 | + if (!isset($this->options[$key])) { |
143 | + $this->options[$key] = $value; |
144 | + $updated = true; |
145 | } |
146 | - $this->current_options['version'] = WP_FOOTNOTES_VERSION; |
147 | - update_option('swas_footnote_options', $this->current_options); |
148 | + } |
149 | + if ($updated) { |
150 | + update_option('mp_wp_cpp_options', $this->options); |
151 | } |
152 | } |
153 | |
154 | -/* |
155 | - if (!empty($_POST['save_options'])){ |
156 | - $footnotes_options['superscript'] = (array_key_exists('superscript', $_POST)) ? true : false; |
157 | - $footnotes_options['pre_backlink'] = $_POST['pre_backlink']; |
158 | - $footnotes_options['backlink'] = $_POST['backlink']; |
159 | - $footnotes_options['post_backlink'] = $_POST['post_backlink']; |
160 | - $footnotes_options['pre_identifier'] = $_POST['pre_identifier']; |
161 | - $footnotes_options['list_style_type'] = $_POST['list_style_type']; |
162 | - $footnotes_options['post_identifier'] = $_POST['post_identifier']; |
163 | - $footnotes_options['list_style_symbol'] = $_POST['list_style_symbol']; |
164 | - $footnotes_options['pre_footnotes'] = stripslashes($_POST['pre_footnotes']); |
165 | - $footnotes_options['post_footnotes'] = stripslashes($_POST['post_footnotes']); |
166 | - $footnotes_options['style_rules'] = stripslashes($_POST['style_rules']); |
167 | - $footnotes_options['no_display_home'] = (array_key_exists('no_display_home', $_POST)) ? true : false; |
168 | - $footnotes_options['no_display_archive'] = (array_key_exists('no_display_archive', $_POST)) ? true : false; |
169 | - $footnotes_options['no_display_date'] = (array_key_exists('no_display_date', $_POST)) ? true : false; |
170 | - $footnotes_options['no_display_category'] = (array_key_exists('no_display_category', $_POST)) ? true : false; |
171 | - $footnotes_options['no_display_search'] = (array_key_exists('no_display_search', $_POST)) ? true : false; |
172 | - $footnotes_options['no_display_feed'] = (array_key_exists('no_display_feed', $_POST)) ? true : false; |
173 | - $footnotes_options['combine_identical_notes'] = (array_key_exists('combine_identical_notes', $_POST)) ? true : false; |
174 | - $footnotes_options['priority'] = $_POST['priority']; |
175 | - update_option('swas_footnote_options', $footnotes_options); |
176 | - }elseif(!empty($_POST['reset_options'])){ |
177 | - update_option('swas_footnote_options', ''); |
178 | - update_option('swas_footnote_options', $this->default_options); |
179 | - } |
180 | -*/ |
181 | - |
182 | // Hook me up |
183 | - add_action('the_content', array($this, 'process'), $this->current_options['priority']); |
184 | - add_action('admin_menu', array($this, 'add_options_page')); // Insert the Admin panel. |
185 | + add_action('the_content', array($this, 'process_codeblocks'), self::MP_WP_CODEBLOCKS_PRIORITY); |
186 | + add_action('the_content', array($this, 'process_footnotes'), self::MP_WP_FOOTNOTES_PRIORITY); |
187 | + add_filter('the_content', array($this, 'server_side_selection')); |
188 | add_action('wp_head', array($this, 'insert_styles')); |
189 | } |
190 | |
191 | + |
192 | + /** |
193 | + * Finds the selection from the query params. |
194 | + * @param $data string The content of the post. |
195 | + * @return string The new content with the highlighted selection. |
196 | + */ |
197 | + function server_side_selection($data) { |
198 | + //bookend code goes here |
199 | + $b_code = '<span class="mp-wp-selection" id="select">'; |
200 | + $b_code .= $_GET["b"]; |
201 | + $e_code = $_GET["e"].'</span>'; |
202 | + |
203 | + //change page ; last to first to preserve indexes. |
204 | + $b_pos = strpos($data,$_GET["b"]); |
205 | + $e_pos = strpos($data,$_GET["e"], $b_pos); |
206 | + if ($e_pos>0) |
207 | + $data = substr_replace($data, $e_code, $e_pos, strlen($_GET["e"])); |
208 | + if ($b_pos>0) |
209 | + $data = substr_replace($data, $b_code, $b_pos, strlen($_GET["b"])); |
210 | + return $data; |
211 | + } |
212 | + |
213 | + /** |
214 | + * Searches the text and apply markup to codeblocks. |
215 | + * Adds line number links and diff syntax highlighting. |
216 | + * @param $data string The content of the post. |
217 | + * @return string The new content with formatted codeblocks. |
218 | + */ |
219 | + function process_codeblocks($data) { |
220 | + global $post; |
221 | + |
222 | + // Regex extraction of all codeblocks (or return if there are none) |
223 | + if ( !preg_match_all("/\[([a-z]+)\[(.*)(\]\])/Us", $data, $codeblocks, PREG_SET_ORDER) ) { |
224 | + return $data; |
225 | + } |
226 | + |
227 | + for ($i = 0; $i < count($codeblocks); $i++) { |
228 | + $codeblocks[$i]['snippet'] = $this->format_snippet($codeblocks[$i][2], $codeblocks[$i][1], $i+1); |
229 | + } |
230 | + |
231 | + foreach ($codeblocks as $key => $value) { |
232 | + $data = substr_replace($data, $value['snippet'], strpos($data,$value[0]),strlen($value[0])); |
233 | + } |
234 | + |
235 | + return $data; |
236 | + } |
237 | + |
238 | + function format_snippet($snippet, $syntax, $snippet_number) { |
239 | + $highlighting_functions = array( |
240 | + 'plaintext' => 'highlight_as_plain_text', |
241 | + 'diff' => 'highlight_as_diff' |
242 | + ); |
243 | + |
244 | + if (is_null($highlighting_functions[$syntax])) { |
245 | + $syntax = 'plaintext'; |
246 | + } |
247 | + |
248 | + $code_lines = explode("\r\n", $snippet); |
249 | + |
250 | + foreach ($code_lines as $idx => $line) { |
251 | + $line_number = sprintf('S%d-L%d', $snippet_number, $idx+1); |
252 | + $line_link = sprintf('<a href="#%s" name="%s">%d</a>', $line_number, $line_number, $idx+1); |
253 | + $line_open = sprintf('<tr><td class="line-number-column">%s</td><td class="content-column">', $line_link); |
254 | + $line_close = '</td></tr>'; |
255 | + |
256 | + $code_lines[$idx] = $this->$highlighting_functions[$syntax]($line_open, $line, $line_close); |
257 | + } |
258 | + |
259 | + $formatted_snippet = implode("\n", $code_lines); |
260 | + |
261 | + $formatted_snippet = sprintf( |
262 | + '%s%s%s', |
263 | + '<div class="mp-wp-codeblock"><table cellpadding="0" cellspacing="0"><tbody>', |
264 | + $formatted_snippet, |
265 | + '</tbody></table></div>' |
266 | + ); |
267 | + |
268 | + return $formatted_snippet; |
269 | + } |
270 | + |
271 | + function highlight_as_plain_text($line_open, $line, $line_close) { |
272 | + return sprintf('%s<span class="line-default">%s</span>%s', $line_open, $line, $line_close); |
273 | + } |
274 | + |
275 | + function highlight_as_diff($line_open, $line, $line_close) { |
276 | + if (substr($line, 0, 5) == 'diff ') { |
277 | + $highlighted_line = sprintf('%s<span class="line-filename">%s</span>%s', $line_open, $line, $line_close); |
278 | + } elseif (substr($line, 0, 4) == '--- ' || substr($line, 0, 4) == '+++ ' || substr($line, 0, 3) == '@@ ') { |
279 | + $highlighted_line = sprintf('%s<span class="line-meta">%s</span>%s', $line_open, $line, $line_close); |
280 | + } elseif (substr($line, 0, 1) == '-') { |
281 | + $highlighted_line = sprintf('%s<span class="line-removed">%s</span>%s', $line_open, $line, $line_close); |
282 | + } elseif (substr($line, 0, 1) == '+') { |
283 | + $highlighted_line = sprintf('%s<span class="line-added">%s</span>%s', $line_open, $line, $line_close); |
284 | + } else { |
285 | + $highlighted_line = sprintf('%s<span class="line-default">%s</span>%s', $line_open, $line, $line_close); |
286 | + } |
287 | + |
288 | + return $highlighted_line; |
289 | + } |
290 | + |
291 | /** |
292 | * Searches the text and extracts footnotes. |
293 | * Adds the identifier links and creats footnotes list. |
294 | * @param $data string The content of the post. |
295 | * @return string The new content with footnotes generated. |
296 | */ |
297 | - function process($data) { |
298 | + function process_footnotes($data) { |
299 | global $post; |
300 | |
301 | // Check for and setup the starting number |
302 | $start_number = (preg_match("|<!\-\-startnum=(\d+)\-\->|",$data,$start_number_array)==1) ? $start_number_array[1] : 1; |
303 | |
304 | // Regex extraction of all footnotes (or return if there are none) |
305 | - if (!preg_match_all("/(".preg_quote(WP_FOOTNOTES_OPEN)."|<footnote>)(.*)(".preg_quote(WP_FOOTNOTES_CLOSE)."|<\/footnote>)/Us", $data, $identifiers, PREG_SET_ORDER)) { |
306 | + if (!preg_match_all("/(".preg_quote(self::MP_WP_FOOTNOTES_OPEN)."|<footnote>)(.*)(".preg_quote(self::MP_WP_FOOTNOTES_CLOSE)."|<\/footnote>)/Us", $data, $identifiers, PREG_SET_ORDER)) { |
307 | return $data; |
308 | } |
309 | |
310 | - // Check whether we are displaying them or not |
311 | - $display = true; |
312 | - if ($this->current_options['no_display_home'] && is_home()) $display = false; |
313 | - if ($this->current_options['no_display_archive'] && is_archive()) $display = false; |
314 | - if ($this->current_options['no_display_date'] && is_date()) $display = false; |
315 | - if ($this->current_options['no_display_category'] && is_category()) $display = false; |
316 | - if ($this->current_options['no_display_search'] && is_search()) $display = false; |
317 | - if ($this->current_options['no_display_feed'] && is_feed()) $display = false; |
318 | - |
319 | $footnotes = array(); |
320 | |
321 | // Check if this post is using a different list style to the settings |
322 | if ( array_key_exists(get_post_meta($post->ID, 'footnote_style', true), $this->styles) ) { |
323 | $style = get_post_meta($post->ID, 'footnote_style', true); |
324 | } else { |
325 | - $style = $this->current_options['list_style_type']; |
326 | + $style = $this->options['list_style_type']; |
327 | } |
328 | |
329 | // Create 'em |
330 | |
331 | $identifiers[$i]['text'] = $identifiers[$i][2]; |
332 | } |
333 | |
334 | - |
335 | - // if we're combining identical notes check if we've already got one like this & record keys |
336 | - if ($this->current_options['combine_identical_notes']){ |
337 | - for ($j=0; $j<count($footnotes); $j++){ |
338 | - if ($footnotes[$j]['text'] == $identifiers[$i]['text']){ |
339 | - $identifiers[$i]['use_footnote'] = $j; |
340 | - $footnotes[$j]['identifiers'][] = $i; |
341 | - break; |
342 | - } |
343 | - } |
344 | - } |
345 | - |
346 | - if (!isset($identifiers[$i]['use_footnote'])){ |
347 | - // Add footnote and record the key |
348 | - $identifiers[$i]['use_footnote'] = count($footnotes); |
349 | - $footnotes[$identifiers[$i]['use_footnote']]['text'] = $identifiers[$i]['text']; |
350 | - $footnotes[$identifiers[$i]['use_footnote']]['symbol'] = $identifiers[$i]['symbol']; |
351 | - $footnotes[$identifiers[$i]['use_footnote']]['identifiers'][] = $i; |
352 | - } |
353 | + // Add footnote and record the key |
354 | + $identifiers[$i]['use_footnote'] = count($footnotes); |
355 | + $footnotes[$identifiers[$i]['use_footnote']]['text'] = $identifiers[$i]['text']; |
356 | + $footnotes[$identifiers[$i]['use_footnote']]['symbol'] = $identifiers[$i]['symbol']; |
357 | + $footnotes[$identifiers[$i]['use_footnote']]['identifiers'][] = $i; |
358 | } |
359 | |
360 | // Footnotes and identifiers are stored in the array |
361 | |
362 | $id_id = "identifier_".$key."_".$post->ID; |
363 | $id_num = ($style == 'decimal') ? $value['use_footnote']+$start_number : $this->convert_num($value['use_footnote']+$start_number, $style, count($footnotes)); |
364 | $id_href = ( ($use_full_link) ? get_permalink($post->ID) : '' ) . "#footnote_".$value['use_footnote']."_".$post->ID; |
365 | - |
366 | -// $id_title = str_replace('"', """, htmlentities(strip_tags($value['text']), ENT_QUOTES, 'UTF-8')); |
367 | - |
368 | $id_title = str_replace('"', '`', strip_tags($value['text'])); |
369 | - $id_replace = $this->current_options['pre_identifier'].'<a href="'.$id_href.'" id="'.$id_id.'" class="footnote-link footnote-identifier-link" title="'.$id_title.'">'.$id_num.'</a>'.$this->current_options['post_identifier']; |
370 | - if ($this->current_options['superscript']) $id_replace = '<sup>'.$id_replace.'</sup>'; |
371 | - if ($display) $data = substr_replace($data, $id_replace, strpos($data,$value[0]),strlen($value[0])); |
372 | - else $data = substr_replace($data, '', strpos($data,$value[0]),strlen($value[0])); |
373 | + $id_replace = '<sup>'.$this->options['pre_identifier'].'<a href="'.$id_href.'" id="'.$id_id.'" class="footnote-link footnote-identifier-link" title="'.$id_title.'">'.$id_num.'</a>'.$this->options['post_identifier'].'</sup>'; |
374 | + $data = substr_replace($data, $id_replace, strpos($data,$value[0]),strlen($value[0])); |
375 | } |
376 | |
377 | // Display footnotes |
378 | - if ($display) { |
379 | - $start = ($start_number != 1) ? 'start="'.$start_number.'" ' : ''; |
380 | - $data = $data.$this->current_options['pre_footnotes']; |
381 | - |
382 | - $data = $data . '<ol '.$start.'class="footnotes">'; |
383 | - foreach ($footnotes as $key => $value) { |
384 | - $data = $data.'<li id="footnote_'.$key.'_'.$post->ID.'" class="footnote"'; |
385 | - if ($style == 'symbol') { |
386 | - $data = $data . ' style="list-style-type:none;"'; |
387 | - } elseif($style != $this->current_options['list_style_type']) { |
388 | - $data = $data . ' style="list-style-type:' . $style . ';"'; |
389 | - } |
390 | - $data = $data . '>'; |
391 | - if ($style == 'symbol') { |
392 | - $data = $data . '<span class="symbol">' . $this->convert_num($key+$start_number, $style, count($footnotes)) . '</span> '; |
393 | - } |
394 | - $data = $data.$value['text']; |
395 | - if (!is_feed()){ |
396 | - foreach($value['identifiers'] as $identifier){ |
397 | - $data = $data.$this->current_options['pre_backlink'].'<a href="'.( ($use_full_link) ? get_permalink($post->ID) : '' ).'#identifier_'.$identifier.'_'.$post->ID.'" class="footnote-link footnote-back-link">'.$this->current_options['backlink'].'</a>'.$this->current_options['post_backlink']; |
398 | - } |
399 | + $start = ($start_number != 1) ? 'start="'.$start_number.'" ' : ''; |
400 | + $data = $data.$this->options['pre_footnotes']; |
401 | + |
402 | + $data = $data . '<ol '.$start.'class="footnotes">'; |
403 | + foreach ($footnotes as $key => $value) { |
404 | + $data = $data.'<li id="footnote_'.$key.'_'.$post->ID.'" class="footnote"'; |
405 | + if ($style == 'symbol') { |
406 | + $data = $data . ' style="list-style-type:none;"'; |
407 | + } elseif($style != $this->options['list_style_type']) { |
408 | + $data = $data . ' style="list-style-type:' . $style . ';"'; |
409 | + } |
410 | + $data = $data . '>'; |
411 | + if ($style == 'symbol') { |
412 | + $data = $data . '<span class="symbol">' . $this->convert_num($key+$start_number, $style, count($footnotes)) . '</span> '; |
413 | + } |
414 | + $data = $data.$value['text']; |
415 | + if (!is_feed()){ |
416 | + foreach($value['identifiers'] as $identifier){ |
417 | + $data = $data.$this->options['pre_backlink'].'<a href="'.( ($use_full_link) ? get_permalink($post->ID) : '' ).'#identifier_'.$identifier.'_'.$post->ID.'" class="footnote-link footnote-back-link">'.$this->options['backlink'].'</a>'.$this->options['post_backlink']; |
418 | } |
419 | - $data = $data . '</li>'; |
420 | } |
421 | - $data = $data . '</ol>' . $this->current_options['post_footnotes']; |
422 | + $data = $data . '</li>'; |
423 | } |
424 | - return $data; |
425 | - } |
426 | - |
427 | - /** |
428 | - * Really insert the options page. |
429 | - */ |
430 | - function footnotes_options_page() { |
431 | - $this->current_options = get_option('swas_footnote_options'); |
432 | - foreach ($this->current_options as $key=>$setting) { |
433 | - $new_setting[$key] = htmlentities($setting); |
434 | - } |
435 | - $this->current_options = $new_setting; |
436 | - unset($new_setting); |
437 | - include (dirname(__FILE__) . '/options.php'); |
438 | - } |
439 | + $data = $data . '</ol>' . $this->options['post_footnotes']; |
440 | |
441 | - /** |
442 | - * Insert the options page into the admin area. |
443 | - */ |
444 | - function add_options_page() { |
445 | - // Add a new menu under Options: |
446 | - add_options_page('Footnotes', 'Footnotes', 8, __FILE__, array($this, 'footnotes_options_page')); |
447 | - } |
448 | - |
449 | - function upgrade_post($data){ |
450 | - $data = str_replace('<footnote>',WP_FOOTNOTES_OPEN,$data); |
451 | - $data = str_replace('</footnote>',WP_FOOTNOTES_CLOSE,$data); |
452 | return $data; |
453 | } |
454 | |
455 | - function insert_styles(){ |
456 | + function insert_styles() { |
457 | ?> |
458 | <style type="text/css"> |
459 | - <?php if ($this->current_options['list_style_type'] != 'symbol'): ?> |
460 | - ol.footnotes li {list-style-type:<?php echo $this->current_options['list_style_type']; ?>;} |
461 | + ol.footnotes { font-size: 0.8em; color: #666; } |
462 | + a.footnote-link, |
463 | + td.line-number-column { |
464 | + -moz-user-select: none; |
465 | + -webkit-user-select: none; |
466 | + user-select: none; |
467 | + } |
468 | + div.mp-wp-codeblock { |
469 | + background: none; |
470 | + font-family: monospace; |
471 | + color: #333; |
472 | + border: 1px solid #ddd; |
473 | + padding: 0; |
474 | + overflow: auto; |
475 | + } |
476 | + td.line-number-column { background: #f5f6f7; text-align: right; vertical-align: top; } |
477 | + td.line-number-column a { color: #555; padding: 0 5px; } |
478 | + td.content-column { |
479 | + padding-left: 10px; |
480 | + white-space: pre-wrap; |
481 | + word-break: break-word; |
482 | + tab-size: 4; |
483 | + -moz-tab-size: 4; |
484 | + max-width: 100%; /* adjust, if necessary, to fit your blog's viewport */ |
485 | + } |
486 | + span.line-filename { font-weight: bold; } |
487 | + span.line-meta { |
488 | + display: block; |
489 | + color: #999; |
490 | + word-wrap: break-word; |
491 | + word-break: break-all; |
492 | + } |
493 | + span.line-added { color: green; } |
494 | + span.line-removed { color:red; } |
495 | + |
496 | + <?php if ($this->options['list_style_type'] != 'symbol'): ?> |
497 | + ol.footnotes li { list-style-type: <?php echo $this->options['list_style_type']; ?>; } |
498 | <?php endif; ?> |
499 | - <?php echo $this->current_options['style_rules'];?> |
500 | + |
501 | + span.mp-wp-selection { background-color: #d3d3d3; } |
502 | </style> |
503 | <?php |
504 | } |
505 | |
506 | |
507 | - function convert_num ($num, $style, $total){ |
508 | + function convert_num ($num, $style, $total) { |
509 | switch ($style) { |
510 | case 'decimal-leading-zero' : |
511 | $width = max(2, strlen($total)); |
512 | |
513 | case 'symbol' : |
514 | $sym = ''; |
515 | for ($i = 0; $i<$num; $i++) { |
516 | - $sym .= $this->current_options['list_style_symbol']; |
517 | + $sym .= $this->options['list_style_symbol']; |
518 | } |
519 | return $sym; |
520 | } |
521 | |
522 | * @param string $case Upper or lower case. |
523 | * @return string The roman numeral |
524 | */ |
525 | - function roman($num, $case= 'upper'){ |
526 | + function roman($num, $case= 'upper') { |
527 | $num = (int) $num; |
528 | $conversion = array('M'=>1000, 'CM'=>900, 'D'=>500, 'CD'=>400, 'C'=>100, 'XC'=>90, 'L'=>50, 'XL'=>40, 'X'=>10, 'IX'=>9, 'V'=>5, 'IV'=>4, 'I'=>1); |
529 | $roman = ''; |
530 | |
531 | return ($case == 'lower') ? strtolower($roman) : $roman; |
532 | } |
533 | |
534 | - function alpha($num, $case='upper'){ |
535 | + function alpha($num, $case='upper') { |
536 | $j = 1; |
537 | for ($i = 'A'; $i <= 'ZZ'; $i++){ |
538 | if ($j == $num){ |
539 | diff -uNr a/mp-wp/xmlrpc.php b/mp-wp/xmlrpc.php |
540 | |
541 | |
542 | |
543 | $comment_post_ID = (int) $post_ID; |
544 | $comment_author = $title; |
545 | $this->escape($comment_author); |
546 | - $comment_author_url = $pagelinkedfrom; |
547 | + $select_tail = "?b=".substr(rawurlencode(strip_tags($excerpt)),0,12)."&e=".substr(rawurlencode(strip_tags($excerpt)),0,-4)."#select"; |
548 | + $comment_author_url = $pagelinkedfrom.$select_tail; |
549 | $comment_content = $context; |
550 | $this->escape($comment_content); |
551 | $comment_type = 'pingback'; |
552 |
- Previously just the footnotes plugin before embeddable codeblocks and server-side selection were added in this patch. [↩]
Your code displayer runs offscreen ; I tried to get you some shots to show it but look at this sad shit -- 5 failed, 41 expired out of 46, browsershots.org is dead by now too, joining a lengthy pile of needful infrastructure nobody's left to salvage.
So what can we do, sit here like savages, "your thing runs offscreen".
@Mircea Popescu Thanks for taking a look. Do you mean that there is horizontal scrolling inside the code "pane"? Or that the code pane itself is running off the browser's viewport? The former is intentional but is only set with CSS and so can be adjusted at the theme level by adding
td.content-column { word-break: break-all; }
.Oh is that what it was, a horiz scroller ? It doesn't show on this machine ; most people regard these very dimly fwis.
@Mircea Popescu Can you check again to see if it's fixed now? There should be no horizontal scrolling.
There was a fix I made earlier on my live version that breaks the long file hash in a vdiff but for the rest of the code only wraps at the word level. I forgot to carry this fix over when updating the patch.
A wider layout for displaying code will help readability as well (just so that less wrapping is required in the first place). I'm working on an update to my theme that will improve this.
Since I now have a definite need to get selection working for a hosted blog customer, and would prefer to do it the proper / standard / upstream way if such a way in fact exists, I tried to give this patch a closer look, but was put off enough by first impressions that I'm not sure I can bring myself to push through it as is.
You've got mixed tab and space indents (server_side_selection); inconsistent spacing style in new code; inconsistent spacing style even within a space-only change (roman); a bulk reindent mixed with content change making the latter harder to follow (default_options); poor factoring (that sprintf paste table in highlight_as_diff, not to mention assigning a variable just in order to return it).
Then there's the angle that since it's 406 lines of patching on what was a 346 line file it might as well be a total rewrite, from which view it's a missed opportunity to fix the overall structure. Such as dropping the "plugin" baggage wherein this (and only this) file is considered "content", on a level with themes and uploads, despite in actual usage being part of the core text formatting, on a level with the insertion of br and p tags; and wherein the "how to deploy a new blog" process that nobody's published except in bits and pieces needs to include "don't forget to activate the footnotes plugin!" in its lengthy list of ridiculous GUI-based post-install tasks. Or the "Encapsulate in a class [for no discernible reason and requiring more code to instantiate it into a throwaway global variable]".
Except that existing users already put selection code in their own themes per the original recipe so... won't the two implementations interfere unless the old one is manually reverted in full or in part?
[...] http://billymg.com/2020/05/updated-vpatch-add-embeddable-codeblocks-and-the-server-side-select-mecha... << billymg -- Updated vpatch: Add embeddable codeblocks and the server-side select mechanism [...]
[...] diana_coman: yeah, i would recommend just keeping the directory of your current custom theme as is. the included themes can be safely nuked for sure (server-side selection is handled in the footnotes.php as of this patch) [...]
[...] was trimmed3, a feature was added, patches were produced, and in 2020 TMSR was closed. I had also at this time just moved [...]