<!-- Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved. The copyrights embodied in the content of this file are licensed by Yahoo! Inc. under the BSD (revised) open source license @author Dan Vlad Dascalescu <dandv@yahoo-inc.com> --> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="../../js/codemirror.js" type="text/javascript"></script> <title>CodeMirror: PHP+HTML+JavaScript+CSS mixed-mode demonstration</title> <link rel="stylesheet" type="text/css" href="../../css/docs.css"/> </head> <body style="padding: 20px;"> <p>This is a complex demonstration of the <b>PHP+HTML+JavaScript+CSS mixed-mode syntax highlight</b> capabilities of <a href="../../index.html">CodeMirror</a>. <?php ... ?> tags use the PHP parser, <script> tags use the JavaScript parser, and <style> tags use the CSS parser. The rest of the content is parsed using the XML parser in HTML mode.</p> <p>Features of the PHP parser: <ul> <li>special "deprecated" style for PHP4 keywords like 'var' <li>support for PHP 5.3 keywords: 'namespace', 'use' <li>911 predefined constants, 1301 predefined functions, 105 predeclared classes from a typical PHP installation in a LAMP environment <li>new feature: syntax error flagging, thus enabling strict parsing of: <ol> <li>function definitions with explicitly or implicitly typed arguments and default values <li>modifiers (public, static etc.) applied to method and member definitions <li>foreach(array_expression as $key [=> $value]) loops </ol> <li>differentiation between single-quoted strings and double-quoted interpolating strings </ul> </p> <div style="border: 1px solid black; padding: 3px; background-color: #F8F8F8"> <textarea id="code" cols="120" rows="30"> The "root" parser is XML in HTML mode. Next, we can switch into PHP mode, for example. This is <?php echo 'text output by'; ?> PHP. </b> On the line above, we just had an XML syntax error due to the </b> tag not being opened. <?xml version='1.0' encoding='UTF-8' standalone='yes'?> HTML text will follow <html> <head> <title>Similarly, the 'script' tag will switch to the JavaScript parser:</title> <script type="text/javascript"> // Press enter inside the object and your new line will be suitably // indented. var keyBindings = { enter: "newline-and-indent", tab: "reindent-selection", ctrl_enter: "reparse-buffer", ctrl_z: "undo", ctrl_y: "redo", ctrl_backspace: "undo-for-safari-which-stupidly-enough-blocks-ctrl-z" }; // Press tab on the next line and the wrong indentation will be fixed. var regex = /foo|bar/i; function example(x) { // Local variables get a different colour than global ones. var y = 44.4; return x + y - z; } </script> <style> /* Some example CSS */ @import url("something.css"); body { margin: 0; padding: 3em 6em; font-family: tahoma, arial, sans-serif; color: #000; } #navigation a { font-weight: bold; text-decoration: none !important; } h1 { font-size: 2.5em; } h1:before, h2:before { content: "::"; } code { font-family: courier, monospace; font-size: 80%; color: #418A8A; } </style> </head> <body> The PHP code below contains some deliberate errors. Play with the editor by fixing them and observing how the highlight changes. <?php namespace A; namespace A::B::C; namespace A::::B; namespace A::B::C::; namespace A::B::C::D x; self::range($row['lft'], $row['rgt'])); // error: extra ')' $a = (b() + 4) 5 foo; // error: missing operators self::$var; $parent = self::range($max + 1, $max + 1); $row[attributes][$attribute_name] = $attribute_value; $row[attributes()][$attribute_name] = $attribute_value; $row[attributes(5)][$attribute_name] = $attribute_value; $row[$attributes()][$attribute_name] = $attribute_value; abstract class 5 extends foo implements echo { private function domainObjectBuilder() { return $this->use_domain_object_builder ? $this->domain()->objectBuilder() : null; } const $myconst = 'some string'; $array[myconst] = 4; // this is a single-line C++-style comment # this is a single-line shell-style comment private var $a = __FILE__; protected static $b = timezone_transitions_get('some parameter here'); global $g = isset("string"); static $s = hash_update_file; // warning: predefined function non-call function mike ($var) $foo; mike(A::func(param)); func($b $c); // error: function parameters must be comma-separated foo bar; // error: no operator $baz $quux; // error: no operator public abstract function loadPageXML(util_FilePath $filename, $merge=0+$foo, $x, $y=3) { $newrow[$key] = $val; $newresult[] = $row; $state = $row['c'] == 1; $attribute_values[$attribute_name] = null; $row['attributes'][$attribute_name] = $attribute_value; $result[$row['element']][$row['attribute']] = $row['value']; $sql = "multiline string line2 is special - it'll interpolate variables like $state and method calls {$this->cache->add($key, 5)} and maybe \"more\" line5"; $sql = 'multiline string single quoting means no \'interpolation\' like "$start" or method call {$this->cache->add($key, 5)} will happen line5'; $bitpattern = 1 << 2; $bitpattern <<= 3; $incorrect = <<< 5 EOSTRING // FIXME: CodeMirror update bug: add a letter before 5 and notice that syntax is not updated until EOF, even with continuousScanning: 500 error: the identifier must conform to the identifier rules EOSTRING; $sql = <<< EOSQL SELECT attribute, element, value FROM attribute_values WHERE dimension = ? EOSQL; $this->lr_cache->add($key, self::range($row['lft'], $row['rgt'])); $composite_string = <<<EOSTRING some lines here EOSTRING . 'something extra'; $page_lft = ($domain->name() == 'page') ? $start + 1 : $page_start + 1; echo "This is class foo"; echo "a = ".$this ->a[2+3*$array["foo"]].""; echo "b = {$this->b}"; // FIXME: highlight interpolation in strings } final function makecoffee error($types = array("cappuccino"), $coffeeMaker = NULL) { $out_of_way_amount = $max - $child->left() + 1; $absolute_pos = $child->left() - $move->width(); $varfunc(1, 'x'); $varfunc(1, 'x') + foo() - 5; $funcarray[$i]('param1', $param2); $lr[$domain_name] = $this->get_left_and_right($domain, $dimension_name, $element_name); $domain_list = is_null($domain) ? r3_Domain::names() : array($domain->name()); foreach (r3_Domain::names() as $domain_name) { $placeholders = 'distance LIKE ' . implode(array_fill(1, $num_distances, '?'), ' OR distance LIKE '); } return $this->target*$this->trans+myfunc(__METHOD__); /* echo 'This is a test'; /* This comment will cause a problem */ */ } switch( $type ) { case "r3core_AddTemplateToTargetEvent": $this->notifyAddTemplateToTarget( $genevent ); break; case "r3core_GenerateTargetEvent" $this: for($i=0; $i<=this->method(); $i++) { echo 'Syntax "highlighting"'; } try { foreach($array xor $loader->parse_fn($filename) as $key => value) { namespace r3; } } catch( Exception $e ) { /** restore the backup */ $this->loadAll($tmp, $event, true); // `php -l` doesn't complain at all at this (it assumes string constants): this + makes * no - sense; } break; default moo: throw new r3_util_Exception( get_class( $genevent ) . " does not map" ); } }; ?> <r3:cphp> php("works", $here, 2); </r3:cphp> <r4:cphp> class foo { // a comment var $a; var $b; }; </r4:cphp> <h1>This is an <?php # echo 'simple';?> example.</h1> <p>The header above will say 'This is an example'.</p> <h1>This is an <?php // echo 'simple';?> example.</h1> <?php echo; ?> <body> <?php echo "<html> <head> <script> var foo = 'bar'; </script> <style> span.test {font-family: arial, 'lucida console', sans-serif} </style> </head> <body> <!-- comment --> </body> </html>"; ?> </body> </html> </textarea> </div> <script type="text/javascript"> var editor = CodeMirror.fromTextArea('code', { height: "350px", parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js", "../contrib/php/js/tokenizephp.js", "../contrib/php/js/parsephp.js", "../contrib/php/js/parsephphtmlmixed.js"], stylesheet: ["../../css/xmlcolors.css", "../../css/jscolors.css", "../../css/csscolors.css", "css/phpcolors.css"], path: "../../js/", continuousScanning: 500 }); </script> </body> </html>