зеркало из https://github.com/mozilla/ubiquity.git
Added documentation to utils.js and code documentation prototype JS app taken from http://hg.toolness.com/doc-thingy/.
This commit is contained in:
Родитель
6dfc04b04d
Коммит
afbbf7aa08
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" type="text/css" media="all" href="docs.css" />
|
||||
<title>Ubiquity Documentation</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
</body>
|
||||
<script src="resource://ubiquity-scripts/jquery.js"></script>
|
||||
<script src="resource://ubiquity-scripts/wikicreole.js"></script>
|
||||
<script src="docs.js"></script>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" type="text/css" media="all" href="docs.css" />
|
||||
<title>Ubiquity Documentation</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
</body>
|
||||
<script src="../../../scripts/jquery.js"></script>
|
||||
<script src="../../../scripts/wikicreole.js"></script>
|
||||
<script src="docs.js"></script>
|
||||
</html>
|
|
@ -0,0 +1,45 @@
|
|||
body {
|
||||
font-family: palatino, georgia, verdana, arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#content {
|
||||
width: 800px;
|
||||
text-align: left;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.documentation {
|
||||
width: 380px;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.documentation h1 {
|
||||
font-weight: normal;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.documentation h2 {
|
||||
font-weight: normal;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-family: monaco, andale mono, lucidatypewriter, courier,
|
||||
courier new, monospace;
|
||||
float: left;
|
||||
white-space: pre;
|
||||
font-size: 6pt;
|
||||
background-color: #f0f0f0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
width: 380px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
clear: both;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>Ubiquity Documentation</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
if (window.location.protocol == "chrome:")
|
||||
window.location = "docs-chrome.html";
|
||||
else
|
||||
window.location = "docs-content.html";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,94 @@
|
|||
var App = {};
|
||||
|
||||
App.trim = function trim(str) {
|
||||
return str.replace(/^\s+|\s+$/g,"");
|
||||
};
|
||||
|
||||
App.getLocalUrlData = function getLocalUrlData(url) {
|
||||
var jsm = {};
|
||||
Components.utils.import("resource://ubiquity-modules/codesource.js",
|
||||
jsm);
|
||||
var lcs = new jsm.LocalUriCodeSource(url);
|
||||
return lcs.getCode();
|
||||
};
|
||||
|
||||
App.processCode = function processCode(code) {
|
||||
var lines = code.split('\n');
|
||||
var blocks = [];
|
||||
var blockText = "";
|
||||
var codeText = "";
|
||||
var firstCommentLine;
|
||||
var lastCommentLine;
|
||||
|
||||
function maybeAppendBlock() {
|
||||
if (blockText)
|
||||
blocks.push({text: blockText,
|
||||
lineno: firstCommentLine,
|
||||
numLines: lastCommentLine - firstCommentLine + 1,
|
||||
code: codeText});
|
||||
}
|
||||
|
||||
jQuery.each(
|
||||
lines,
|
||||
function(lineNum) {
|
||||
var line = this;
|
||||
var isCode = true;
|
||||
var isComment = (App.trim(line).indexOf("//") == 0);
|
||||
if (isComment) {
|
||||
var startIndex = line.indexOf("//");
|
||||
var text = line.slice(startIndex + 3);
|
||||
if (lineNum == lastCommentLine + 1) {
|
||||
blockText += text + "\n";
|
||||
lastCommentLine += 1;
|
||||
isCode = false;
|
||||
} else if (text[0] == "=" || text[0] == "*") {
|
||||
maybeAppendBlock();
|
||||
firstCommentLine = lineNum;
|
||||
lastCommentLine = lineNum;
|
||||
blockText = text + "\n";
|
||||
codeText = "";
|
||||
isCode = false;
|
||||
}
|
||||
}
|
||||
if (isCode)
|
||||
codeText += line + "\n";
|
||||
});
|
||||
maybeAppendBlock();
|
||||
|
||||
var creole = new Parse.Simple.Creole(
|
||||
{interwiki: {
|
||||
WikiCreole: 'http://www.wikicreole.org/wiki/',
|
||||
Wikipedia: 'http://en.wikipedia.org/wiki/'
|
||||
},
|
||||
linkFormat: ''
|
||||
});
|
||||
|
||||
jQuery.each(
|
||||
blocks,
|
||||
function(i) {
|
||||
var docs = $('<div class="documentation">');
|
||||
creole.parse(docs.get(0), this.text);
|
||||
$("#content").append(docs);
|
||||
var code = $('<div class="code">');
|
||||
code.text(this.code);
|
||||
$("#content").append(code);
|
||||
|
||||
var docsSurplus = docs.height() - code.height() + 1;
|
||||
if (docsSurplus > 0)
|
||||
code.css({paddingBottom: docsSurplus + "px"});
|
||||
|
||||
$("#content").append('<div class="divider">');
|
||||
});
|
||||
};
|
||||
|
||||
$(window).ready(
|
||||
function() {
|
||||
if (window.location.protocol == "chrome:") {
|
||||
var code = App.getLocalUrlData("resource://ubiquity-modules/utils.js");
|
||||
App.processCode(code);
|
||||
} else
|
||||
jQuery.get("../../../modules/utils.js",
|
||||
{},
|
||||
App.processCode,
|
||||
"text");
|
||||
});
|
|
@ -36,6 +36,12 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// = Utils =
|
||||
//
|
||||
// This is a small library of all-purpose, general utility functions
|
||||
// for use by chrome code. Everything clients need is contained within
|
||||
// the {{{Utils}}} namespace.
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Utils"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
|
@ -43,8 +49,24 @@ const Ci = Components.interfaces;
|
|||
|
||||
var Utils = {};
|
||||
|
||||
// Keep a reference to the global object, as certain utility functions
|
||||
// need it.
|
||||
Utils.__globalObject = this;
|
||||
|
||||
// ** {{{ Utils.reportWarning() }}} **
|
||||
//
|
||||
// This function can be used to report a warning to the JS Error Console,
|
||||
// which can be displayed in Firefox by choosing "Error Console" from
|
||||
// the "Tools" menu.
|
||||
//
|
||||
// {{{aMessage}}} is a plaintext string corresponding to the warning
|
||||
// to provide.
|
||||
//
|
||||
// {{{stackFrame}}} is an optional {{{nsIStackFrame}}} instance that
|
||||
// corresponds to the stack frame which is reporting the error; a link
|
||||
// to the line of source that it references will be shown in the JS
|
||||
// Error Console. It defaults to the caller's stack frame.
|
||||
|
||||
Utils.reportWarning = function reportWarning(aMessage, stackFrame) {
|
||||
if (!stackFrame)
|
||||
stackFrame = Components.stack.caller;
|
||||
|
@ -64,6 +86,13 @@ Utils.reportWarning = function reportWarning(aMessage, stackFrame) {
|
|||
consoleService.logMessage(scriptError);
|
||||
};
|
||||
|
||||
// ** {{{ Utils.reportInfo() }}} **
|
||||
//
|
||||
// Reports a purely informational message to the JS Error Console.
|
||||
// Source code links aren't provided for informational messages, so
|
||||
// unlike {{{Utils.reportWarning()}}}, a stack frame can't be passed
|
||||
// in to this function.
|
||||
|
||||
Utils.reportInfo = function reportInfo(aMessage) {
|
||||
var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
||||
.getService(Components.interfaces.nsIConsoleService);
|
||||
|
@ -71,18 +100,78 @@ Utils.reportInfo = function reportInfo(aMessage) {
|
|||
consoleService.logStringMessage(aCategory + aMessage);
|
||||
};
|
||||
|
||||
// ** {{{ Utils.encodeJson() }}} **
|
||||
//
|
||||
// This function serializes the given object using JavaScript Object
|
||||
// Notation (JSON).
|
||||
|
||||
Utils.encodeJson = function encodeJson(object) {
|
||||
var json = Cc["@mozilla.org/dom/json;1"]
|
||||
.createInstance(Ci.nsIJSON);
|
||||
return json.encode(object);
|
||||
};
|
||||
|
||||
// ** {{{ Utils.decodeJson() }}} **
|
||||
//
|
||||
// This function unserializes the given string in JavaScript Object
|
||||
// Notation (JSON) format and returns the result.
|
||||
|
||||
Utils.decodeJson = function decodeJson(string) {
|
||||
var json = Cc["@mozilla.org/dom/json;1"]
|
||||
.createInstance(Ci.nsIJSON);
|
||||
return json.decode(string);
|
||||
};
|
||||
|
||||
// ** {{{ Utils.setTimeout() }}} **
|
||||
//
|
||||
// This function works just like the {{{window.setTimeout()}}} method
|
||||
// in content space, but it can only accept a function (not a string)
|
||||
// as the callback argument.
|
||||
//
|
||||
// {{{callback}}} is the callback function to call when the given
|
||||
// delay period expires. It will be called only once (not at a regular
|
||||
// interval).
|
||||
//
|
||||
// {{{delay}}} is the delay, in milliseconds, after which the callback
|
||||
// will be called once.
|
||||
//
|
||||
// This function returns a timer ID, which can later be given to
|
||||
// {{{Utils.clearTimeout()}}} if the client decides that it wants to
|
||||
// cancel the callback from being triggered.
|
||||
|
||||
// TODO: Allow strings for the first argument like DOM setTimeout() does.
|
||||
|
||||
Utils.setTimeout = function setTimeout(callback, delay) {
|
||||
var classObj = Cc["@mozilla.org/timer;1"];
|
||||
var timer = classObj.createInstance(Ci.nsITimer);
|
||||
var timerID = Utils.__timerData.nextID;
|
||||
// emulate window.setTimeout() by incrementing next ID by random amount
|
||||
Utils.__timerData.nextID += Math.floor(Math.random() * 100) + 1;
|
||||
Utils.__timerData.timers[timerID] = timer;
|
||||
|
||||
timer.initWithCallback(new Utils.__TimerCallback(callback),
|
||||
delay,
|
||||
classObj.TYPE_ONE_SHOT);
|
||||
return timerID;
|
||||
};
|
||||
|
||||
// ** {{{ Utils.clearTimeout() }}} **
|
||||
//
|
||||
// This function behaves like the {{{window.clearTimeout()}}} function
|
||||
// in content space, and cancels the callback with the given timer ID
|
||||
// from ever being called.
|
||||
|
||||
Utils.clearTimeout = function clearTimeout(timerID) {
|
||||
if(!(timerID in Utils.__timerData.timers))
|
||||
return;
|
||||
|
||||
var timer = Utils.__timerData.timers[timerID];
|
||||
timer.cancel();
|
||||
delete Utils.__timerData.timers[timerID];
|
||||
};
|
||||
|
||||
// Support infrastructure for the timeout-related functions.
|
||||
|
||||
Utils.__TimerCallback = function __TimerCallback(callback) {
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
|
@ -107,42 +196,20 @@ Utils.__timerData = {
|
|||
timers: {}
|
||||
};
|
||||
|
||||
//Utils.setTimeout works just like DOM setTimeout() method
|
||||
//but it can only accept a function (not a string) as the callback argument
|
||||
//TODO: Allow strings for the first argument like DOM setTimeout() does.
|
||||
|
||||
Utils.setTimeout = function setTimeout(callback, delay) {
|
||||
var classObj = Cc["@mozilla.org/timer;1"];
|
||||
var timer = classObj.createInstance(Ci.nsITimer);
|
||||
var timerID = Utils.__timerData.nextID;
|
||||
// emulate window.setTimeout() by incrementing next ID by random amount
|
||||
Utils.__timerData.nextID += Math.floor(Math.random() * 100) + 1;
|
||||
Utils.__timerData.timers[timerID] = timer;
|
||||
|
||||
timer.initWithCallback(new Utils.__TimerCallback(callback),
|
||||
delay,
|
||||
classObj.TYPE_ONE_SHOT);
|
||||
return timerID;
|
||||
};
|
||||
|
||||
Utils.clearTimeout = function clearTimeout(timerID) {
|
||||
if(!(timerID in Utils.__timerData.timers))
|
||||
return;
|
||||
|
||||
var timer = Utils.__timerData.timers[timerID];
|
||||
timer.cancel();
|
||||
delete Utils.__timerData.timers[timerID];
|
||||
};
|
||||
|
||||
// Given a string representing an absolute URL or a nsIURI object,
|
||||
// returns an equivalent nsIURI object. Alternatively, an object with
|
||||
// keyword arguments as keys can also be passed in; the following
|
||||
// arguments are supported:
|
||||
// ** {{{ Utils.url() }}} **
|
||||
//
|
||||
// uri: a string/nsIURI representing an absolute or relative URL.
|
||||
// Given a string representing an absolute URL or a {{{nsIURI}}}
|
||||
// object, returns an equivalent {{{nsIURI}}} object. Alternatively,
|
||||
// an object with keyword arguments as keys can also be passed in; the
|
||||
// following arguments are supported:
|
||||
//
|
||||
// base: a string/nsIURI representing an absolute URL, which is used
|
||||
// as the base URL for the 'uri' keyword argument.
|
||||
// * {{{uri}}} is a string or {{{nsIURI}}} representing an absolute or
|
||||
// relative URL.
|
||||
//
|
||||
// * {{{base}}} is a string or {{{nsIURI}}} representing an absolute
|
||||
// URL, which is used as the base URL for the {{{uri}}} keyword
|
||||
// argument.
|
||||
|
||||
Utils.url = function url(spec) {
|
||||
var base = null;
|
||||
if (typeof(spec) == "object") {
|
||||
|
@ -160,10 +227,21 @@ Utils.url = function url(spec) {
|
|||
return ios.newURI(spec, null, base);
|
||||
};
|
||||
|
||||
Utils.openUrlInBrowser = function openUrlInBrowser(urlString, postData) {
|
||||
// allow postData to be null/undefined, string representation, json representation, or nsIInputStream
|
||||
// nsIInputStream is what is needed
|
||||
// ** {{{ Utils.openUrlInBrowser() }}} **
|
||||
//
|
||||
// This function opens the given URL in the user's browser, using
|
||||
// their current preferences for how new URLs should be opened (e.g.,
|
||||
// in a new window vs. a new tab, etc).
|
||||
//
|
||||
// {{{urlString}}} is a string corresponding to the URL to be
|
||||
// opened.
|
||||
//
|
||||
// {{{postData}}} is an optional argument that allows HTTP POST data
|
||||
// to be sent to the newly-opened page. It may be a string, an Object
|
||||
// with keys and values corresponding to their POST analogues, or an
|
||||
// {{{nsIInputStream}}}.
|
||||
|
||||
Utils.openUrlInBrowser = function openUrlInBrowser(urlString, postData) {
|
||||
var postInputStream = null;
|
||||
if(postData) {
|
||||
if(postData instanceof Ci.nsIInputStream) {
|
||||
|
@ -178,7 +256,8 @@ Utils.openUrlInBrowser = function openUrlInBrowser(urlString, postData) {
|
|||
|
||||
postInputStream = Cc["@mozilla.org/network/mime-input-stream;1"]
|
||||
.createInstance(Ci.nsIMIMEInputStream);
|
||||
postInputStream.addHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
postInputStream.addHeader("Content-Type",
|
||||
"application/x-www-form-urlencoded");
|
||||
postInputStream.addContentLength = true;
|
||||
postInputStream.setData(stringStream);
|
||||
}
|
||||
|
@ -197,7 +276,8 @@ Utils.openUrlInBrowser = function openUrlInBrowser(urlString, postData) {
|
|||
//3 (default in Firefox 2 and above): In a new tab
|
||||
//1 (or anything else): In the current tab or window
|
||||
|
||||
if(browser.mCurrentBrowser.currentURI.spec == "about:blank" && !browser.webProgress.isLoadingDocument )
|
||||
if(browser.mCurrentBrowser.currentURI.spec == "about:blank" &&
|
||||
!browser.webProgress.isLoadingDocument )
|
||||
browserWindow.loadURI(urlString, null, postInputStream, false);
|
||||
else if(openPref == 3)
|
||||
browser.loadOneTab(urlString, null, null, postInputStream, false, false);
|
||||
|
@ -208,8 +288,12 @@ Utils.openUrlInBrowser = function openUrlInBrowser(urlString, postData) {
|
|||
browserWindow.loadURI(urlString, null, postInputStream, false);
|
||||
};
|
||||
|
||||
// Focuses a tab with the given URL if one exists in the current
|
||||
// window, otherwise opens a new tab with the URL and focuses it.
|
||||
// ** {{{ Utils.focusUrlInBrowser() }}} **
|
||||
//
|
||||
// This function focuses a tab with the given URL if one exists in the
|
||||
// current window; otherwise, it delegates to
|
||||
// {{{Utils.openUrlInBrowser()}}}.
|
||||
|
||||
Utils.focusUrlInBrowser = function focusUrlInBrowser(urlString) {
|
||||
let Application = Components.classes["@mozilla.org/fuel/application;1"]
|
||||
.getService(Components.interfaces.fuelIApplication);
|
||||
|
@ -223,6 +307,11 @@ Utils.focusUrlInBrowser = function focusUrlInBrowser(urlString) {
|
|||
Utils.openUrlInBrowser(urlString);
|
||||
};
|
||||
|
||||
// ** {{{ Utils.getCookie() }}} **
|
||||
//
|
||||
// This function returns the cookie for the given domain and with the
|
||||
// given name. If no matching cookie exists, {{{null}}} is returned.
|
||||
|
||||
Utils.getCookie = function getCookie(domain, name) {
|
||||
var cookieManager = Cc["@mozilla.org/cookiemanager;1"].
|
||||
getService(Ci.nsICookieManager);
|
||||
|
@ -238,6 +327,8 @@ Utils.getCookie = function getCookie(domain, name) {
|
|||
return null;
|
||||
};
|
||||
|
||||
// = The rest of this documentation still needs to be written. =
|
||||
|
||||
Utils.paramsToString = function paramsToString(params) {
|
||||
var stringPairs = [];
|
||||
function valueTypeIsOk(val) {
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright (c) 2008 Ivan Fomichev
|
||||
*
|
||||
* Portions Copyright (c) 2007 Chris Purcell
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
if (!Parse) { var Parse = {}; }
|
||||
if (!Parse.Simple) { Parse.Simple = {}; }
|
||||
|
||||
Parse.Simple.Base = function(root, options) {
|
||||
if (!arguments.length) { return; }
|
||||
|
||||
this.root = new this.ruleConstructor(root);
|
||||
this.options = options;
|
||||
};
|
||||
|
||||
Parse.Simple.Base.prototype = {
|
||||
ruleConstructor: null,
|
||||
root: null,
|
||||
options: null,
|
||||
|
||||
parse: function(node, data, options) {
|
||||
if (options) {
|
||||
for (i in this.options) {
|
||||
if (typeof options[i] == 'undefined') { options[i] = this.options[i]; }
|
||||
}
|
||||
}
|
||||
else {
|
||||
options = this.options;
|
||||
}
|
||||
this.root.apply(node, data, options);
|
||||
}
|
||||
};
|
||||
|
||||
Parse.Simple.Base.prototype.constructor = Parse.Simple.Base;
|
||||
|
||||
Parse.Simple.Base.Rule = function(params) {
|
||||
if (!arguments.length) { return; }
|
||||
|
||||
for (var p in params) { this[p] = params[p]; }
|
||||
if (!this.children) { this.children = []; }
|
||||
};
|
||||
|
||||
Parse.Simple.Base.prototype.ruleConstructor = Parse.Simple.Base.Rule;
|
||||
|
||||
Parse.Simple.Base.Rule.prototype = {
|
||||
regex: null,
|
||||
capture: null,
|
||||
replaceRegex: null,
|
||||
replaceString: null,
|
||||
tag: null,
|
||||
attrs: null,
|
||||
children: null,
|
||||
|
||||
match: function(data, options) {
|
||||
return data.match(this.regex);
|
||||
},
|
||||
|
||||
build: function(node, r, options) {
|
||||
var data;
|
||||
if (this.capture !== null) {
|
||||
data = r[this.capture];
|
||||
}
|
||||
|
||||
var target;
|
||||
if (this.tag) {
|
||||
target = document.createElement(this.tag);
|
||||
node.appendChild(target);
|
||||
}
|
||||
else { target = node; }
|
||||
|
||||
if (data) {
|
||||
if (this.replaceRegex) {
|
||||
data = data.replace(this.replaceRegex, this.replaceString);
|
||||
}
|
||||
this.apply(target, data, options);
|
||||
}
|
||||
|
||||
if (this.attrs) {
|
||||
for (var i in this.attrs) {
|
||||
target.setAttribute(i, this.attrs[i]);
|
||||
if (i == 'class') { target.className = this.attrs[i]; } // for IE
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
apply: function(node, data, options) {
|
||||
var tail = '' + data;
|
||||
var matches = [];
|
||||
|
||||
if (!this.fallback.apply) {
|
||||
this.fallback = new this.constructor(this.fallback);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var best = false;
|
||||
var rule = false;
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
if (typeof matches[i] == 'undefined') {
|
||||
if (!this.children[i].match) {
|
||||
this.children[i] = new this.constructor(this.children[i]);
|
||||
}
|
||||
matches[i] = this.children[i].match(tail, options);
|
||||
}
|
||||
if (matches[i] && (!best || best.index > matches[i].index)) {
|
||||
best = matches[i];
|
||||
rule = this.children[i];
|
||||
if (best.index == 0) { break; }
|
||||
}
|
||||
}
|
||||
|
||||
var pos = best ? best.index : tail.length;
|
||||
if (pos > 0) {
|
||||
this.fallback.apply(node, tail.substring(0, pos), options);
|
||||
}
|
||||
|
||||
if (!best) { break; }
|
||||
|
||||
if (!rule.build) { rule = new this.constructor(rule); }
|
||||
rule.build(node, best, options);
|
||||
|
||||
var chopped = best.index + best[0].length;
|
||||
tail = tail.substring(chopped);
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
if (matches[i]) {
|
||||
if (matches[i].index >= chopped) {
|
||||
matches[i].index -= chopped;
|
||||
}
|
||||
else {
|
||||
matches[i] = void 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
fallback: {
|
||||
apply: function(node, data, options) {
|
||||
node.appendChild(document.createTextNode(data));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Parse.Simple.Base.Rule.prototype.constructor = Parse.Simple.Base.Rule;
|
||||
|
||||
Parse.Simple.Creole = function(options) {
|
||||
var rx = {};
|
||||
rx.link = '[^\\]|~\\n]*(?:(?:\\](?!\\])|~.)[^\\]|~\\n]*)*';
|
||||
rx.linkText = '[^\\]~\\n]*(?:(?:\\](?!\\])|~.)[^\\]~\\n]*)*';
|
||||
rx.uriPrefix = '\\b(?:(?:https?|ftp)://|mailto:)';
|
||||
rx.uri = rx.uriPrefix + rx.link;
|
||||
rx.rawUri = rx.uriPrefix + '\\S*[^\\s!"\',.:;?]';
|
||||
rx.interwikiPrefix = '[\\w.]+:';
|
||||
rx.interwikiLink = rx.interwikiPrefix + rx.link;
|
||||
|
||||
var formatLink = function(link, format) {
|
||||
format = format instanceof Array ? format : [ format ];
|
||||
if (typeof format[1] == 'undefined') { format[1] = ''; }
|
||||
return format[0] + link + format[1];
|
||||
};
|
||||
|
||||
var g = {
|
||||
hr: { tag: 'hr', regex: /(^|\n)\s*----\s*(\n|$)/ },
|
||||
|
||||
br: { tag: 'br', regex: /\\\\/ },
|
||||
|
||||
preBlock: { tag: 'pre', capture: 2,
|
||||
regex: /(^|\n)\{\{\{\n((.*\n)*?)\}\}\}(\n|$)/,
|
||||
replaceRegex: /^ ([ \t]*\}\}\})/gm,
|
||||
replaceString: '$1' },
|
||||
tt: { tag: 'tt',
|
||||
regex: /\{\{\{(.*?\}\}\}+)/, capture: 1,
|
||||
replaceRegex: /\}\}\}$/, replaceString: '' },
|
||||
|
||||
ulist: { tag: 'ul', capture: 0,
|
||||
regex: /(^|\n)([ \t]*\*[^*#].*(\n|$)([ \t]*[^\s*#].*(\n|$))*([ \t]*[*#]{2}.*(\n|$))*)+/ },
|
||||
olist: { tag: 'ol', capture: 0,
|
||||
regex: /(^|\n)([ \t]*#[^*#].*(\n|$)([ \t]*[^\s*#].*(\n|$))*([ \t]*[*#]{2}.*(\n|$))*)+/ },
|
||||
li: { tag: 'li', capture: 0,
|
||||
regex: /[ \t]*([*#]).+(\n[ \t]*[^*#\s].*)*(\n[ \t]*\1[*#].+)*/,
|
||||
replaceRegex: /(^|\n)[ \t]*[*#]/g, replaceString: '$1' },
|
||||
|
||||
table: { tag: 'table', capture: 0,
|
||||
regex: /(^|\n)(\|.*?[ \t]*(\n|$))+/ },
|
||||
tr: { tag: 'tr', capture: 2, regex: /(^|\n)(\|.*?)\|?[ \t]*(\n|$)/ },
|
||||
th: { tag: 'th', regex: /\|+=([^|]*)/, capture: 1 },
|
||||
td: { tag: 'td', capture: 1,
|
||||
regex: /\|+([^|~]*(~(.|(?=\n)|$)[^|~]*)*)/ },
|
||||
|
||||
singleLine: { regex: /.+/, capture: 0 },
|
||||
paragraph: { tag: 'p', capture: 0,
|
||||
regex: /(^|\n)([ \t]*\S.*(\n|$))+/ },
|
||||
text: { capture: 0, regex: /(^|\n)([ \t]*[^\s].*(\n|$))+/ },
|
||||
|
||||
strong: { tag: 'strong', capture: 1,
|
||||
regex: /\*\*([^*~]*((\*(?!\*)|~(.|(?=\n)|$))[^*~]*)*)(\*\*|\n|$)/ },
|
||||
em: { tag: 'em', capture: 1,
|
||||
regex: '\\/\\/(((?!' + rx.uriPrefix + ')[^\\/~])*' +
|
||||
'((' + rx.rawUri + '|\\/(?!\\/)|~(.|(?=\\n)|$))' +
|
||||
'((?!' + rx.uriPrefix + ')[^\\/~])*)*)(\\/\\/|\\n|$)' },
|
||||
|
||||
img: { regex: '\\{\\{((?!\\{)[^|}\\n]*(?:}(?!})[^|}\\n]*)*)\\|' +
|
||||
'([^}~\\n]*((}(?!})|~.)[^}~\\n]*)*)}}',
|
||||
build: function(node, r, options) {
|
||||
var img = document.createElement('img');
|
||||
img.src = r[1];
|
||||
img.alt = r[2].replace(/~(.)/g, '$1');
|
||||
node.appendChild(img);
|
||||
} },
|
||||
|
||||
namedUri: { regex: '\\[\\[(' + rx.uri + ')\\|(' + rx.linkText + ')\\]\\]',
|
||||
build: function(node, r, options) {
|
||||
var link = document.createElement('a');
|
||||
link.href = r[1];
|
||||
if (options && options.isPlainUri) {
|
||||
link.appendChild(document.createTextNode(r[2]));
|
||||
}
|
||||
else {
|
||||
this.apply(link, r[2], options);
|
||||
}
|
||||
node.appendChild(link);
|
||||
} },
|
||||
|
||||
namedLink: { regex: '\\[\\[(' + rx.link + ')\\|(' + rx.linkText + ')\\]\\]',
|
||||
build: function(node, r, options) {
|
||||
var link = document.createElement('a');
|
||||
|
||||
link.href = options && options.linkFormat
|
||||
? formatLink(r[1].replace(/~(.)/g, '$1'), options.linkFormat)
|
||||
: r[1].replace(/~(.)/g, '$1');
|
||||
this.apply(link, r[2], options);
|
||||
|
||||
node.appendChild(link);
|
||||
} },
|
||||
|
||||
unnamedUri: { regex: '\\[\\[(' + rx.uri + ')\\]\\]',
|
||||
build: 'dummy' },
|
||||
unnamedLink: { regex: '\\[\\[(' + rx.link + ')\\]\\]',
|
||||
build: 'dummy' },
|
||||
unnamedInterwikiLink: { regex: '\\[\\[(' + rx.interwikiLink + ')\\]\\]',
|
||||
build: 'dummy' },
|
||||
|
||||
rawUri: { regex: '(' + rx.rawUri + ')',
|
||||
build: 'dummy' },
|
||||
|
||||
escapedSequence: { regex: '~(' + rx.rawUri + '|.)', capture: 1,
|
||||
tag: 'span', attrs: { 'class': 'escaped' } },
|
||||
escapedSymbol: { regex: /~(.)/, capture: 1,
|
||||
tag: 'span', attrs: { 'class': 'escaped' } }
|
||||
};
|
||||
g.unnamedUri.build = g.rawUri.build = function(node, r, options) {
|
||||
if (!options) { options = {}; }
|
||||
options.isPlainUri = true;
|
||||
g.namedUri.build.call(this, node, Array(r[0], r[1], r[1]), options);
|
||||
};
|
||||
g.unnamedLink.build = function(node, r, options) {
|
||||
g.namedLink.build.call(this, node, Array(r[0], r[1], r[1]), options);
|
||||
};
|
||||
g.namedInterwikiLink = { regex: '\\[\\[(' + rx.interwikiLink + ')\\|(' + rx.linkText + ')\\]\\]',
|
||||
build: function(node, r, options) {
|
||||
var link = document.createElement('a');
|
||||
|
||||
var m, f;
|
||||
if (options && options.interwiki) {
|
||||
m = r[1].match(/(.*?):(.*)/);
|
||||
f = options.interwiki[m[1]];
|
||||
}
|
||||
|
||||
if (typeof f == 'undefined') {
|
||||
if (!g.namedLink.apply) {
|
||||
g.namedLink = new this.constructor(g.namedLink);
|
||||
}
|
||||
return g.namedLink.build.call(g.namedLink, node, r, options);
|
||||
}
|
||||
|
||||
link.href = formatLink(m[2].replace(/~(.)/g, '$1'), f);
|
||||
|
||||
this.apply(link, r[2], options);
|
||||
|
||||
node.appendChild(link);
|
||||
}
|
||||
};
|
||||
g.unnamedInterwikiLink.build = function(node, r, options) {
|
||||
g.namedInterwikiLink.build.call(this, node, Array(r[0], r[1], r[1]), options);
|
||||
};
|
||||
g.namedUri.children = g.unnamedUri.children = g.rawUri.children =
|
||||
g.namedLink.children = g.unnamedLink.children =
|
||||
g.namedInterwikiLink.children = g.unnamedInterwikiLink.children =
|
||||
[ g.escapedSymbol, g.img ];
|
||||
|
||||
for (var i = 1; i <= 6; i++) {
|
||||
g['h' + i] = { tag: 'h' + i, capture: 2,
|
||||
regex: '(^|\\n)[ \\t]*={' + i + '}[ \\t]' +
|
||||
'([^~]*?(~(.|(?=\\n)|$))*)[ \\t]*=*\\s*(\\n|$)'
|
||||
};
|
||||
}
|
||||
|
||||
g.ulist.children = g.olist.children = [ g.li ];
|
||||
g.li.children = [ g.ulist, g.olist ];
|
||||
g.li.fallback = g.text;
|
||||
|
||||
g.table.children = [ g.tr ];
|
||||
g.tr.children = [ g.th, g.td ];
|
||||
g.td.children = [ g.singleLine ];
|
||||
g.th.children = [ g.singleLine ];
|
||||
|
||||
g.h1.children = g.h2.children = g.h3.children =
|
||||
g.h4.children = g.h5.children = g.h6.children =
|
||||
g.singleLine.children = g.paragraph.children =
|
||||
g.text.children = g.strong.children = g.em.children =
|
||||
[ g.escapedSequence, g.strong, g.em, g.br, g.rawUri,
|
||||
g.namedUri, g.namedInterwikiLink, g.namedLink,
|
||||
g.unnamedUri, g.unnamedInterwikiLink, g.unnamedLink,
|
||||
g.tt, g.img ];
|
||||
|
||||
g.root = {
|
||||
children: [ g.h1, g.h2, g.h3, g.h4, g.h5, g.h6,
|
||||
g.hr, g.ulist, g.olist, g.preBlock, g.table ],
|
||||
fallback: { children: [ g.paragraph ] }
|
||||
};
|
||||
|
||||
Parse.Simple.Base.call(this, g.root, options);
|
||||
};
|
||||
|
||||
Parse.Simple.Creole.prototype = new Parse.Simple.Base();
|
||||
|
||||
Parse.Simple.Creole.prototype.constructor = Parse.Simple.Creole;
|
Загрузка…
Ссылка в новой задаче