Initial commit (v 1.0.0)

* add the highlighting of templates and parser functions

Change-Id: I6f5a0aa701b1b4e58510bf17a25eb1a0e1b5f14a
This commit is contained in:
Pavel Astakhov 2014-08-20 23:03:46 +06:00
parent bb488300eb
commit c8bd7736f9
9 changed files with 8333 additions and 0 deletions

11
CodeMirror.hooks.php Normal file
View file

@ -0,0 +1,11 @@
<?php
class CodeMirrorHooks {
public static function onEditPageShowEditFormInitial( EditPage $editPage, OutputPage $output ) {
$output->addModules( 'ext.CodeMirror' );
return true;
}
}

35
CodeMirror.i18n.php Normal file
View file

@ -0,0 +1,35 @@
<?php
/**
* This is a backwards-compatibility shim, generated by:
* https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2FgenerateJsonI18n.php
*
* Beginning with MediaWiki 1.23, translation strings are stored in json files,
* and the EXTENSION.i18n.php file only exists to provide compatibility with
* older releases of MediaWiki. For more information about this migration, see:
* https://www.mediawiki.org/wiki/Requests_for_comment/Localisation_format
*
* This shim maintains compatibility back to MediaWiki 1.17.
*/
$messages = array();
if ( !function_exists( 'wfJsonI18nShimfe179a89caef8049' ) ) {
function wfJsonI18nShimfe179a89caef8049( $cache, $code, &$cachedData ) {
$codeSequence = array_merge( array( $code ), $cachedData['fallbackSequence'] );
foreach ( $codeSequence as $csCode ) {
$fileName = dirname( __FILE__ ) . "/i18n/$csCode.json";
if ( is_readable( $fileName ) ) {
$data = FormatJson::decode( file_get_contents( $fileName ), true );
foreach ( array_keys( $data ) as $key ) {
if ( $key === '' || $key[0] === '@' ) {
unset( $data[$key] );
}
}
$cachedData['messages'] = array_merge( $data, $cachedData['messages'] );
}
$cachedData['deps'][] = new FileDependency( $fileName );
}
return true;
}
$GLOBALS['wgHooks']['LocalisationCacheRecache'][] = 'wfJsonI18nShimfe179a89caef8049';
}

57
CodeMirror.php Normal file
View file

@ -0,0 +1,57 @@
<?php
/**
* Main entry point for the CodeMirror extension.
*
* @link https://www.mediawiki.org/wiki/Extension:CodeMirror Documentation
* @file CodeMirror.php
* @defgroup CodeMirror
* @ingroup Extensions
* @author Pavel Astakhov <pastakhov@yandex.ru>
* @licence GNU General Public Licence 2.0 or later
*/
// Check to see if we are being called as an extension or directly
if ( !defined( 'MEDIAWIKI' ) ) {
die( 'This file is an extension to MediaWiki and thus not a valid entry point.' );
}
const CODEMIRROR_VERSION = '1.0.0';
// Register this extension on Special:Version
$wgExtensionCredits['parserhook'][] = array(
'path' => __FILE__,
'name' => 'CodeMirror',
'version' => CODEMIRROR_VERSION,
'url' => 'https://www.mediawiki.org/wiki/Extension:CodeMirror',
'author' => '[https://www.mediawiki.org/wiki/User:Pastakhov Pavel Astakhov]',
'descriptionmsg' => 'codemirror-desc'
);
// Allow translations for this extension
$wgMessagesDirs['CodeMirror'] = __DIR__ . '/i18n';
$wgExtensionMessagesFiles['CodeMirror'] = __DIR__ . '/CodeMirror.i18n.php';
$wgAutoloadClasses['CodeMirrorHooks'] = __DIR__ . '/CodeMirror.hooks.php';
$wgHooks['EditPage::showEditForm:initial'][] = 'CodeMirrorHooks::onEditPageShowEditFormInitial';
$tpl = array(
'localBasePath' => __DIR__ . '/resources',
'remoteExtPath' => 'CodeMirror/resources',
);
$wgResourceModules['ext.CodeMirror'] = array(
'scripts' => 'ext.CodeMirror.js',
'dependencies' => 'ext.CodeMirror.lib',
) + $tpl;
$wgResourceModules['ext.CodeMirror.lib'] = array(
'group' => 'ext.CodeMirror.lib',
'scripts' => array(
'lib/codemirror/lib/codemirror.js',
//'lib/codemirror/edit/matchbrackets.js',
//'lib/codemirror/edit/closebrackets.js',
'mode/mediawiki/mediawiki.js',
),
'styles' => 'lib/codemirror/lib/codemirror.css',
) + $tpl;

