Make WordPress Core


Ignore:
Timestamp:
09/13/2017 06:07:48 AM (9 years ago)
Author:
westonruter
Message:

Editor: Add CodeMirror-powered code editor with syntax highlighting, linting, and auto-completion.

  • Code editor is integrated into the Theme/Plugin Editor, Additional CSS in Customizer, and Custom HTML widget. Code editor is not yet integrated into the post editor, and it may not be until accessibility concerns are addressed.
  • The CodeMirror component in the Custom HTML widget is integrated in a similar way to TinyMCE being integrated into the Text widget, adopting the same approach for integrating dynamic JavaScript-initialized fields.
  • Linting is performed for JS, CSS, HTML, and JSON via JSHint, CSSLint, HTMLHint, and JSONLint respectively. Linting is not yet supported for PHP.
  • When user lacks unfiltered_html the capability, the Custom HTML widget will report any Kses-invalid elements and attributes as errors via a custom Kses rule for HTMLHint.
  • When linting errors are detected, the user will be prevented from saving the code until the errors are fixed, reducing instances of broken websites.
  • The placeholder value is removed from Custom CSS in favor of a fleshed-out section description which now auto-expands when the CSS field is empty. See #39892.
  • The CodeMirror library is included as wp.CodeMirror to prevent conflicts with any existing CodeMirror global.
  • An wp.codeEditor.initialize() API in JS is provided to convert a textarea into CodeMirror, with a wp_enqueue_code_editor() function in PHP to manage enqueueing the assets and settings needed to edit a given type of code.
  • A user preference is added to manage whether or not "syntax highlighting" is enabled. The feature is opt-out, being enabled by default.
  • Allowed file extensions in the theme and plugin editors have been updated to include formats which CodeMirror has modes for: conf, css, diff, patch, html, htm, http, js, json, jsx, less, md, php, phtml, php3, php4, php5, php7, phps, scss, sass, sh, bash, sql, svg, xml, yml, yaml, txt.

Props westonruter, georgestephanis, obenland, melchoyce, pixolin, mizejewski, michelleweber, afercia, grahamarmfield, samikeijonen, rianrietveld, iseulde.
See #38707.
Fixes #12423, #39892.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/customize/custom-css-setting.php

    r39919 r41376  
    356356                $this->assertTrue( $result );
    357357
    358                 // Check for Unclosed Comment.
    359                 $unclosed_comment = $basic_css . ' /* This is a comment. ';
     358                // Check for markup.
     359                $unclosed_comment = $basic_css . '</style>';
    360360                $result = $this->setting->validate( $unclosed_comment );
    361                 $this->assertTrue( array_key_exists( 'unclosed_comment', $result->errors ) );
    362 
    363                 // Check for Unopened Comment.
    364                 $unclosed_comment = $basic_css . ' This is a comment.*/';
    365                 $result = $this->setting->validate( $unclosed_comment );
    366                 $this->assertTrue( array_key_exists( 'imbalanced_comments', $result->errors ) );
    367 
    368                 // Check for Unclosed Curly Brackets.
    369                 $unclosed_curly_bracket = $basic_css . '  a.link { text-decoration: none;';
    370                 $result = $this->setting->validate( $unclosed_curly_bracket );
    371                 $this->assertTrue( array_key_exists( 'imbalanced_curly_brackets', $result->errors ) );
    372 
    373                 // Check for Unopened Curly Brackets.
    374                 $unopened_curly_bracket = $basic_css . '  a.link text-decoration: none; }';
    375                 $result = $this->setting->validate( $unopened_curly_bracket );
    376                 $this->assertTrue( array_key_exists( 'imbalanced_curly_brackets', $result->errors ) );
    377 
    378                 // Check for Unclosed Braces.
    379                 $unclosed_brace = $basic_css . '  input[type="text" { color: #f00; } ';
    380                 $result = $this->setting->validate( $unclosed_brace );
    381                 $this->assertTrue( array_key_exists( 'imbalanced_braces', $result->errors ) );
    382 
    383                 // Check for Unopened Braces.
    384                 $unopened_brace = $basic_css . ' inputtype="text"] { color: #f00; } ';
    385                 $result = $this->setting->validate( $unopened_brace );
    386                 $this->assertTrue( array_key_exists( 'imbalanced_braces', $result->errors ) );
    387 
    388                 // Check for Imbalanced Double Quotes.
    389                 $imbalanced_double_quotes = $basic_css . ' div.background-image { background-image: url( "image.jpg ); } ';
    390                 $result = $this->setting->validate( $imbalanced_double_quotes );
    391                 $this->assertTrue( array_key_exists( 'unequal_double_quotes', $result->errors ) );
    392 
    393                 // Check for Unclosed Parentheses.
    394                 $unclosed_parentheses = $basic_css . ' div.background-image { background-image: url( "image.jpg" ; } ';
    395                 $result = $this->setting->validate( $unclosed_parentheses );
    396                 $this->assertTrue( array_key_exists( 'imbalanced_parentheses', $result->errors ) );
    397 
    398                 // Check for Unopened Parentheses.
    399                 $unopened_parentheses = $basic_css . ' div.background-image { background-image: url "image.jpg" ); } ';
    400                 $result = $this->setting->validate( $unopened_parentheses );
    401                 $this->assertTrue( array_key_exists( 'imbalanced_parentheses', $result->errors ) );
    402 
    403                 // A basic Content declaration with no other errors should not throw an error.
    404                 $content_declaration = $basic_css . ' a:before { content: ""; display: block; }';
    405                 $result = $this->setting->validate( $content_declaration );
    406                 $this->assertTrue( $result );
    407 
    408                 // An error, along with a Content declaration will throw two errors.
    409                 // In this case, we're using an extra opening brace.
    410                 $content_declaration = $basic_css . ' a:before { content: "["; display: block; }';
    411                 $result = $this->setting->validate( $content_declaration );
    412                 $this->assertTrue( array_key_exists( 'imbalanced_braces', $result->errors ) );
    413                 $this->assertTrue( array_key_exists( 'possible_false_positive', $result->errors ) );
    414 
    415                 $css = 'body { background: #f00; } h1.site-title { font-size: 36px; } a:hover { text-decoration: none; } input[type="text"] { padding: 1em; } /* This is a comment */';
    416                 $this->assertTrue( $this->setting->validate( $css ) );
    417 
    418                 $validity = $this->setting->validate( $css . ' /* This is another comment.' );
    419                 $this->assertInstanceOf( 'WP_Error', $validity );
    420                 $this->assertContains( 'unclosed code comment', join( ' ', $validity->get_error_messages() ) );
    421 
    422                 $css = '/* This is comment one. */  /* This is comment two. */';
    423                 $this->assertTrue( $this->setting->validate( $css ) );
    424 
    425                 $basic_css = 'body { background: #f00; } h1.site-title { font-size: 36px; } a:hover { text-decoration: none; } input[type="text"] { padding: 1em; }';
    426                 $this->assertTrue( $this->setting->validate( $basic_css ) );
    427 
    428                 $css = $basic_css . ' .link:before { content: "*"; display: block; }';
    429                 $this->assertTrue( $this->setting->validate( $css ) );
    430 
    431                 $css .= ' ( trailing';
    432                 $validity = $this->setting->validate( $css );
    433                 $this->assertWPError( $validity );
    434                 $this->assertNotEmpty( $result->get_error_message( 'possible_false_positive' ) );
     361                $this->assertTrue( array_key_exists( 'illegal_markup', $result->errors ) );
    435362        }
    436363}
Note: See TracChangeset for help on using the changeset viewer.