8
i18n/en.json Normal file
View file

@ -0,0 +1,8 @@
{
"@metadata": {
"authors": [
"pastakhov"
]
},
"codemirror-desc": "Syntax-highlighted editing for wiki pages using [http://codemirror.net/ CodeMirror]"
}

8
i18n/qqq.json Normal file
View file

@ -0,0 +1,8 @@
{
"@metadata": {
"authors": [
"pastakhov"
]
},
"codemirror-desc": "{{desc|name=PhpTags CodeEditor|url=https://www.mediawiki.org/wiki/Extension:CodeMirror}}"
}

View file

@ -0,0 +1,12 @@
$( document ).ready( function () {
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("wpTextbox1"), {
mode: "text/mediawiki",
styleActiveLine: true,
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
indentWithTabs: true
//matchBrackets: true,
//autoCloseBrackets: true
});
} );

View file

@ -0,0 +1,301 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
}
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
line-height: 1;
position: relative;
overflow: hidden;
background: white;
color: black;
}
.CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
padding-bottom: 30px;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-lines {
cursor: text;
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 1;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}

7801
resources/lib/codemirror/lib/codemirror.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,100 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("mediawiki", function(config, parserConfig) {
function inTemplatePageName(stream, state) { // {{
if (stream.eat("#")) {
state.tokenize = inParserFunctionName;
return "strong";
}
stream.eatWhile(/[^\|}]/);
state.tokenize = inTemplateArgumentSeparator;
return "link";
}
function inTemplateArgumentSeparator(stream, state) { // {{ Page name |
if (stream.eat("|")) {
state.tokenize = inTemplateArgument;
return "tag strong";
}
if (stream.eat("}")) {
if (stream.eat("}")) {
state.tokenize = inText;
return "tag bracket";
}
}
stream.next();
return null;
}
function inTemplateArgument(stream, state) { // {{ Page name |
stream.eatWhile(/[^\|}]/);
state.tokenize = inTemplateArgumentSeparator;
return "string";
}
function inParserFunctionName(stream, state) { // {{#
stream.eatWhile(/[^:}]/);
state.tokenize = inParserFunctionArgumentSeparator;
return "keyword";
}
function inParserFunctionArgumentSeparator(stream, state) { // {{ Page name |
if (stream.eat(/[|:]/)) {
state.tokenize = inParserFunctionArgument;
return "tag strong";
}
if (stream.eat("}")) {
if (stream.eat("}")) {
state.tokenize = inText;
return "tag bracket";
}
}
stream.next();
return "string";
}
function inParserFunctionArgument(stream, state) { // {{#
stream.eatWhile(/[^|}]/);
state.tokenize = inParserFunctionArgumentSeparator;
return "string";
}
function inText(stream, state) {
var ch = stream.next();
switch (ch) {
case "{":
if (stream.eat("{")) { // Templates
state.tokenize = inTemplatePageName;
stream.eatSpace();
return "tag bracket";
}
break;
}
return null;
}
return {
startState: function() {
return {tokenize: inText, style: null};
},
token: function(stream, state) {
return state.tokenize(stream, state);
}
};
});
CodeMirror.defineMIME("text/mediawiki", "mediawiki");
});