trac-wysiwyg-0.12.0.3+r10725/0000755000175000017500000000000011677636642013416 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.12/0000755000175000017500000000000011677636642013776 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/0000755000175000017500000000000011677636642016372 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/__init__.py0000644000175000017500000000432511346222740020466 0ustar wmbwmb# -*- coding: utf-8 -*- import re from trac.core import Component, implements from trac.config import ListOption from trac.ticket.web_ui import TicketModule from trac.web.api import IRequestFilter from trac.web.chrome import ITemplateProvider, add_link, add_stylesheet, add_script, add_script_data from trac.web.href import Href __all__ = ['WysiwygModule'] class WysiwygModule(Component): implements(ITemplateProvider, IRequestFilter) wysiwyg_stylesheets = ListOption('tracwysiwyg', 'wysiwyg_stylesheets', doc="""Add stylesheets to the WYSIWYG editor""") # ITemplateProvider#get_htdocs_dirs def get_htdocs_dirs(self): from pkg_resources import resource_filename return [('tracwysiwyg', resource_filename(__name__, 'htdocs'))] # ITemplateProvider#get_templates_dirs def get_templates_dirs(self): return [] # IRequestFilter#pre_process_request def pre_process_request(self, req, handler): return handler # IRequestFilter#post_process_request def post_process_request(self, req, template, data, content_type): options = {} options['escapeNewlines'] = False if template == 'ticket.html': options['escapeNewlines'] = TicketModule(self.env).must_preserve_newlines if options: add_script_data(req, { '_tracwysiwyg': options }) add_link(req, 'tracwysiwyg.base', req.href() or '/') stylesheets = ['chrome/common/css/trac.css', 'chrome/tracwysiwyg/editor.css'] stylesheets += self.wysiwyg_stylesheets for stylesheet in stylesheets: add_link(req, 'tracwysiwyg.stylesheet', _expand_filename(req, stylesheet)) add_stylesheet(req, 'tracwysiwyg/wysiwyg.css') add_script(req, 'tracwysiwyg/wysiwyg.js') add_script(req, 'tracwysiwyg/wysiwyg-load.js') return (template, data, content_type) def _expand_filename(req, filename): if filename.startswith('chrome/common/') and 'htdocs_location' in req.chrome: href = Href(req.chrome['htdocs_location']) return href(filename[14:]) if filename.startswith('/') or re.match(r'https?://', filename): href = Href(filename) return href() return req.href(filename) trac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/htdocs/0000755000175000017500000000000011677636761017660 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/htdocs/wysiwyg.css0000644000175000017500000001061411317167602022076 0ustar wmbwmbiframe.wysiwyg { border: 1px solid #d7d7d7; clear: both; display: block; -moz-user-select: none; -webkit-user-select: none; } div.trac-resizable { clear: both; } iframe.wysiwyg:focus { border: 1px solid #886; } .editor-toggle { float: right; font-size: 80%; } .wysiwyg-toolbar { border: solid #d7d7d7; border-width: 1px 1px 1px 0; height: 18px; width: 400px; float: left; -moz-user-select: none; -webkit-user-select: none; } .wysiwyg-toolbar ul, .wysiwyg-toolbar li { list-style-type: none; margin: 0px; padding: 0px; } .wysiwyg-toolbar li { float: left; display: block; } .wysiwyg-toolbar li :link, .wysiwyg-toolbar li :visited { background: transparent url(toolbar.png) no-repeat; border: 1px solid #fff; border-left-color: #d7d7d7; cursor: default; display: block; width: 20px; height: 16px; color: #777; } .wysiwyg-toolbar li.selected :link, .wysiwyg-toolbar li.selected :visited { border: 1px solid #7c4; } .wysiwyg-toolbar li a:hover, .wysiwyg-toolbar li.selected a:hover { background-color: transparent; border: 1px solid #fb2; color: #886; } .wysiwyg-toolbar li a#wt-style { width: 62px; white-space: nowrap; overflow-x: hidden; line-height: 1.2; padding-left: 2px; padding-right: 2px; background-image: url(../common/desc.png); background-position: right bottom; } .wysiwyg-toolbar li a#wt-style span { display: none; } .wysiwyg-toolbar li.wysiwyg-menu-style a#wt-style span.wysiwyg-menu-style { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-paragraph a#wt-style span.wysiwyg-menu-paragraph { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading1 a#wt-style span.wysiwyg-menu-heading1 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading2 a#wt-style span.wysiwyg-menu-heading2 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading3 a#wt-style span.wysiwyg-menu-heading3 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading4 a#wt-style span.wysiwyg-menu-heading4 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading5 a#wt-style span.wysiwyg-menu-heading5 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading6 a#wt-style span.wysiwyg-menu-heading6 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-code a#wt-style span.wysiwyg-menu-code { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-quote a#wt-style span.wysiwyg-menu-quote { display: inline; } .wysiwyg-toolbar li a#wt-em { background-position: 0 0; } .wysiwyg-toolbar li a#wt-strong { background-position: 0 -16px; } .wysiwyg-toolbar li a#wt-underline { background-position: 0 -32px; } .wysiwyg-toolbar li a#wt-monospace { background-position: 0 -160px; } .wysiwyg-toolbar li a#wt-link { background-position: 0 -96px; } .wysiwyg-toolbar li a#wt-unlink { background-position: 0 -112px; } .wysiwyg-toolbar li a#wt-ol { background-position: 0 -176px; } .wysiwyg-toolbar li a#wt-ul { background-position: 0 -192px; } .wysiwyg-toolbar li a#wt-outdent { background-position: 0 -208px; } .wysiwyg-toolbar li a#wt-indent { background-position: 0 -224px; } .wysiwyg-toolbar li a#wt-table { background-position: 0 -240px; } .wysiwyg-toolbar li a#wt-hr { background-position: 0 -128px; } .wysiwyg-toolbar li a#wt-br { background-position: 0 -144px; } .wysiwyg-toolbar li a#wt-remove { background-position: 0 -256px; } .wysiwyg-toolbar li a#wt-decorationmenu, .wysiwyg-toolbar li a#wt-tablemenu { width: 10px; background-image: url(../common/desc.png); background-position: center bottom; } .wysiwyg-menu { border: 1px solid #d7d7d7; padding: 1px 2px; background-color: #fff; -moz-opacity: 0.90; opacity: 0.90; } .wysiwyg-menu p, .wysiwyg-menu h1, .wysiwyg-menu h2, .wysiwyg-menu h3, .wysiwyg-menu h4, .wysiwyg-menu h5, .wysiwyg-menu h6, .wysiwyg-menu pre.wiki, .wysiwyg-menu blockquote.citation { margin: 0px; } .wysiwyg-menu ul, .wysiwyg-menu li { list-style-type: none; margin: 0px; padding: 0px; } .wysiwyg-menu :link, .wysiwyg-menu :visited { display: block; padding: 1px; border: 1px solid #fff; color: #000; } .wysiwyg-menu .selected :link, .wysiwyg-menu .selected :visited { border: 1px solid #7c4; } .wysiwyg-menu a:hover, .wysiwyg-menu .selected a:hover { border: 1px solid #fb2; } .wysiwyg-menu .menu { font-size: 85%; } trac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/htdocs/wysiwyg-load.js0000644000175000017500000000012510761221176022632 0ustar wmbwmbjQuery(document).ready(function($) { setTimeout(TracWysiwyg.initialize, 10); }); trac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/htdocs/wysiwyg.js0000644000175000017500000043146011642344654021735 0ustar wmbwmbvar TracWysiwyg = function(textarea, options) { var self = this; var editorMode = TracWysiwyg.getEditorMode(); this.autolink = true; this.textarea = textarea; this.options = options = options || {}; var wikitextToolbar = null; var textareaResizable = null; if (/\btrac-resizable\b/i.test(textarea.className)) { var tmp = textarea.parentNode; tmp = tmp && tmp.parentNode; if (tmp && /\btrac-resizable\b/i.test(tmp.className)) { wikitextToolbar = tmp.previousSibling; textareaResizable = tmp; } } else { wikitextToolbar = textarea.previousSibling; } if (wikitextToolbar && (wikitextToolbar.nodeType != 1 || wikitextToolbar.className != "wikitoolbar")) { wikitextToolbar = null; } this.textareaResizable = textareaResizable; this.wikitextToolbar = wikitextToolbar; this.createEditable(document, textarea, textareaResizable); var frame = this.frame; var resizable = this.resizable; this.contentWindow = frame.contentWindow; this.contentDocument = this.contentWindow.document; this.initializeEditor(this.contentDocument); this.wysiwygToolbar = this.createWysiwygToolbar(document); this.styleMenu = this.createStyleMenu(document); this.decorationMenu = this.createDecorationMenu(document); this.tableMenu = this.createTableMenu(document); this.menus = [ this.styleMenu, this.decorationMenu, this.tableMenu ]; this.toolbarButtons = this.setupMenuEvents(); this.toggleEditorButtons = null; this.autolinkButton = null; this.savedWysiwygHTML = null; this.setupToggleEditorButtons(); this.setupSyncTextAreaHeight(); var styleStatic = { position: "static", left: "-9999px", top: "-9999px" }; var styleAbsolute = { position: "absolute", left: "-9999px", top: "-9999px" }; switch (editorMode) { case "textarea": TracWysiwyg.setStyle(textareaResizable || textarea, styleStatic); if (wikitextToolbar) { TracWysiwyg.setStyle(wikitextToolbar, styleStatic); } TracWysiwyg.setStyle(resizable || frame, { position: "absolute", left: "-9999px", top: TracWysiwyg.elementPosition(textareaResizable || textarea).top + "px" }); TracWysiwyg.setStyle(this.wysiwygToolbar, styleAbsolute); TracWysiwyg.setStyle(this.autolinkButton.parentNode, { display: "none" }); textarea.setAttribute("tabIndex", ""); frame.setAttribute("tabIndex", "-1"); break; case "wysiwyg": TracWysiwyg.setStyle(textareaResizable || textarea, { position: "absolute", left: "-9999px", top: TracWysiwyg.elementPosition(textareaResizable || textarea).top + "px" }); if (wikitextToolbar) { TracWysiwyg.setStyle(wikitextToolbar, styleAbsolute); } TracWysiwyg.setStyle(resizable || frame, styleStatic); TracWysiwyg.setStyle(this.wysiwygToolbar, styleStatic); TracWysiwyg.setStyle(this.autolinkButton.parentNode, { display: "" }); textarea.setAttribute("tabIndex", "-1"); frame.setAttribute("tabIndex", ""); break; } var body = document.body; for (var i = 0; i < this.menus.length; i++) { body.insertBefore(this.menus[i], body.firstChild); } var element = wikitextToolbar || textareaResizable || textarea; element.parentNode.insertBefore(this.toggleEditorButtons, element); element.parentNode.insertBefore(this.wysiwygToolbar, element); function lazySetup() { if (self.contentDocument.body) { var exception; try { self.execCommand("useCSS", false); } catch (e) { } try { self.execCommand("styleWithCSS", false); } catch (e) { } if (editorMode == "wysiwyg") { try { self.loadWysiwygDocument() } catch (e) { exception = e } } self.setupEditorEvents(); self.setupFormEvent(); if (exception) { (self.textareaResizable || self.textarea).style.position = "static"; if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "static"; } (self.resizable || self.frame).style.position = self.wysiwygToolbar.style.position = "absolute"; self.autolinkButton.parentNode.style.display = "none"; alert("Failed to activate the wysiwyg editor."); throw exception; } } else { setTimeout(lazySetup, 100); } } lazySetup(); }; TracWysiwyg.prototype.initializeEditor = function(d) { var l = window.location; var html = []; html.push( '\n', '', '', '', ''); var stylesheets = TracWysiwyg.tracPaths.stylesheets; if (!stylesheets) { // Work around wysiwyg stops with Agilo var base = TracWysiwyg.tracPaths.base.replace(/\/*$/, "/"); stylesheets = [ base + "chrome/common/css/trac.css", base + "chrome/tracwysiwyg/editor.css" ]; } var length = stylesheets.length; for (var i = 0; i < length; i++) { html.push(''); } html.push('', '', '', ''); var first = !window.opera && d.addEventListener ? true : false; if (first) { d.designMode = "On"; } d.open(); d.write(html.join("")); d.close(); if (!first) { d.designMode = "On"; if (d != this.contentWindow.document) { this.contentDocument = this.contentWindow.document; } } }; TracWysiwyg.prototype.toggleAutolink = function() { this.autolink = !this.autolink; this.autolinkButton.checked = this.autolink; }; TracWysiwyg.prototype.listenerToggleAutolink = function(input) { var self = this; return function(event) { self.autolink = input.checked; }; }; TracWysiwyg.prototype.listenerToggleEditor = function(type) { var self = this; switch (type) { case "textarea": return function(event) { var textarea = self.textareaResizable || self.textarea; if (textarea.style.position == "absolute") { self.hideAllMenus(); self.loadTracWikiText(); textarea.style.position = "static"; self.textarea.setAttribute("tabIndex", ""); if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "static"; } self.syncTextAreaHeight(); (self.resizable || self.frame).style.position = self.wysiwygToolbar.style.position = "absolute"; self.frame.setAttribute("tabIndex", "-1"); self.autolinkButton.parentNode.style.display = "none"; TracWysiwyg.setEditorMode(type); } self.focusTextarea(); }; case "wysiwyg": return function(event) { var frame = self.resizable || self.frame; if (frame.style.position == "absolute") { try { self.loadWysiwygDocument(); } catch (e) { TracWysiwyg.stopEvent(event || window.event); alert("Failed to activate the wysiwyg editor."); throw e; } (self.textareaResizable || self.textarea).style.position = "absolute"; self.textarea.setAttribute("tabIndex", "-1"); if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "absolute"; } frame.style.position = self.wysiwygToolbar.style.position = "static"; self.frame.setAttribute("tabIndex", ""); self.autolinkButton.parentNode.style.display = ""; TracWysiwyg.setEditorMode(type); } self.focusWysiwyg(); }; } }; TracWysiwyg.prototype.activeEditor = function() { return this.textarea.style.position == "absolute" ? "wysiwyg" : "textarea"; }; TracWysiwyg.prototype.setupFormEvent = function() { var self = this; function listener(event) { var textarea = self.textareaResizable || self.textarea; try { if (textarea.style.position == "absolute") { var body = self.contentDocument.body; if (self.savedWysiwygHTML !== null && body.innerHTML != self.savedWysiwygHTML) { self.textarea.value = self.domToWikitext(body, self.options); } } } catch (e) { TracWysiwyg.stopEvent(event || window.event); } } addEvent(this.textarea.form, "submit", listener); }; TracWysiwyg.prototype.createEditable = function(d, textarea, textareaResizable) { var self = this; var getStyle = TracWysiwyg.getStyle; var dimension = getDimension(textarea); if (!dimension.width || !dimension.height) { setTimeout(lazy, 100); } if (!dimension.width) { dimension.width = parseInt(getStyle(textarea, "fontSize"), 10) * (textarea.cols || 10) * 0.5; } if (!dimension.height) { dimension.height = parseInt(getStyle(textarea, "lineHeight"), 10) * (textarea.rows || 3); } var wrapper = d.createElement("div"); wrapper.innerHTML = ''; var frame = this.frame = wrapper.firstChild; if (textareaResizable) { var offset = null; var offsetFrame = null; var contentDocument = null; var grip = d.createElement("div"); grip.className = "trac-grip"; if (/^[0-9]+$/.exec(dimension.width)) { grip.style.width = dimension.width + "px"; } addEvent(grip, "mousedown", beginDrag); wrapper.appendChild(grip); var resizable = d.createElement("div"); resizable.className = "trac-resizable"; resizable.appendChild(wrapper); grip.style.marginLeft = (frame.offsetLeft - grip.offsetLeft) + 'px'; grip.style.marginRight = (grip.offsetWidth - frame.offsetWidth) +'px'; this.resizable = resizable; textareaResizable.parentNode.insertBefore(resizable, textareaResizable.nextSibling); } else { textarea.parentNode.insertBefore(frame, textarea.nextSibling); } function beginDrag(event) { offset = frame.height - event.pageY; contentDocument = self.contentDocument; frame.blur(); addEvent(d, "mousemove", dragging); addEvent(d, "mouseup", endDrag); addEvent(contentDocument, "mousemove", draggingForFrame); addEvent(contentDocument, "mouseup", endDrag); } var topPageY = 0, framePageY = 0; function dragging(event) { var height = Math.max(32, offset + event.pageY); textarea.style.height = height + "px"; frame.height = height; } function draggingForFrame(event) { var height = Math.max(32, event.clientY); textarea.style.height = height + "px"; frame.height = height; } function endDrag(event) { self.focusWysiwyg(); TracWysiwyg.removeEvent(d, "mousemove", dragging); TracWysiwyg.removeEvent(d, "mouseup", endDrag); TracWysiwyg.removeEvent(contentDocument, "mousemove", draggingForFrame); TracWysiwyg.removeEvent(contentDocument, "mouseup", endDrag); } function getDimension(textarea) { var width = textarea.offsetWidth; if (width) { var parentWidth = textarea.parentNode.offsetWidth + parseInt(getStyle(textarea, 'borderLeftWidth'), 10) + parseInt(getStyle(textarea, 'borderRightWidth'), 10); if (width == parentWidth) { width = "100%"; } } return { width: width, height: textarea.offsetHeight }; } function lazy() { var dimension = getDimension(textarea); if (dimension.width && dimension.height) { self.frame.width = dimension.width; self.frame.height = dimension.height; if (textareaResizable) { grip.style.width = /^[0-9]+$/.exec(dimension.width) ? dimension.width + "px" : dimension.width; } return; } setTimeout(lazy, 100); } }; TracWysiwyg.prototype.createWysiwygToolbar = function(d) { var html = [ '' ]; var div = d.createElement("div"); div.className = "wysiwyg-toolbar"; div.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return div; }; TracWysiwyg.prototype.createStyleMenu = function(d) { var html = [ '

Normal

', '

Header 1

', '

Header 2

', '

Header 3

', '

Header 4

', '
Header 5
', '
Header 6
', '
Code block
', '
Quote
' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.createDecorationMenu = function(d) { var html = [ '' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.createTableMenu = function(d) { var html = [ '' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.setupMenuEvents = function() { function addToolbarEvent(element, self, args) { var method = args.shift(); addEvent(element, "click", function(event) { var w = self.contentWindow; TracWysiwyg.stopEvent(event || w.event); var keepMenus = false, exception; try { keepMenus = method.apply(self, args) } catch (e) { exception = e } if (!keepMenus) { self.hideAllMenus(); } element.blur(); w.focus(); if (exception) { throw exception; } }); } function argsByType(self, name, element) { switch (name) { case "style": return [ self.toggleMenu, self.styleMenu, element ]; case "strong": return [ self.execDecorate, "bold" ]; case "em": return [ self.execDecorate, "italic" ]; case "underline": return [ self.execDecorate, "underline" ]; case "strike": return [ self.execDecorate, "strikethrough" ]; case "sub": return [ self.execDecorate, "subscript" ]; case "sup": return [ self.execDecorate, "superscript" ]; case "monospace": return [ self.execDecorate, "monospace" ]; case "decorationmenu": return [ self.toggleMenu, self.decorationMenu, element ]; case "remove": return [ self.execCommand, "removeformat" ]; case "paragraph": return [ self.formatParagraph ]; case "heading1": return [ self.formatHeaderBlock, "h1" ]; case "heading2": return [ self.formatHeaderBlock, "h2" ]; case "heading3": return [ self.formatHeaderBlock, "h3" ]; case "heading4": return [ self.formatHeaderBlock, "h4" ]; case "heading5": return [ self.formatHeaderBlock, "h5" ]; case "heading6": return [ self.formatHeaderBlock, "h6" ]; case "link": return [ self.createLink ]; case "unlink": return [ self.execCommand, "unlink" ]; case "ol": return [ self.insertOrderedList ]; case "ul": return [ self.insertUnorderedList ]; case "outdent": return [ self.outdent ]; case "indent": return [ self.indent ]; case "table": return [ self.insertTable ]; case "tablemenu": return [ self.toggleMenu, self.tableMenu, element ]; case "insert-row-before": return [ self.insertTableRow, false ]; case "insert-row-after": return [ self.insertTableRow, true ]; case "insert-col-before": return [ self.insertTableColumn, false ]; case "insert-col-after": return [ self.insertTableColumn, true ]; case "delete-row": return [ self.deleteTableRow ]; case "delete-col": return [ self.deleteTableColumn ]; case "code": return [ self.formatCodeBlock ]; case "quote": return [ self.formatQuoteBlock ]; case "hr": return [ self.insertHorizontalRule ]; case "br": return [ self.insertLineBreak ]; } return null; } function setup(container) { var elements = container.getElementsByTagName("a"); var length = elements.length; for (var i = 0; i < length; i++) { var element = elements[i]; var name = element.id.replace(/^wt-/, ""); var args = argsByType(this, name, element); if (args) { addToolbarEvent(element, this, args); buttons[name] = element; } } } var buttons = {}; setup.call(this, this.wysiwygToolbar); for (var i = 0; i < this.menus.length; i++) { setup.call(this, this.menus[i]); } return buttons; }; TracWysiwyg.prototype.toggleMenu = function(menu, element) { if (parseInt(menu.style.left, 10) < 0) { this.hideAllMenus(menu); var position = TracWysiwyg.elementPosition(element); TracWysiwyg.setStyle(menu, { left: position[0] + "px", top: (position[1] + 18) + "px" }); } else { this.hideAllMenus(); } return true; }; TracWysiwyg.prototype.hideAllMenus = function(except) { var menus = this.menus; var length = menus.length; for (var i = 0; i < length; i++) { if (menus[i] != except) { TracWysiwyg.setStyle(menus[i], { left: "-1000px", top: "-1000px" }); } } }; TracWysiwyg.prototype.execDecorate = function(name) { if (this.selectionContainsTagName("pre")) { return; } var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var position = this.getSelectionPosition(); var ancestor = {}; ancestor.start = getSelfOrAncestor(position.start, /^(?:a|tt)$/); ancestor.end = getSelfOrAncestor(position.end, /^(?:a|tt)$/); this.expandSelectionToElement(ancestor); if (name != "monospace") { this.execCommand(name); } else { this.execDecorateMonospace(); } this.selectionChanged(); }; TracWysiwyg.prototype.execDecorateMonospace = function() { var html = this.getSelectionHTML(); var removePattern = /|<\/tt>/gi; if (/^/i.test(html) && /<\/tt>$/i.test(html)) { html = html.replace(removePattern, ""); } else { var id = this.generateDomId(); html = '' + html.replace(removePattern, "") + ""; } this.insertHTML(html); var node = this.contentDocument.getElementById(id); if (node) { this.selectNode(node); } }; TracWysiwyg.prototype.execCommand = function(name, arg) { return this.contentDocument.execCommand(name, false, arg); }; TracWysiwyg.prototype.setupEditorEvents = function() { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var self = this; var d = this.contentDocument; var w = this.contentWindow; var ime = false; function listenerKeydown(event) { var method = null; var args = null; event = event || self.contentWindow.event; var keyCode = event.keyCode; switch (keyCode) { case 0x09: // TAB var range = self.getSelectionRange(); var stop = false; var element = getSelfOrAncestor(range.startContainer, /^(?:li|pre|table)$/); if (element) { switch (element.tagName.toLowerCase()) { case "li": self.execCommand(event.shiftKey ? "outdent" : "indent"); self.selectionChanged(); stop = true; break; case "pre": self.insertHTML("\t"); stop = true; break; case "table": if (getSelfOrAncestor(range.endContainer, "table") == element) { self.moveFocusInTable(!event.shiftKey); self.selectionChanged(); stop = true; } break; } } if (stop) { TracWysiwyg.stopEvent(event); } return; case 0xe5: ime = true; break; } switch ((keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0)) { case 0x40000042: // C-b method = self.execDecorate; args = [ "bold" ]; break; case 0x40000049: // C-i method = self.execDecorate; args = [ "italic" ]; break; case 0x4000004c: // C-l method = self.toggleAutolink; args = []; break; case 0x40000055: // C-u method = self.execDecorate; args = [ "underline" ]; break; case 0x40000059: // C-y method = self.execCommand; args = [ "redo" ]; break; case 0x4000005a: // C-z method = self.execCommand; args = [ "undo" ]; break; } if (method !== null) { TracWysiwyg.stopEvent(event); method.apply(self, args); self.selectionChanged(); } else if (keyCode) { var focus = self.getFocusNode(); if (!getSelfOrAncestor(focus, /^(?:p|li|h[1-6]|t[dh]|d[td]|pre|blockquote)$/)) { self.execCommand("formatblock", "

"); } } } addEvent(d, window.opera ? "keypress" : "keydown", listenerKeydown); function listenerKeypress(event) { event = event || self.contentWindow.event; var modifier = (event.ctrlKey ? 0x40000000 : 0) | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0); switch (event.charCode || event.keyCode) { case 0x20: // SPACE self.detectTracLink(event); return; case 0x3e: // ">" self.detectTracLink(event); return; case 0x0d: // ENTER self.detectTracLink(event); switch (modifier) { case 0: if (self.insertParagraphOnEnter) { self.insertParagraphOnEnter(event); } break; case 0x20000000: // Shift if (self.insertLineBreakOnShiftEnter) { self.insertLineBreakOnShiftEnter(event); } break; } return; } } addEvent(d, "keypress", listenerKeypress); function listenerKeyup(event) { var keyCode = event.keyCode; if (ime) { switch (keyCode) { case 0x20: // SPACE self.detectTracLink(event); break; } ime = false; } self.selectionChanged(); } addEvent(d, "keyup", listenerKeyup); function listenerMouseup(event) { self.selectionChanged(); } addEvent(d, "mouseup", listenerMouseup); function listenerClick(event) { self.hideAllMenus(); self.selectionChanged(); } addEvent(d, "click", listenerClick); }; TracWysiwyg.prototype.loadWysiwygDocument = function() { var d = this.contentDocument; var container = d.body; var tmp; while (tmp = container.lastChild) { container.removeChild(tmp); } var fragment = this.wikitextToFragment(this.textarea.value, d, this.options); container.appendChild(fragment); this.savedWysiwygHTML = container.innerHTML; }; TracWysiwyg.prototype.focusWysiwyg = function() { var self = this; var w = this.contentWindow; function lazy() { w.focus(); try { self.execCommand("useCSS", false); } catch (e) { } try { self.execCommand("styleWithCSS", false); } catch (e) { } self.selectionChanged(); } setTimeout(lazy, 10); }; TracWysiwyg.prototype.loadTracWikiText = function() { this.textarea.value = this.domToWikitext(this.contentDocument.body, this.options); this.savedWysiwygHTML = null; }; TracWysiwyg.prototype.focusTextarea = function() { this.textarea.focus(); }; TracWysiwyg.prototype.setupToggleEditorButtons = function() { var div = document.createElement("div"); var mode = TracWysiwyg.editorMode; var html = '' + '' + ' ' + ' ' + '  '; div.className = "editor-toggle"; div.innerHTML = html.replace(/@/g, ++TracWysiwyg.count); this.toggleEditorButtons = div; var buttons = div.getElementsByTagName("input"); for (var i = 0; i < buttons.length; i++) { var button = buttons[i]; switch (button.type) { case "checkbox": var listener = this.listenerToggleAutolink(button); addEvent(button, "click", listener); addEvent(button, "keypress", listener); this.autolinkButton = button; break; case "radio": addEvent(button, "click", this.listenerToggleEditor(button.value)); break; } } }; TracWysiwyg.prototype.setupSyncTextAreaHeight = function() { var self = this; var d = document; var timer = null; var editrows = document.getElementById("editrows"); if (editrows) { addEvent(editrows, "change", changeHeight); } if (this.textareaResizable) { addEvent(this.textarea.nextSibling, "mousedown", beginDrag); } function changeHeight() { if (timer !== null) { clearTimeout(timer); } setTimeout(sync, 10); } function beginDrag(event) { addEvent(d, "mousemove", changeHeight); addEvent(d, "mouseup", endDrag); } function endDrag(event) { TracWysiwyg.removeEvent(d, "mousemove", changeHeight); TracWysiwyg.removeEvent(d, "mouseup", endDrag); } function sync() { timer = null; self.syncTextAreaHeight(); } }; TracWysiwyg.prototype.syncTextAreaHeight = function() { var height = this.textarea.offsetHeight; var frame = this.frame; if (height > 0 && frame.height != height) { frame.height = height; } }; TracWysiwyg.prototype.detectTracLink = function(event) { if (!this.autolink) { return; } var range = this.getSelectionRange(); var node = range.startContainer; if (!node || !range.collapsed) { return; } var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; if (getSelfOrAncestor(node, /^(?:a|tt|pre)$/)) { return; } var offset = range.startOffset; if (node.nodeType != 3) { node = node.childNodes[offset]; while (node && node.nodeType != 3) { node = node.lastChild; } if (!node) { return; } offset = node.nodeValue.length; } else if (offset == 0) { node = node.previousSibling; if (!node || node.nodeType == 1) { return; } offset = node.nodeValue.length; } var startContainer = node; var endContainer = node; var text = [ node.nodeValue.substring(0, offset) ]; for ( ; ; ) { if (/[ \t\r\n\f\v]/.test(text[text.length - 1])) { break; } node = node.previousSibling; if (!node || node.nodeType == 1) { break; } text.push(node.nodeValue); startContainer = node; } text.reverse(); text = text.join(""); if (!text) { return; } var pattern = this.wikiDetectTracLinkPattern; pattern.lastIndex = /[^ \t\r\n\f\v]*$/.exec(text).index; var match, tmp; for (tmp = pattern.exec(text); tmp; tmp = pattern.exec(text)) { match = tmp; } if (!match) { return; } var label = match[0]; var link = this.normalizeTracLink(label); var id = this.generateDomId(); var anchor = this.createAnchor(link, label, { id: id, "data-tracwysiwyg-autolink": "true" }); var anonymous = this.contentDocument.createElement("div"); anonymous.appendChild(anchor); var html = anonymous.innerHTML; node = endContainer; var startOffset = match.index; while (startContainer != node && startOffset >= startContainer.nodeValue.length) { startOffset -= startContainer.nodeValue.length; startContainer = startContainer.nextSibling; } var endOffset = startOffset + label.length; endContainer = startContainer; while (endContainer != node && endOffset >= endContainer.nodeValue.length) { endOffset -= endContainer.nodeValue.length; endContainer = endContainer.nextSibling; } this.selectRange(startContainer, startOffset, endContainer, endOffset); offset = text.length - match.index - label.length; if (offset == 0) { switch (event.keyCode) { case 0x20: // SPACE this.insertHTML(html + "\u00a0"); TracWysiwyg.stopEvent(event); return; case 0x0d: // ENTER if (event.shiftKey) { if (window.opera || !anonymous.addEventListener) { this.insertHTML(html + "
"); if (window.opera) { anchor = this.contentDocument.getElementById(id); node = anchor.parentNode; offset = node.childNodes.length; this.selectRange(node, offset, node, offset); } TracWysiwyg.stopEvent(event); return; } } this.insertHTML(html); anchor = this.contentDocument.getElementById(id); node = event.shiftKey ? anchor.parentNode : anchor; offset = node.childNodes.length; this.selectRange(node, offset, node, offset); return; } } this.insertHTML(html); anchor = this.contentDocument.getElementById(id); node = anchor.nextSibling; if (!node) { node = anchor.parentNode; offset = node.childNodes.length; } this.selectRange(node, offset, node, offset); }; TracWysiwyg.prototype.formatParagraph = function() { if (this.selectionContainsTagName("table")) { return; } this.execCommand("formatblock", "

"); this.selectionChanged(); }; TracWysiwyg.prototype.formatHeaderBlock = function(name) { if (this.selectionContainsTagName("table")) { return; } this.execCommand("formatblock", "<" + name + ">"); this.selectionChanged(); }; TracWysiwyg.prototype.insertOrderedList = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("insertorderedlist"); this.selectionChanged(); }; TracWysiwyg.prototype.insertUnorderedList = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("insertunorderedlist"); this.selectionChanged(); }; TracWysiwyg.prototype.outdent = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("outdent"); }; TracWysiwyg.prototype.indent = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("indent"); }; TracWysiwyg.prototype.insertTable = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var id = this.generateDomId(); this.insertHTML(this.tableHTML(id, 2, 3)); var element = this.contentDocument.getElementById(id) if (element) { this.selectNodeContents(element); } this.selectionChanged(); }; TracWysiwyg.prototype._tableHTML = function(row, col) { var tr = "" + ((1 << col) - 1).toString(2).replace(/1/g, "") + ""; var html = [ '', '', ((1 << row) - 1).toString(2).replace(/1/g, tr), '', '
' ]; return html.join(""); }; TracWysiwyg.prototype._getFocusForTable = function() { var hash = { node: null, cell: null, row: null, table: null }; hash.node = this.getFocusNode(); hash.cell = hash.node ? TracWysiwyg.getSelfOrAncestor(hash.node, /^t[dh]$/) : null; hash.row = hash.cell ? TracWysiwyg.getSelfOrAncestor(hash.cell, "tr") : null; hash.table = hash.row ? TracWysiwyg.getSelfOrAncestor(hash.row, "table") : null; return hash; }; TracWysiwyg.prototype.insertTableRow = function(after) { var focus = this._getFocusForTable(); if (focus.table && focus.row) { var d = this.contentDocument; var cells = focus.row.getElementsByTagName("td"); var row = focus.table.insertRow(focus.row.rowIndex + (after ? 1 : 0)); for (var j = 0; j < cells.length; j++) { this.insertTableCell(row, 0); } } }; TracWysiwyg.prototype.insertTableColumn = function(after) { var focus = this._getFocusForTable(); if (focus.table && focus.cell) { var d = this.contentDocument; var rows = focus.table.rows; var length = rows.length; var cellIndex = focus.cell.cellIndex + (after ? 1 : 0); for (var i = 0; i < length; i++) { var row = rows[i]; this.insertTableCell(row, Math.min(cellIndex, row.cells.length)); } } }; TracWysiwyg.prototype.deleteTableRow = function() { var focus = this._getFocusForTable(); if (focus.table && focus.row) { focus.table.deleteRow(focus.row.rowIndex); } }; TracWysiwyg.prototype.deleteTableColumn = function() { var focus = this._getFocusForTable(); if (focus.table && focus.cell) { var rows = focus.table.rows; var length = rows.length; var cellIndex = focus.cell.cellIndex; for (var i = 0; i < length; i++) { var row = rows[i]; if (cellIndex < row.cells.length) { row.deleteCell(cellIndex); } } } }; TracWysiwyg.prototype.moveFocusInTable = function(forward) { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var focus = this.getFocusNode(); var element = getSelfOrAncestor(focus, /^(?:t[dhr]|table)$/); var target, table, rows, cells; switch (element.tagName.toLowerCase()) { case "td": case "th": focus = element; var row = getSelfOrAncestor(element, "tr"); cells = row.cells; if (forward) { if (focus.cellIndex + 1 < cells.length) { target = cells[focus.cellIndex + 1]; } else { table = getSelfOrAncestor(row, /^(?:tbody|table)$/); rows = table.rows; target = row.rowIndex + 1 < rows.length ? rows[row.rowIndex + 1].cells[0] : null; } } else { if (focus.cellIndex > 0) { target = cells[focus.cellIndex - 1]; } else { table = getSelfOrAncestor(row, /^(?:tbody|table)$/); rows = table.rows; if (row.rowIndex > 0) { cells = rows[row.rowIndex - 1].cells; target = cells[cells.length - 1]; } else { target = null; } } } break; case "tr": cells = element.cells; target = cells[forward ? 0 : cells.length - 1]; break; case "tbody": case "table": rows = element.rows; cells = rows[forward ? 0 : rows.length - 1].cells; target = cells[forward ? 0 : cells.length - 1]; break; } if (target) { this.selectNodeContents(target); } else if (table) { table = getSelfOrAncestor(table, "table"); var parent = table.parentNode; var elements = parent.childNodes; var length = elements.length; for (var offset = 0; offset < length; offset++) { if (table == elements[offset]) { if (forward) { offset++; } this.selectRange(parent, offset, parent, offset); } } } }; TracWysiwyg.prototype.formatCodeBlock = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var text = this.getSelectionText(); if (!text) { var node = this.getFocusNode(); while (node.nodeType == 3) { node = node.parentNode; } text = TracWysiwyg.getTextContent(node); this.selectNode(node); } var fragment = this.getSelectionFragment(); text = this.domToWikitext(fragment, { formatCodeBlock: true }).replace(/\s+$/, ""); var d = this.contentDocument; var anonymous = d.createElement("div"); var pre = d.createElement("pre"); pre.className = "wiki"; anonymous.appendChild(pre); if (text) { pre.appendChild(d.createTextNode(text)); } this.insertHTML(anonymous.innerHTML); this.selectionChanged(); }; TracWysiwyg.prototype.formatQuoteBlock = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var d = this.contentDocument; var anonymous = d.createElement("div"); var container = d.createElement("blockquote"); container.className = "citation"; var fragment = this.getSelectionFragment(); var childNodes = fragment.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { var child = childNodes[i]; var text = null; switch (child.nodeType) { case 1: if (child.tagName.toLowerCase() != "blockquote" || child.className != "citation") { text = TracWysiwyg.getTextContent(child); } break; case 3: text = child.nodeValue; break; default: continue; } if (text !== null) { if (!text) { continue; } var tmp = d.createElement("p"); tmp.appendChild(d.createTextNode(text)); child = tmp; } container.insertBefore(child, container.firstChild); } if (container.childNodes.length == 0) { container.appendChild(d.createElement("p")); } anonymous.appendChild(container); this.insertHTML(anonymous.innerHTML); this.selectionChanged(); }; TracWysiwyg.prototype.insertHorizontalRule = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } if (!this.execCommand("inserthorizontalrule")) { this.insertHTML("


"); } this.selectionChanged(); }; TracWysiwyg.prototype.createLink = function() { if (this.selectionContainsTagName("pre")) { return; } var focus = this.getFocusNode(); var anchor = TracWysiwyg.getSelfOrAncestor(focus, "a"); var expand = anchor || TracWysiwyg.getSelfOrAncestor(focus, "tt"); var currLink; if (anchor) { var attrs; var autolink = anchor.getAttribute("data-tracwysiwyg-autolink"); if (autolink === null) { attrs = TracWysiwyg.unserializeFromHref(anchor.href); autolink = attrs["data-tracwysiwyg-autolink"]; } if (autolink == "true") { var pattern = this.wikiDetectTracLinkPattern; pattern.lastIndex = 0; var label = TracWysiwyg.getTextContent(anchor); var match = pattern.exec(label); if (match && match.index == 0 && match[0].length == label.length) { currLink = this.normalizeTracLink(label); } } if (!currLink) { currLink = anchor.getAttribute("data-tracwysiwyg-link") || attrs["data-tracwysiwyg-link"] || anchor.href; } } else { currLink = ""; } if (expand) { this.selectNodeContents(expand); } var text = this.getSelectionText() || ""; var newLink = (prompt(text ? "Enter TracLink:" : "Insert TracLink:", currLink) || "").replace(/^\s+|\s+$/g, ""); if (newLink && newLink != currLink) { text = text || newLink; newLink = this.normalizeTracLink(newLink); var id = this.generateDomId(); var d = this.contentDocument; var anonymous = d.createElement("div"); anchor = this.createAnchor(newLink, text, { id: id }); anonymous.appendChild(anchor); this.insertHTML(anonymous.innerHTML); anchor = d.getElementById(id); if (anchor) { this.selectNodeContents(anchor); } } this.selectionChanged(); }; TracWysiwyg.prototype.createAnchor = function(link, label, attrs) { var d = this.contentDocument; var anchor = d.createElement("a"); var href = {}; for (var name in attrs) { var value = attrs[name]; href[name] = value; anchor.setAttribute(name, value); } href["data-tracwysiwyg-link"] = link; anchor.href = TracWysiwyg.serializeToHref(href); anchor.title = link; anchor.setAttribute("data-tracwysiwyg-link", link); anchor.setAttribute("onclick", "return false;"); anchor.appendChild(d.createTextNode(label)); return anchor; }; TracWysiwyg.prototype.collectChildNodes = function(dest, source) { var childNodes = source.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { dest.insertBefore(childNodes[i], dest.firstChild); } }; TracWysiwyg.prototype.generateDomId = function() { var d = this.contentDocument; for ( ; ; ) { var id = "tmp-" + (new Date().valueOf().toString(36)); if (!d.getElementById(id)) { return id; } } }; TracWysiwyg.prototype.selectionChanged = function() { var status = { strong: false, em: false, underline: false, strike: false, sub: false, sup: false, monospace: false, paragraph: false, heading1: false, heading2: false, heading3: false, heading4: false, heading5: false, heading6: false, link: false, ol: false, ul: false, outdent: false, indent: false, table: false, code: false, quote: false, hr: false, br: false }; var tagNameToKey = { b: "strong", i: "em", u: "underline", del: "strike", tt: "monospace", p: "paragraph", h1: "heading1", h2: "heading2", h3: "heading3", h4: "heading4", h5: "heading5", h6: "heading6", a: "link", pre: "code", blockquote: "quote" }; var position = this.getSelectionPosition(); var node; if (position.start) { node = position.start == position.end ? position.start.firstChild : position.start.nextSibling; node = node || position.start; } else { node = null; } while (node) { if (node.nodeType == 1) { var name = node.tagName.toLowerCase(); if (name in tagNameToKey) { name = tagNameToKey[name]; } status[name] = true; } node = node.parentNode; } var toolbarButtons = this.toolbarButtons; for (var name in status) { var button = toolbarButtons[name]; if (button) { var parent = button.parentNode; parent.className = (parent.className || "").replace(/ *\bselected\b|$/, status[name] ? " selected" : ""); } } var styles = [ "quote", "paragraph", "code", "heading1", "heading2", "heading3", "heading4", "heading5", "heading6" ]; var styleButton = toolbarButtons["style"]; var styleButtonClass = "wysiwyg-menu-style"; for (var i = 0; i < styles.length; i++) { var name = styles[i]; if (status[name]) { styleButtonClass = "wysiwyg-menu-" + name; break; } } styleButton.parentNode.className = styleButtonClass; }; (function() { var _linkScheme = "[a-zA-Z][a-zA-Z0-9+-.]*"; // cf. WikiSystem.XML_NAME, http://www.w3.org/TR/REC-xml/#id var _xmlName = "[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD](?:[-:_.A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]*[-_A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD])?" var _quotedString = "'[^']+'|" + '"[^"]+"'; var _changesetId = "(?:\\d+|[a-fA-F\\d]{6,})"; var _ticketLink = "#\\d+"; var _reportLink = "\\{\\d+\\}"; var _changesetPath = "/[^\\]]*"; var _changesetLinkBracket = "\\[" + _changesetId + "(?:" + _changesetPath + ")?\\]"; var _changesetLinkRev = "r" + _changesetId + "\\b(?!:" + _changesetId + ")"; var _logLinkBracket = "\\[" + _changesetId + "[-:]" + _changesetId + "(?:" + _changesetPath + ")?\\]"; var _logLinkRev = "r" + _changesetId + "[-:]" + _changesetId + "\\b"; var _tracLink = _linkScheme + ":(?:" + _quotedString + "|[a-zA-Z0-9/?!#@](?:(?:\\|(?=[^| \\t\\r\\f\\v])|[^|<> \\t\\r\\f\\v])*[a-zA-Z0-9/=])?)"; var _wikiPageName = "[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+(?:#[\\w:][-\\w\\d.:]*)?" + "(?=:(?:$|[ \\t\\r\\f\\v])|[^:a-zA-Z]|[ \\t\\r\\f\\v]|$)"; var wikiInlineRules = []; wikiInlineRules.push("!?'''''"); // 1. bolditalic wikiInlineRules.push("!?'''"); // 2. bold wikiInlineRules.push("!?''"); // 3. italic wikiInlineRules.push("!?__"); // 4. underline wikiInlineRules.push("!?~~"); // 5. strike wikiInlineRules.push("!?,,"); // 6. subscript wikiInlineRules.push("!?\\^"); // 7. superscript wikiInlineRules.push("!?\\{\\{\\{.*?\\}\\}\\}"); // 8. code block wikiInlineRules.push("!?`.*?`"); // 9. inline wikiInlineRules.push("[!&]?" + _ticketLink); // 10. ticket wikiInlineRules.push("!?" + _reportLink); // 11. report // 12. changeset wikiInlineRules.push("!?" + _changesetLinkBracket + "|(?:\\b|!)" + _changesetLinkRev); // 13. log wikiInlineRules.push("!?" + _logLinkBracket + "|(?:\\b|!)" + _logLinkRev); wikiInlineRules.push("!?" + _tracLink); // 14. wiki:TracLinks wikiInlineRules.push("!?\\[(?:" // 15. [wiki:TracLinks label] or [/relative label] + "[/.#][^ \\t\\r\\f\\v[\\]]*|" + _linkScheme + ":(?:" + _quotedString + "|[^\\] \\t\\r\\f\\v]*)|" + _wikiPageName + "[ \\t\\r\\f\\v]+(?:" + _quotedString + "|[^\\]]+)" + ")(?:[ \\t\\r\\f\\v]+(?:" + _quotedString + "|[^\\]]+))?\\]"); // 16. [[macro]] wikiInlineRules.push("!?\\[\\[(?:[\\w/+-]+\\??|\\?)(?:\\]\\]|\\(.*?\\)\\]\\])"); // 17. WikiPageName wikiInlineRules.push("(?:\\b|!)" + _wikiPageName); // 18. ["internal free link"] wikiInlineRules.push("!?\\[(?:" + _quotedString + ")\\]"); // 19. wikiInlineRules.push("!?<@:[^>]+>".replace(/@/g, _linkScheme)); // 20. [=#anchor label] wikiInlineRules.push("!?\\[=#" + _xmlName + "(?:[ \\t\\r\\f\\v]+[^\\]]*)?\\]"); var wikiToDomInlineRules = wikiInlineRules.slice(0); // 1001. escaping double pipes wikiToDomInlineRules.push("!=?(?:\\|\\|)+(?:[ \\t\\r\\f\\v]*$|)"); var wikiRules = wikiToDomInlineRules.slice(0); wikiRules.push("^(?: *>)+[ \\t\\r\\f\\v]*"); // -1. citation // -2. header wikiRules.push("^[ \\t\\r\\f\\v]*={1,6}[ \\t\\r\\f\\v]+.*?(?:#" + _xmlName + ")?[ \\t\\r\\f\\v]*$"); // -3. list wikiRules.push("^[ \\t\\r\\f\\v]*(?:[-*]|[0-9]+\\.|[a-zA-Z]\\.|[ivxIVX]{1,5}\\.) "); // -4. definition wikiRules.push("^[ \\t\\r\\f\\v]+(?:`[^`]*`|\\{\\{\\{.*?\\}\\}\\}|[^`{:]|:[^:])+::(?:[ \\t\\r\\f\\v]+|$)"); wikiRules.push("^[ \\t\\r\\f\\v]+(?=[^ \\t\\r\\f\\v])"); // -5. leading space wikiRules.push("=?(?:\\|\\|)+[ \\t\\r\\f\\v]*\\\\?$"); // -6. closing table row wikiRules.push("=?(?:\\|\\|)+=?"); // -7. cell var domToWikiInlineRules = wikiInlineRules.slice(0); domToWikiInlineRules.push("!?=?(?:\\|\\|)+=?"); // cell var wikiSyntaxRules = []; wikiSyntaxRules.push(_ticketLink); wikiSyntaxRules.push(_reportLink); wikiSyntaxRules.push(_changesetLinkBracket); wikiSyntaxRules.push(_changesetLinkRev); wikiSyntaxRules.push(_logLinkBracket); wikiSyntaxRules.push(_logLinkRev); var wikiDetectTracLinkRules = []; wikiDetectTracLinkRules.push(_ticketLink); wikiDetectTracLinkRules.push(_reportLink); wikiDetectTracLinkRules.push(_changesetLinkBracket); wikiDetectTracLinkRules.push("\\b" + _changesetLinkRev); wikiDetectTracLinkRules.push(_logLinkBracket); wikiDetectTracLinkRules.push("\\b" + _logLinkRev); wikiDetectTracLinkRules.push(_tracLink); wikiDetectTracLinkRules.push("\\b" + _wikiPageName); var domToWikiInlinePattern = new RegExp("(?:" + domToWikiInlineRules.join("|") + ")", "g"); var wikiRulesPattern = new RegExp("(?:(" + wikiRules.join(")|(") + "))", "g"); var wikiSyntaxPattern = new RegExp("^(?:" + wikiSyntaxRules.join("|") + ")$"); var wikiSyntaxLogPattern = new RegExp("^[\\[r]" + _changesetId + "[-:]"); var wikiDetectTracLinkPattern = new RegExp("(?:" + wikiDetectTracLinkRules.join("|") + ")", "g"); TracWysiwyg.prototype._linkScheme = _linkScheme; TracWysiwyg.prototype._quotedString = _quotedString; TracWysiwyg.prototype._changesetId = _changesetId; TracWysiwyg.prototype._tracLink = _tracLink; TracWysiwyg.prototype._wikiPageName = _wikiPageName; TracWysiwyg.prototype.wikiInlineRules = wikiInlineRules; TracWysiwyg.prototype.wikiToDomInlineRules = wikiToDomInlineRules; TracWysiwyg.prototype.xmlNamePattern = new RegExp("^" + _xmlName + "$"); TracWysiwyg.prototype.domToWikiInlinePattern = domToWikiInlinePattern; TracWysiwyg.prototype.wikiRulesPattern = wikiRulesPattern; TracWysiwyg.prototype.wikiSyntaxPattern = wikiSyntaxPattern; TracWysiwyg.prototype.wikiSyntaxLogPattern = wikiSyntaxLogPattern; TracWysiwyg.prototype.wikiDetectTracLinkPattern = wikiDetectTracLinkPattern; })(); TracWysiwyg.prototype.normalizeTracLink = function(link) { link = this.convertWikiSyntax(link); if (/^[\/.#]/.test(link)) { link = encode(link); } if (!/^[\w.+-]+:/.test(link)) { link = "wiki:" + link; } if (/^wiki:[^\"\']/.test(link) && /\s/.test(link)) { if (link.indexOf('"') === -1) { link = 'wiki:"' + link + '"'; } else if (link.indexOf("'") === -1) { link = "wiki:'" + link + "'"; } else { link = 'wiki:"' + link.replace(/"/g, "%22") + '"'; } } return link; }; TracWysiwyg.prototype.convertWikiSyntax = function(link) { var match = this.wikiSyntaxPattern.exec(link); if (match) { switch (match[0].charCodeAt(0)) { case 0x7b: // "{" link = "report:" + link.slice(1, -1); break; case 0x5b: // "[" link = (this.wikiSyntaxLogPattern.test(link) ? "log:@" : "changeset:") + link.slice(1, -1); break; case 0x23: // # link = "ticket:" + link.substring(1); break; case 0x72: // r link = (this.wikiSyntaxLogPattern.test(link) ? "log:@" : "changeset:") + link.substring(1); break; } } return link; }; TracWysiwyg.prototype.isInlineNode = function(node) { if (node) { switch (node.nodeType) { case 1: return (node.tagName.toLowerCase() in this.wikiInlineTags); case 3: return true; } } return false; }; (function() { var blocks = { p: true, blockquote: true, div: true, li: true, ul: true, ol: true, dl: true, dt: true, dd: true, h1: true, h2: true, h3: true, h4: true, h5: true, h6: true, table: true, thead: true, tbody: true, tr: true, td: true, th: true }; function generator(prop, blocks) { return function (node) { if (!node) { return false; } for ( ; ; ) { if (node[prop]) { return false; } node = node.parentNode; if (!node) { return true; } if (node.nodeType == 1 && node.tagName.toLowerCase() in blocks) { return true; } } return false; }; } TracWysiwyg.prototype.isLastChildInBlockNode = generator("nextSibling", blocks); TracWysiwyg.prototype.isFirstChildInBlockNode = generator("previousSibling", blocks); })(); TracWysiwyg.prototype.wikitextToFragment = function(wikitext, contentDocument, options) { options = options || {}; var escapeNewlines = !!options.escapeNewlines; var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var _linkScheme = this._linkScheme; var _quotedString = this._quotedString; var wikiInlineRulesCount = this.wikiInlineRules.length; var wikiToDomInlineRulesCount = this.wikiToDomInlineRules.length; var wikiRulesPattern = new RegExp(this.wikiRulesPattern.source, "g"); var self = this; var fragment = contentDocument.createDocumentFragment(); var holder = fragment; var lines = wikitext.split("\n"); var codeText = null; var currentHeader = null; var quoteDepth = []; var listDepth = []; var decorationStatus; var decorationStack; var inCodeBlock, inParagraph, inDefList, inTable, inTableRow, continueTableRow; inCodeBlock = inParagraph = inDefList = inTable = inTableRow = continueTableRow = false; function handleCodeBlock(line) { if (/^ *\{\{\{ *$/.test(line)) { inCodeBlock++; if (inCodeBlock == 1) { closeParagraph(); codeText = []; } else { codeText.push(line); } } else if (/^ *\}\}\} *$/.test(line)) { inCodeBlock--; if (inCodeBlock == 0) { var pre = contentDocument.createElement("pre"); pre.className = "wiki"; pre.appendChild(contentDocument.createTextNode(codeText.join( pre.addEventListener && !window.opera ? "\n" : "\n\r"))); holder.appendChild(pre); codeText = []; } else { codeText.push(line); } } else { codeText.push(line); } } function handleCitation(value) { var quote = /^(?: *>)+/.exec(value)[0]; var depth = quote.replace(/ +/g, "").length; if (depth > quoteDepth.length) { closeToFragment("blockquote"); while (depth > quoteDepth.length) { openQuote((new RegExp("^(?: *>){" + (quoteDepth.length + 1) + "}")).exec(quote)[0].length, true); } } else if (depth == quoteDepth.length) { // nothing to do } else { closeParagraph(); while (depth < quoteDepth.length) { closeQuote(); } } } function openQuote(length, citation) { var target = holder; if (target != fragment) { target = getSelfOrAncestor(target, "blockquote"); } var element = contentDocument.createElement("blockquote"); if (citation) { element.className = "citation"; } (target || fragment).appendChild(element); holder = element; quoteDepth.push(length); } function closeQuote() { var target = getSelfOrAncestor(holder, "blockquote"); holder = target.parentNode; quoteDepth.pop(); } function handleHeader(line) { var match = /^\s*(=+)[ \t\r\f\v]+.*?(?:#([^ \t\r\f\v]+))?[ \t\r\f\v]*$/.exec(line); if (!match) { return null; } closeToFragment(); var tag = "h" + match[1].length; var element = contentDocument.createElement(tag); if (match[2]) { element.id = match[2]; } fragment.appendChild(element); holder = element; return tag; } function closeHeader() { if (currentHeader) { var target = getSelfOrAncestor(holder, currentHeader); holder = target.parentNode; currentHeader = null; } } function handleInline(name) { if (name == "bolditalic") { if (decorationStatus.italic) { handleInline("italic"); handleInline("bold"); } else { handleInline("bold"); handleInline("italic"); } return; } var d = contentDocument; if (decorationStatus[name]) { var tagNames = []; for (var index = decorationStack.length - 1; index >= 0; index--) { var tagName = holder.tagName; holder = holder.parentNode; if (decorationStack[index] == name) { break; } tagNames.push(tagName); } decorationStack.splice(index, 1); decorationStatus[name] = false; while (tagNames.length > 0) { var element = d.createElement(tagNames.pop()); holder.appendChild(element); holder = element; } return; } var tagName; switch (name) { case "bold": tagName = "b"; break; case "italic": tagName = "i"; break; case "underline": tagName = "u"; break; case "strike": tagName = "del"; break; case "subscript": tagName = "sub"; break; case "superscript": tagName = "sup"; break; } if (holder == fragment) { openParagraph(); } element = d.createElement(tagName); holder.appendChild(element); holder = element; decorationStatus[name] = true; decorationStack.push(name); } function handleInlineCode(value, length) { var d = contentDocument; var element = d.createElement("tt"); value = value.slice(length, -length); if (value.length > 0) { element.appendChild(d.createTextNode(value)); holder.appendChild(element); } } function createAnchor(link, label) { var anchor = self.createAnchor(link, label); holder.appendChild(anchor); } function handleTracLinks(value) { var match = handleTracLinks.pattern.exec(value); if (match) { var link = match[1]; if (!/^(?:[\w.+-]+:|[\/.#].*)/.test(link)) { link = "wiki:" + link; } var text = (match[2] || match[1].replace(/^[\w.+-]+:/, "")).replace(/^(["'])(.*)\1$/g, "$2"); createAnchor(link, text); } else { holder.appendChild(contentDocument.createTextNode(value)); } } handleTracLinks.pattern = new RegExp("\\[" + "((?:" + _linkScheme + ":)?(?:" + _quotedString + "|[^\\]\\s]+))" + "(?:\\s+(.*))?\\]"); function handleTracWikiLink(value) { createAnchor(value, value); } function handleBracketLinks(value) { var d = contentDocument; var link = value.slice(1, -1); var anchor = self.createAnchor(link, link); var _holder = holder; _holder.appendChild(d.createTextNode("<")); _holder.appendChild(anchor); _holder.appendChild(d.createTextNode(">")); } function handleWikiPageName(name, label) { createAnchor("wiki:" + name, label || name); } function handleTracOtherLinks(value) { createAnchor(self.convertWikiSyntax(value), value); } function handleTracTicketLink(value) { if (!/^&/.test(value)) { handleTracOtherLinks(value); return true; } return false; } function handleWikiAnchor(text) { var match = /^\[=#([^ \t\r\f\v\]]+)(?:[ \t\r\f\v]+([^\]]*))?\]$/.exec(text); var d = contentDocument; var element = d.createElement("span"); element.className = "wikianchor"; element.id = match[1]; if (match[2]) { element.appendChild(self.wikitextToOnelinerFragment(match[2], d, self.options)); } holder.appendChild(element); } function handleList(value) { var match = /^(\s*)(?:([-*])|((?:([0-9]+)|([a-z])|([A-Z])|[ivxIVX]{1,5})))/.exec(value); var tag, className, depth, start; if (!match) { holder.appendChild(contentDocument.createTextNode(value)); return; } depth = match[1].length; if (match[2]) { tag = "ul"; } else if (match[3]) { tag = "ol"; switch (match[3]) { case "0": className = "arabiczero"; break; case "1": break; case "i": className = "lowerroman"; break; case "I": className = "upperroman"; break; default: if (match[4]) { start = parseInt(match[4], 10); } else if (match[5]) { className = "loweralpha"; } else if (match[6]) { className = "upperalpha"; } break; } } var last = listDepth.length - 1; if (depth > (last >= 0 ? listDepth[last] : -1)) { closeToFragment("li"); openList(tag, className, start, depth); } else { var container, list; if (listDepth.length > 1 && depth < listDepth[last]) { do { if (depth >= listDepth[last]) { break; } closeList(); last = listDepth.length - 1; } while (listDepth.length > 1); container = holder; } else { list = getSelfOrAncestor(holder, "li"); self.appendBogusLineBreak(list); container = list.parentNode; } if (tag != container.tagName.toLowerCase()) { holder = container.parentNode; listDepth.pop(); openList(tag, className, start, depth); } else { var tmp = contentDocument.createElement("li"); container.appendChild(tmp); holder = tmp; listDepth[last] = depth; } } } function openList(tag, className, start, depth) { var d = contentDocument; var h = holder; var container = d.createElement(tag); if (className) { container.className = className; } if (start) { container.setAttribute("start", start); } var list = d.createElement("li"); container.appendChild(list); var target; if (h == fragment) { target = fragment; } else { target = getSelfOrAncestor(h, "li"); target = target ? target.parentNode : h; } target.appendChild(container); holder = list; listDepth.push(depth); } function closeList() { var h = holder; var target = getSelfOrAncestor(h, "li"); if (target) { self.appendBogusLineBreak(target); holder = target.parentNode.parentNode; } else { holder = h.parentNode; } listDepth.pop(); } function handleDefinition(value) { var d = contentDocument; var h = holder; var dl = null; if (inDefList) { dl = getSelfOrAncestor(h, "dl"); } else { closeParagraph(); dl = d.createElement("dl"); fragment.appendChild(dl); inDefList = true; } var match = /^ +(.*?)\s*::/.exec(value); var dt = d.createElement("dt"); var oneliner = self.wikitextToOnelinerFragment(match[1], d, self.options); dt.appendChild(oneliner); dl.appendChild(dt); var dd = d.createElement("dd"); dl.appendChild(dd); holder = dd; } function closeDefList() { var element = getSelfOrAncestor(holder, "dl"); if (element) { holder = element.parentNode; } inDefList = false; } function handleIndent(value) { var depth = value.length; var last = quoteDepth.length - 1; if (depth > (last >= 0 ? quoteDepth[last] : 0)) { closeParagraph(); closeTable(); openQuote(depth, false); } else { while (quoteDepth.length > 0) { if (depth >= quoteDepth[last]) { break; } closeToFragment("blockquote"); closeQuote(); last = quoteDepth.length - 1; } quoteDepth[last] = depth; } } function openParagraph() { if (!inParagraph) { var element = contentDocument.createElement("p"); holder.appendChild(element); holder = element; inParagraph = true; } } function closeParagraph() { if (inParagraph) { var target = holder; if (target != fragment) { target = getSelfOrAncestor(target, "p"); self.appendBogusLineBreak(target); } holder = target.parentNode; inParagraph = false; } } function handleTableCell(action, colspan, header, align) { var d = contentDocument; var h, table, tbody; if (!inTable) { closeToFragment("blockquote"); h = holder; table = d.createElement("table"); table.className = "wiki"; tbody = d.createElement("tbody"); table.appendChild(tbody); h.appendChild(table); inTable = true; inTableRow = false; } else { h = holder; tbody = getSelfOrAncestor(h, "tbody"); } if (inTableRow) { var cell = getSelfOrAncestor(h, "td"); if (cell) { self.appendBogusLineBreak(cell); } } var row; switch (action) { case 1: row = d.createElement("tr"); tbody.appendChild(row); inTableRow = true; break; case 0: row = getSelfOrAncestor(h, "tr"); break; case -1: if (inTableRow) { var target = getSelfOrAncestor(h, "tr"); holder = target.parentNode; inTableRow = false; } return; } var cell = d.createElement(header ? "th" : "td"); if (colspan > 1) { cell.setAttribute("colSpan", colspan); } switch (align) { case -1: align = "left"; break; case 0: align = "center"; break; case 1: align = "right"; break; default: align = null; break; } if (align !== null) { cell.setAttribute("align", align); } row.appendChild(cell); holder = cell; decorationStatus = {}; } function closeTable() { if (inTable) { var target = getSelfOrAncestor(holder, "table"); holder = target.parentNode; inTable = inTableRow = false; } } function closeToFragment(stopTag) { var element = holder; var _fragment = fragment; stopTag = stopTag ? stopTag.toLowerCase() : null; while (element != _fragment) { var tag = element.tagName.toLowerCase(); if (tag == stopTag) { holder = element; return; } var method; switch (tag) { case "p": method = closeParagraph; break; case "li": case "ul": case "ol": method = closeList; break; case "dd": method = closeDefList; break; case "blockquote": method = closeQuote; break; case "td": case "tr": case "tbody": case "table": method = closeTable; break; default: break; } if (method) { method(); element = holder; } else { element = element.parentNode; } } holder = _fragment; } function getMatchNumber(match) { var length = match.length; for (var i = 1; i < length; i++) { if (match[i]) { if (i <= wikiInlineRulesCount) { return i; } if (i <= wikiToDomInlineRulesCount) { return i - wikiInlineRulesCount + 1000; } return wikiToDomInlineRulesCount - i; } } return null; } for (var indexLines = 0; indexLines < lines.length; indexLines++) { var line = lines[indexLines].replace(/\r$/, ""); if (inCodeBlock || /^ *\{\{\{ *$/.test(line)) { handleCodeBlock(line); continue; } if (/^----/.test(line)) { closeToFragment(); fragment.appendChild(contentDocument.createElement("hr")); continue; } if (line.length == 0) { closeToFragment(); continue; } line = line.replace(/\t/g, " "); line = line.replace(/\u00a0/g, " "); wikiRulesPattern.lastIndex = 0; var prevIndex = wikiRulesPattern.lastIndex; decorationStatus = {}; decorationStack = []; for ( ; ; ) { var match = wikiRulesPattern.exec(line); var matchNumber = null; var text = null; if (match) { matchNumber = getMatchNumber(match); if (prevIndex < match.index) { text = line.substring(prevIndex, match.index); } } else { text = line.substring(prevIndex); } if ((prevIndex == 0 && text || match && match.index == 0 && matchNumber > 0) && (!inParagraph || quoteDepth.length > 0) && (!inDefList || !/^ /.test(line))) { closeToFragment(); } if (text || match && matchNumber > 0) { if (inParagraph && (prevIndex == 0 || quoteDepth.length > 0)) { if (escapeNewlines) { if (quoteDepth.length == 0) { holder.appendChild(contentDocument.createElement("br")); } } else { text = text ? (" " + text) : " "; } } if (!inTable && quoteDepth.length > 0 || holder == fragment) { if (!inParagraph) { openParagraph(); } } if (text) { holder.appendChild(contentDocument.createTextNode(text)); } } if (!match) { break; } prevIndex = wikiRulesPattern.lastIndex; var matchText = match[0]; if (!/^!/.test(matchText)) { // start '!' switch (matchNumber) { case 1: // bolditalic handleInline("bolditalic"); continue; case 2: // bold handleInline("bold"); continue; case 3: // italic handleInline("italic"); continue; case 4: // underline handleInline("underline"); continue; case 5: // strike handleInline("strike"); continue; case 6: // subscript handleInline("subscript"); continue; case 7: // superscript handleInline("superscript"); continue; case 8: // code block handleInlineCode(matchText, 3); continue; case 9: // inline handleInlineCode(matchText, 1); continue; case 10: // ticket if (handleTracTicketLink(matchText)) { continue; } break; case 11: // report case 12: // changeset case 13: // log handleTracOtherLinks(matchText); continue; case 14: // wiki:TracLinks handleTracWikiLink(matchText); continue; case 15: // [wiki:TracLinks label] handleTracLinks(matchText); continue; case 16: // [[macro]] break; case 17: // WikiPageName handleWikiPageName(matchText); continue; case 18: // ["internal free link"] handleWikiPageName(matchText.slice(1, -1), matchText.slice(2, -2)); continue; case 19: // handleBracketLinks(matchText); continue; case 20: // [=#anchor label] handleWikiAnchor(matchText); continue; case 1001: // escaping double escape break; case -1: // citation if (escapeNewlines && inParagraph) { holder.appendChild(contentDocument.createElement("br")); } handleCitation(matchText); if (escapeNewlines) { openParagraph(); } continue; case -2: // header currentHeader = handleHeader(matchText); if (currentHeader) { line = line.replace(/(?:[ \t\r\f\v]+#[^ \t\r\f\v]+)?[ \t\r\f\v]*$/, ""); var m = /^\s*(=+)[ \t\r\f\v]+/.exec(line); if (line.slice(-m[1].length) == m[1]) { line = line.slice(0, -m[1].length).replace(/[ \t\r\f\v]+$/, ""); } wikiRulesPattern.lastIndex = prevIndex = m[0].length; continue; } break; case -3: // list handleList(matchText) continue; case -4: // definition handleDefinition(matchText); continue; case -5: // leading space if (listDepth.length == 0 && !inDefList) { handleIndent(matchText); continue; } if (!this.isInlineNode(holder.lastChild)) { continue; } matchText = matchText.replace(/^\s+/, " "); break; case -6: // closing table row if (inTable) { if (matchText.slice(-1) != "\\") { handleTableCell(-1); } else { continueTableRow = true; } continue; } break; case -7: // cell if (quoteDepth.length > 0 && match.index == 0) { closeToFragment(); } var align = null; for ( ; ; ) { // lookahead next double pipes var m = wikiRulesPattern.exec(line); switch (m ? getMatchNumber(m) : 0) { case 0: case -6: case -7: var end = m ? m.index : line.length; if (prevIndex < end) { var tmp = line.substring(prevIndex, end); var m = /^([ \t\r\n\f\v]*)(.*?)([ \t\r\n\f\v]*)$/.exec(tmp); if (m) { if (m[1].length == tmp.length) { align = null; } else if ((m[1].length == 0) === (m[3].length == 0)) { align = m[1].length >= 2 && m[3].length >= 2 ? 0 : null; } else { align = m[1].length == 0 ? -1 : 1; } tmp = m[2]; } line = line.substring(0, prevIndex) + tmp + line.substring(end); } break; default: continue; } break; } wikiRulesPattern.lastIndex = prevIndex; handleTableCell(inTableRow ? 0 : 1, matchText.replace(/^=|=$/g, '').length / 2, matchText.slice(-1) == "=", align); continue; } } if (matchText) { if (listDepth.length == 0 && !currentHeader && !inDefList && !inTable) { openParagraph(); } var tmp; if (matchNumber == 16) { tmp = /^!?\[\[br\]\]$/i.test(matchText) ? (matchText.charCodeAt(0) == 0x21 ? contentDocument.createTextNode(matchText.substring(1)) : contentDocument.createElement("br")) : contentDocument.createTextNode(matchText); } else { tmp = contentDocument.createTextNode(/^!/.test(matchText) ? matchText.substring(1) : matchText); } holder.appendChild(tmp); } } if (currentHeader) { closeHeader(); } if (inTable) { if (continueTableRow) { continueTableRow = false; } else { handleTableCell(-1); } } } closeToFragment(); return fragment; }; TracWysiwyg.prototype.wikitextToOnelinerFragment = function(wikitext, contentDocument, options) { var source = this.wikitextToFragment(wikitext, contentDocument, options); var fragment = contentDocument.createDocumentFragment(); this.collectChildNodes(fragment, source.firstChild); return fragment; }; TracWysiwyg.prototype.wikiOpenTokens = { "h1": "= ", "h2": "== ", "h3": "=== ", "h4": "==== ", "h5": "===== ", "h6": "====== ", "b": "'''", "strong": "'''", "i": "''", "em": "''", "u": "__", "del": "~~", "strike": "~~", "sub": ",,", "sup": "^", "hr": "----\n", "dl": true, "dt": " ", "dd": " ", "table": true, "tbody": true }; TracWysiwyg.prototype.wikiCloseTokens = { "#text": true, "a": true, "tt": true, "h1": " =", "h2": " ==", "h3": " ===", "h4": " ====", "h5": " =====", "h6": " ======", "b": "'''", "strong": "'''", "i": "''", "em": "''", "u": "__", "del": "~~", "strike": "~~", "sub": ",,", "sup": "^", "br": true, "hr": true, "dl": "\n", "dt": "::", "dd": "\n", "tbody": true, "tr": "||\n", "td": true, "th": true }; TracWysiwyg.prototype.wikiBlockTags = { "h1": true, "h2": true, "h3": true, "h4": true, "h5": true, "h6": true, "table": true, "dl": true, "hr": true }; TracWysiwyg.prototype.wikiInlineTags = { "a": true, "tt": true, "b": true, "strong": true, "i": true, "em": true, "u": true, "del": true, "strike": true, "sub": true, "sup": true, "br": true, "span": true }; TracWysiwyg.prototype.domToWikitext = function(root, options) { options = options || {}; var formatCodeBlock = !!options.formatCodeBlock; var escapeNewlines = !!options.escapeNewlines; var self = this; var getTextContent = TracWysiwyg.getTextContent; var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var wikiOpenTokens = this.wikiOpenTokens; var wikiCloseTokens = this.wikiCloseTokens; var wikiInlineTags = this.wikiInlineTags; var wikiBlockTags = this.wikiBlockTags; var xmlNamePattern = this.xmlNamePattern; var domToWikiInlinePattern = this.domToWikiInlinePattern; var wikiSyntaxPattern = this.wikiSyntaxPattern; var tracLinkPattern = new RegExp("^" + this._tracLink + "$"); var wikiPageNamePattern = new RegExp("^" + this._wikiPageName + "$"); var decorationTokenPattern = /^(?:'''|''|__|\^|,,)$/; var texts = []; var stack = []; var last = root; var listDepth = 0; var quoteDepth = 0; var quoteCitation = false; var inCodeBlock = false; var skipNode = null; var openBracket = false; function escapeText(s) { var match = /^!?\[\[(.+)\]\]$/.exec(s); if (match) { return match[1].toLowerCase() != "br" ? s : "!" + s; } if (/^&#\d+/.test(s)) { return s; } return "!" + s; } function isTailEscape() { var t = texts; var length = t.length; return length > 0 ? /!$/.test(t[length - 1]) : false; } function tokenFromSpan(node) { if (node.className == "underline") { return wikiOpenTokens["u"]; } var style = node.style; if (style.fontWeight == "bold") { return wikiOpenTokens["b"]; } if (style.fontStyle == "italic") { return wikiOpenTokens["i"]; } switch (style.textDecoration) { case "underline": return wikiOpenTokens["u"]; case "line-through": return wikiOpenTokens["del"]; } switch (style.verticalAlign) { case "sub": return wikiOpenTokens["sub"]; case "sup": return wikiOpenTokens["sup"]; } return undefined; } function nodeDecorations(node) { var _wikiOpenTokens = wikiOpenTokens; var _decorationTokenPattern = decorationTokenPattern; var hash = {}; for ( ; ; ) { var childNodes = node.childNodes; if (!childNodes || childNodes.length != 1) { break; } var child = childNodes[0]; if (child.nodeType != 1) { break; } var token = _wikiOpenTokens[child.tagName.toLowerCase()]; if (_decorationTokenPattern.test(token)) { hash[token] = true; } node = child; } return hash; } function pushTextWithDecorations(text, node, traclink) { var _texts = texts; var _decorationTokenPattern = decorationTokenPattern; var decorationsHash = nodeDecorations(node); var decorations = []; var cancelDecorations = []; while (_texts.length > 0) { var token = _texts[_texts.length - 1]; if (_decorationTokenPattern.test(token)) { if (decorationsHash[token]) { delete decorationsHash[token]; cancelDecorations.push(_texts.pop()); continue; } if ((token == "'''" || token == "''") && _texts.length > 1) { var moreToken = _texts[_texts.length - 2]; if (_decorationTokenPattern.test(moreToken) && token + moreToken == "'''''" && decorationsHash[moreToken]) { delete decorationsHash[moreToken]; cancelDecorations.push(moreToken); _texts[_texts.length - 2] = _texts[_texts.length - 1]; _texts.pop(); } } } break; } for (var token in decorationsHash) { decorations.push(token); } decorations.sort(); if (decorations.length > 0) { _texts.push.apply(_texts, decorations); } if (traclink) { if (_texts.length > 0 && /[\w.+-]$/.test(_texts[_texts.length - 1])) { _texts.push(traclink); } else { text = new String(text); text["tracwysiwyg-traclink"] = traclink; _texts.push(text); } } else { _texts.push(text); } if (decorations.length > 0) { decorations.reverse(); _texts.push.apply(_texts, decorations); } if (cancelDecorations.length > 0) { cancelDecorations.reverse(); _texts.push.apply(_texts, cancelDecorations); } } function pushToken(token) { var _texts = texts; var _decorationTokenPattern = decorationTokenPattern; var length = _texts.length; if (length == 0 || !_decorationTokenPattern.test(token)) { _texts.push(token); return; } var last = _texts[length - 1]; if (!_decorationTokenPattern.test(last)) { _texts.push(token); return; } if (last == token) { _texts.pop(); return; } if (length < 2 || last + token != "'''''") { _texts.push(token); return; } if (_texts[length - 2] == token) { _texts[length - 2] = _texts[length - 1]; _texts.pop(); } else { _texts.push(token); } } function tracLinkText(link, label) { if (!/\]/.test(label) && !/^[\"\']/.test(label)) { return "[" + link + " " + label + "]"; } if (!/\"/.test(label)) { return "[" + link + ' "' + label + '"]'; } if (!/\'/.test(label)) { return "[" + link + " '" + label + "']"; } return "[" + link + ' "' + label.replace(/"+/g, "") + '"]'; } function pushAnchor(node, bracket) { var link = node.getAttribute("data-tracwysiwyg-link"); var autolink = node.getAttribute("data-tracwysiwyg-autolink"); var attrs; if (link === null) { attrs = TracWysiwyg.unserializeFromHref(node.href); link = attrs["data-tracwysiwyg-link"]; autolink = attrs["data-tracwysiwyg-autolink"]; } link = (link || node.href).replace(/^\s+|\s+$/g, ""); var label = getTextContent(node).replace(/^\s+|\s+$/g, ""); if (!label) { return; } var text = null; var traclink = null; if (autolink == "true") { if (wikiPageNamePattern.test(label)) { text = label; link = "wiki:" + label; traclink = "[wiki:" + label + "]"; } else if (wikiSyntaxPattern.test(label)) { text = label; link = self.convertWikiSyntax(label); } else if (tracLinkPattern.test(label)) { text = link = label; } } else { if (link == label) { if (bracket) { text = label; } else if (tracLinkPattern.test(label)) { text = label; } } } if (!text) { var match = /^([\w.+-]+):(@?(.*))$/.exec(link); if (match) { if (label == match[2]) { if (match[1] == "wiki" && wikiPageNamePattern.test(match[2])) { text = match[2]; traclink = "[wiki:" + text + "]"; } else { text = "[" + link + "]"; } } else { var usingLabel = false; switch (match[1]) { case "changeset": usingLabel = label == "[" + match[2] + "]" || /^\d+$/.test(match[2]) && label == "r" + match[2]; break; case "log": usingLabel = label == "[" + match[3] + "]" || label == "r" + match[3]; break; case "report": usingLabel = label == "{" + match[2] + "}"; break; case "ticket": usingLabel = label == "#" + match[2]; break; } if (usingLabel) { text = label; } } } } if (isTailEscape()) { texts.push(" "); } if (text === null) { text = tracLinkText(link, label); } if (!traclink && /^[\w.+-]/.test(text)) { traclink = tracLinkText(link, label); } pushTextWithDecorations(text, node, traclink); } function string(source, times) { var value = (1 << times) - 1; if (value <= 0) { return ""; } else { return value.toString(2).replace(/1/g, source); } } function open(name, node) { if (skipNode !== null) { return; } var _texts = texts; var token = wikiOpenTokens[name]; if (token !== undefined) { if (name in wikiBlockTags && self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } if (token !== true) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } openBracket = false; } else { switch (name) { case "#text": var value = node.nodeValue; if (value) { if (!inCodeBlock) { if (value && !self.isInlineNode(node.previousSibling || node.parentNode)) { value = value.replace(/^[ \t\r\n\f\v]+/g, ""); } if (value && !self.isInlineNode(node.nextSibling || node.parentNode)) { value = value.replace(/[ \t\r\n\f\v]+$/g, ""); } value = value.replace(/\r?\n/g, " "); if (!formatCodeBlock) { value = value.replace(domToWikiInlinePattern, escapeText); } openBracket = /<$/.test(value); } if (value) { var length = _texts.length; var prev = length > 0 ? _texts[length - 1] : null; if (prev && prev["tracwysiwyg-traclink"] && tracLinkPattern.test(prev + value.substring(0, 1))) { _texts[length - 1] = prev["tracwysiwyg-traclink"]; } _texts.push(value); } } break; case "p": if (quoteDepth > 0) { _texts.push(string(quoteCitation ? "> " : " ", quoteDepth)); } else if (!/[^ \t\r\n\f\v]/.test(getTextContent(node))) { skipNode = node; } break; case "a": skipNode = node; var bracket = false; if (openBracket) { var nextSibling = node.nextSibling; bracket = nextSibling && nextSibling.nodeType == 3 && /^>/.test(nextSibling.nodeValue); openBracket = false; } pushAnchor(node, bracket); break; case "li": _texts.push(" " + string(" ", listDepth - 1)); var container = node.parentNode; if ((container.tagName || "").toLowerCase() == "ol") { var start = container.getAttribute("start") || ""; if (start != "1" && /^(?:[0-9]+|[a-zA-Z]|[ivxIVX]{1,5})$/.test(start)) { _texts.push(start, ". "); } else { switch (container.className) { case "arabiczero": _texts.push("0. "); break; case "lowerroman": _texts.push("i. "); break; case "upperroman": _texts.push("I. "); break; case "loweralpha": _texts.push("a. "); break; case "upperalpha": _texts.push("A. "); break; default: _texts.push("1. "); break; } } } else { _texts.push("* "); } break; case "ul": case "ol": if (listDepth == 0) { if (self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } } else if (listDepth > 0) { if (node.parentNode.tagName.toLowerCase() == "li") { _texts.push("\n"); } } listDepth++; break; case "br": if (!self.isBogusLineBreak(node)) { var value = null; if (inCodeBlock) { value = "\n"; } else if (formatCodeBlock) { switch (((node.parentNode || {}).tagName || "").toLowerCase()) { case "li": value = "\n " + string(" ", listDepth); break; case "p": case "blockquote": value = "\n"; if (quoteDepth > 0) { value += string(quoteCitation ? "> " : " ", quoteDepth); } break; case "dd": value = "\n "; break; case "dt": case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": value = " "; break; default: value = "\n"; break; } } else { if (escapeNewlines && getSelfOrAncestor(node, /^(?:p|blockquote)$/)) { value = quoteDepth > 0 ? "\n" + string(quoteCitation ? "> " : " ", quoteDepth) : "\n"; } if (!value) { value = "[[BR]]"; var length = _texts.length; if (length > 0) { var lastText = _texts[length - 1]; var tmp = lastText + "[[BR]]"; var _pattern = domToWikiInlinePattern; _pattern.lastIndex = 0; var lastMatch, match; while (match = _pattern.exec(tmp)) { lastMatch = match; } if (lastMatch && lastMatch.index < lastText.length && lastMatch.index + lastMatch[0].length > lastText.length) { value = " [[BR]]"; } } } } _texts.push(value); } break; case "pre": _texts.push( /^(?:li|dd)$/i.test(node.parentNode.tagName) || self.isInlineNode(node.previousSibling) ? "\n{{{\n" : "{{{\n"); inCodeBlock = true; break; case "blockquote": if (self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } quoteDepth++; if (quoteDepth == 1) { quoteCitation = (node.className == "citation"); } break; case "th": var header = true; case "td": skipNode = node; var colspan = node.getAttribute("colSpan"); colspan = colspan ? parseInt(colspan, 10) : 0; _texts.push(colspan > 1 ? string("||", colspan) : "||"); if (header) { _texts.push("="); } var align = node.style.textAlign; if (!align) { align = (node.getAttribute("align") || "").toLowerCase(); } var text = self.domToWikitext(node, self.options).replace(/ *\n/g, "[[BR]]").replace(/^ +| +$/g, ""); if (text) { switch (align) { case "left": _texts.push(text, " "); break; case "center": _texts.push(" ", text, " "); break; case "right": _texts.push(" ", text); break; default: _texts.push(" ", text, " "); break; } } else { _texts.push(" "); } if (header) { _texts.push("="); } break; case "tr": if (quoteDepth > 0) { _texts.push(string(quoteCitation ? ">" : " ", quoteDepth)); } break; case "tt": skipNode = node; var value = getTextContent(node); var text; if (value) { if (isTailEscape()) { _texts.push(" "); } if (!/`/.test(value)) { text = "`" + value + "`"; } else if (!/\{\{\{|\}\}\}/.test(value)) { text = "{{{" + value + "}}}"; } else { text = value.replace(/[^`]+|`+/g, function(m) { return m.charCodeAt(0) != 0x60 ? "`" + m + "`" : "{{{" + m + "}}}"; }); } pushTextWithDecorations(text, node); } break; case "span": if (node.className == "wikianchor" && xmlNamePattern.test(node.id || "")) { skipNode = node; var text = self.domToWikitext(node, self.options).replace(/^ +| +$|\]/g, ""); _texts.push("[=#", node.id, text ? " " + text + "]" : "]"); } else { var token = tokenFromSpan(node); if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } } break; case "script": case "style": skipNode = node; break; } if (name != "#text") { openBracket = false; } } } function close(name, node) { if (skipNode !== null) { if (skipNode == node) { skipNode = null; } return; } var _texts = texts; var token = wikiCloseTokens[name]; if (token === true) { // nothing to do } else if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } else { switch (name) { case "p": _texts.push(quoteDepth == 0 ? "\n\n" : "\n"); break; case "li": if (node.getElementsByTagName("li").length == 0) { _texts.push("\n"); } break; case "ul": case "ol": listDepth--; if (listDepth == 0) { _texts.push("\n"); } break; case "pre": var text; var parentNode = node.parentNode; if (parentNode && /^(?:li|dd)$/i.test(parentNode.tagName)) { var nextSibling = node.nextSibling; if (!nextSibling) { text = "\n}}}"; } else if (nextSibling.nodeType != 1) { text = "\n}}}\n"; } else if (nextSibling.tagName.toLowerCase() == "pre") { text = "\n}}}"; } else { text = "\n}}}\n"; } if (text.slice(-1) == "\n") { text += listDepth > 0 ? " " + string(" ", listDepth) : " "; } } else { text = "\n}}}\n"; } _texts.push(text); inCodeBlock = false; break; case "blockquote": quoteDepth--; if (quoteDepth == 0) { _texts.push("\n"); } break; case "span": var token = tokenFromSpan(node); if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } _texts.push(token); } break; case "table": if (quoteDepth == 0) { _texts.push("\n"); } break; } } if (/^h[1-6]$/.test(name)) { if (xmlNamePattern.test(node.id || "")) { _texts.push(" #", node.id); } _texts.push("\n"); } } function iterator(node) { var name = null; switch (node && node.nodeType) { case 1: // element name = node.tagName.toLowerCase(); break; case 3: // text name = "#text"; break; } if (node && last == node.parentNode) { // down // nothing to do } else if (node && last == node.previousSibling) { // forward close(stack.pop(), last); } else { // up, forward var tmp = last; var nodeParent = node ? node.parentNode : root; for ( ; ; ) { var parent = tmp.parentNode; if (parent == node) { break; } close(stack.pop(), tmp); if (parent == nodeParent || !parent) { if (!node) { return; } break; } tmp = parent; } } open(name, node); stack.push(name); last = node; } this.treeWalk(root, iterator); return texts.join("").replace(/^(?: *\n)+|(?: *\n)+$/g, ""); }; if (window.getSelection) { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { var wikiInlineTags = this.wikiInlineTags; var last = element.lastChild; for ( ; ; ) { if (!last) { break; } if (last.nodeType != 1) { return; } var name = last.tagName.toLowerCase(); if (name == "br") { break; } if (!(name in wikiInlineTags)) { return; } last = last.lastChild || last.previousSibling; } var br = this.contentDocument.createElement("br"); element.appendChild(br); }; TracWysiwyg.prototype.isBogusLineBreak = TracWysiwyg.prototype.isLastChildInBlockNode; TracWysiwyg.prototype.insertParagraphOnEnter = function(event) { var range = this.getSelectionRange(); var node = range.endContainer; var header = null; if (node && node.nodeType == 3 && range.endOffset == node.nodeValue.length) { var nextSibling = node.nextSibling; if (!nextSibling || nextSibling.tagName.toLowerCase() == "br") { while (node) { if (node.nodeType == 1 && /^h[1-6]$/i.exec(node.tagName)) { header = node; break; } node = node.parentNode; } if (header) { var parent = header.parentNode; var childNodes = parent.childNodes; var length = childNodes.length; for (var offset = 0; offset < length; offset++) { if (childNodes[offset] == header) { offset++; break; } } this.selectRange(parent, offset, parent, offset); this.insertHTML('


'); TracWysiwyg.stopEvent(event); } } } }; TracWysiwyg.prototype.tableHTML = function(id, row, col) { var html = this._tableHTML(row, col); return html.replace(/<\/td>/g, '
').replace(//, ''); }; TracWysiwyg.prototype.insertTableCell = function(row, index) { var cell = row.insertCell(index); this.appendBogusLineBreak(cell); return cell; }; TracWysiwyg.prototype.getFocusNode = function() { return this.contentWindow.getSelection().focusNode; }; if (window.opera) { TracWysiwyg.prototype.insertLineBreak = function() { this.execCommand("inserthtml", "
"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; } else if (window.getSelection().setBaseAndExtent) { // Safari 2+ TracWysiwyg.prototype.insertLineBreak = function() { this.execCommand("insertlinebreak"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = function(event) { this.insertLineBreak(); TracWysiwyg.stopEvent(event); }; } else { // Firefox 2+ TracWysiwyg.prototype.insertLineBreak = function() { var d = this.contentDocument; var event = d.createEvent("KeyboardEvent"); event.initKeyEvent("keypress", true, true, null, false, false, true, false, 0x000d, 0); d.body.dispatchEvent(event); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; } if (window.getSelection().removeAllRanges) { TracWysiwyg.prototype.selectNode = function(node) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.selectNode(node); selection.addRange(range); }; TracWysiwyg.prototype.selectNodeContents = function(node) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.selectNodeContents(node); selection.addRange(range); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.setStart(start, startOffset); range.setEnd(end, endOffset); selection.addRange(range); }; TracWysiwyg.prototype.getNativeSelectionRange = function() { var selection = this.contentWindow.getSelection(); return selection.rangeCount > 0 ? selection.getRangeAt(0) : null; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { if (arg.start || arg.end) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange() || this.contentDocument.createRange(); selection.removeAllRanges(); if (arg.start) { range.setStartBefore(arg.start); } if (arg.end) { range.setEndAfter(arg.end); } selection.addRange(range); } }; TracWysiwyg.prototype.insertHTML = function(html) { this.execCommand("inserthtml", html); }; } else { // Safari 2 TracWysiwyg.prototype.selectNode = function(node) { var selection = this.contentWindow.getSelection(); var range = this.contentDocument.createRange(); range.selectNode(node); selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); range.detach(); }; TracWysiwyg.prototype.selectNodeContents = function(node) { this.selectRange(node, 0, node, node.childNodes.length); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var selection = this.contentWindow.getSelection(); selection.setBaseAndExtent(start, startOffset, end, endOffset); }; TracWysiwyg.prototype.getNativeSelectionRange = function() { var selection = this.contentWindow.getSelection(); if (selection.anchorNode) { var range = this.contentDocument.createRange(); range.setStart(selection.baseNode, selection.baseOffset); range.setEnd(selection.extentNode, selection.extentOffset); if (range.collapsed && !selection.isCollapsed) { range.setStart(selection.extentNode, selection.extentOffset); range.setEnd(selection.baseNode, selection.baseOffset); } return range; } return null; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { if (arg.start || arg.end) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange(); if (arg.start) { range.setStartBefore(arg.start); } if (arg.end) { range.setEndAfter(arg.end); } selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); range.detach(); } }; TracWysiwyg.prototype.insertHTML = function(html) { var range = this.getNativeSelectionRange(); if (range) { var d = this.contentDocument; var tmp = d.createRange(); tmp.setStart(d.body, 0); tmp.setEnd(d.body, 0); var fragment = tmp.createContextualFragment(html); range.deleteContents(); range.insertNode(fragment); range.detach(); tmp.detach(); } }; } TracWysiwyg.prototype.getSelectionRange = TracWysiwyg.prototype.getNativeSelectionRange; TracWysiwyg.prototype.getSelectionText = function() { var range = this.getNativeSelectionRange(); return range ? range.toString() : null; }; TracWysiwyg.prototype.getSelectionHTML = function() { var fragment = this.getSelectionFragment(); var anonymous = this.contentDocument.createElement("div"); anonymous.appendChild(fragment); return anonymous.innerHTML; }; TracWysiwyg.prototype.getSelectionFragment = function() { var range = this.getNativeSelectionRange(); return range ? range.cloneContents() : this.contentDocument.createDocumentFragment(); }; TracWysiwyg.prototype.getSelectionPosition = function() { var range = this.getNativeSelectionRange(); var position = { start: null, end: null }; if (range) { position.start = range.startContainer; position.end = range.endContainer; } return position; }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange(); if (!range) { return false; } var ancestor = range.commonAncestorContainer; if (!ancestor) { return false; } if (TracWysiwyg.getSelfOrAncestor(ancestor, name)) { return true; } if (ancestor.nodeType != 1) { return false; } var elements = ancestor.getElementsByTagName(name); var length = elements.length; for (var i = 0; i < length; i++) { if (selection.containsNode(elements[i], true)) { return true; } } return false; }; } else if (document.selection) { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { }; TracWysiwyg.prototype.isBogusLineBreak = function(node) { return false }; TracWysiwyg.prototype.insertParagraphOnEnter = null; TracWysiwyg.prototype.insertLineBreak = function() { this.insertHTML("
"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; TracWysiwyg.prototype.tableHTML = function(id, row, col) { var html = this._tableHTML(row, col); return html.replace(//, ''); }; TracWysiwyg.prototype.insertTableCell = function(row, index) { return row.insertCell(index); }; TracWysiwyg.prototype.getFocusNode = function() { this.contentWindow.focus(); var d = this.contentDocument; var range = d.selection.createRange(); var node = range.item ? range.item(0) : range.parentElement(); return node.ownerDocument == d ? node : null; }; TracWysiwyg.prototype.selectNode = function(node) { var d = this.contentDocument; var body = d.body; var range; d.selection.empty(); try { range = body.createControlRange(); range.addElement(node); } catch (e) { range = body.createTextRange(); range.moveToElementText(node); } range.select(); }; TracWysiwyg.prototype.selectNodeContents = function(node) { var d = this.contentDocument; d.selection.empty(); var range = d.body.createTextRange(); range.moveToElementText(node); range.select(); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var d = this.contentDocument; var body = d.body; d.selection.empty(); var range = endPoint(start, startOffset); if (start != end || startOffset != endOffset) { range.setEndPoint("EndToEnd", endPoint(end, endOffset)); } range.select(); function endPoint(node, offset) { var range; if (node.nodeType == 1) { var childNodes = node.childNodes; if (offset >= childNodes.length) { range = body.createTextRange(); range.moveToElementText(node); range.collapse(false); return range; } node = childNodes[offset]; if (node.nodeType == 1) { range = body.createTextRange(); range.moveToElementText(node); range.collapse(true); switch (node.tagName.toLowerCase()) { case "table": range.move("character", -1); break; } return range; } return endPoint(node, 0); } if (node.nodeType != 3) { throw "selectRange: nodeType != @".replace(/@/, node.nodeType); } range = body.createTextRange(); var element = node.previousSibling; while (element) { var nodeType = element.nodeType; if (nodeType == 1) { range.moveToElementText(element); range.collapse(false); break; } if (nodeType == 3) { offset += element.nodeValue.length; } element = element.previousSibling; } if (!element) { range.moveToElementText(node.parentNode); range.collapse(true); } if (offset != 0) { range.move("character", offset); } return range; } }; TracWysiwyg.prototype.getSelectionRange = function() { var body = this.contentDocument.body; var pseudo = {}; var start = this.getNativeSelectionRange(); if (start.item) { var element = start.item(0); var parent = element.parentNode; var childNodes = parent.childNodes; var length = childNodes.length; for (var i = 0; i < length; i++) { if (childNodes[i] == element) { pseudo.startOffset = i; pseudo.endOffset = i + 1; break; } } pseudo.collapsed = false; pseudo.startContainer = pseudo.endContainer = parent; return pseudo; } var end = start.duplicate(); pseudo.collapsed = start.compareEndPoints("StartToEnd", end) == 0; start.collapse(true); end.collapse(false); function nextElement(range) { var parent = range.parentElement(); var childNodes = parent.childNodes; var length = childNodes.length; for (var i = 0; i < length; i++) { var node = childNodes[i]; if (node.nodeType == 1) { var tmp = body.createTextRange(); tmp.moveToElementText(node); if (range.compareEndPoints("EndToStart", tmp) <= 0) { return node; } } } return null; } function nodeOffset(range, parent, element, index, length) { var tmp = body.createTextRange(); tmp.moveToElementText(element || parent); tmp.collapse(!!element); tmp.move("character", -index); if (!element) { length++; } for ( ; length >= 0; length--) { if (tmp.compareEndPoints("EndToStart", range) == 0) { return length; } tmp.move("character", -1); } return null; } function setContainerOffset(range, containerKey, offsetKey) { var parent = range.parentElement(); var element = nextElement(range); var index = 0; var node = element ? element.previousSibling : parent.lastChild; var offset, length; while (node && node.nodeType == 3) { length = node.nodeValue.length; offset = nodeOffset(range, parent, element, index, length); if (offset !== null) { pseudo[containerKey] = node; pseudo[offsetKey] = offset; return; } index += length; node = node.previousSibling; } var childNodes = parent.childNodes; length = childNodes.length; if (length > 0) { pseudo[containerKey] = parent; pseudo[offsetKey] = containerKey == "startContainer" ? 0 : length - 1; return; } element = parent; parent = element.parentNode; childNodes = parent.childNodes; length = childNodes.length; for (offset = 0; offset < length; offset++) { if (element == childNodes[offset]) { pseudo[containerKey] = parent; pseudo[offsetKey] = offset; return; } } } setContainerOffset(start, "startContainer", "startOffset"); setContainerOffset(end, "endContainer", "endOffset"); return pseudo; }; TracWysiwyg.prototype.getNativeSelectionRange = function() { this.contentWindow.focus(); return this.contentDocument.selection.createRange(); }; TracWysiwyg.prototype.getSelectionText = function() { var range = this.getNativeSelectionRange(); if (range) { return range.item ? range.item(0).innerText : range.text; } return null; }; TracWysiwyg.prototype.getSelectionHTML = function() { var range = this.getNativeSelectionRange(); if (range) { return range.item ? range.item(0).innerHTML : range.htmlText; } return null; }; TracWysiwyg.prototype.getSelectionFragment = function() { var d = this.contentDocument; var fragment = d.createDocumentFragment(); var anonymous = d.createElement("div"); anonymous.innerHTML = this.getSelectionHTML(); this.collectChildNodes(fragment, anonymous); return fragment; }; TracWysiwyg.prototype.getSelectionPosition = function() { this.contentWindow.focus(); var d = this.contentDocument; var range = d.selection.createRange(); var startNode = null; var endNode = null; if (range.item) { if (range.item(0).ownerDocument == d) { startNode = range.item(0); endNode = range.item(range.length - 1); } } else { if (range.parentElement().ownerDocument == d) { var startRange = range.duplicate(); startRange.collapse(true); startNode = startRange.parentElement(); var endRange = range.duplicate(); endRange.collapse(false); endNode = endRange.parentElement(); } } return { start: startNode, end: endNode }; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { this.contentWindow.focus(); var d = this.contentDocument; var body = d.body; var range = d.selection.createRange(); var tmp; if (arg.start) { tmp = body.createTextRange(); tmp.moveToElementText(arg.start); range.setEndPoint("StartToStart", tmp); } if (arg.end) { tmp = body.createTextRange(); tmp.moveToElementText(arg.end); range.setEndPoint("EndToEnd", tmp); } if (tmp) { range.select(); } }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { this.contentWindow.focus(); var d = this.contentDocument; var selection = d.selection; var range = selection.createRange(); var parent = range.item ? range.item(0) : range.parentElement(); if (!parent) { return false; } if (TracWysiwyg.getSelfOrAncestor(parent, name)) { return true; } var elements = parent.getElementsByTagName(name); var length = elements.length; for (var i = 0; i < length; i++) { var testRange = selection.createRange(); testRange.moveToElementText(elements[i]); if (range.compareEndPoints("StartToEnd", testRange) <= 0 && range.compareEndPoints("EndToStart", testRange) >= 0) { return true; } } return false; }; TracWysiwyg.prototype.insertHTML = function(html) { this.contentWindow.focus(); var selection = this.contentDocument.selection; var range = selection.createRange(); range.pasteHTML(html.replace(/\t/g, " ")); range.collapse(false); range.select(); range = this.contentDocument.selection.createRange(); }; } else { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { }; TracWysiwyg.prototype.insertParagraphOnEnter = null; TracWysiwyg.prototype.insertLineBreak = function() { }; TracWysiwyg.prototype.insertTableCell = function(row, index) { return null }; TracWysiwyg.prototype.getFocusNode = function() { return null }; TracWysiwyg.prototype.selectNode = function(node) { }; TracWysiwyg.prototype.selectNodeContents = function(node) { return null }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { }; TracWysiwyg.prototype.getSelectionRange = function() { return null }; TracWysiwyg.prototype.getNativeSelectionRange = function() { return null }; TracWysiwyg.prototype.getSelectionText = function() { return null }; TracWysiwyg.prototype.getSelectionHTML = function() { return null }; TracWysiwyg.prototype.getSelectionFragment = function() { return null }; TracWysiwyg.prototype.getSelectionPosition = function() { return null }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { return false }; TracWysiwyg.prototype.insertHTML = function(html) { }; } TracWysiwyg.prototype._treeWalkEmulation = function(root, iterator) { if (!root.firstChild) { iterator(null); return; } var element = root; var tmp; while (element) { if (tmp = element.firstChild) { element = tmp; } else if (tmp = element.nextSibling) { element = tmp; } else { for ( ; ; ) { element = element.parentNode; if (element == root || !element) { iterator(null); return; } if (tmp = element.nextSibling) { element = tmp; break; } } } iterator(element); } }; if (document.createTreeWalker) { TracWysiwyg.prototype.treeWalk = function(root, iterator) { var walker = root.ownerDocument.createTreeWalker( root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, true); while (walker.nextNode()) { iterator(walker.currentNode); } iterator(null); }; } else { TracWysiwyg.prototype.treeWalk = TracWysiwyg.prototype._treeWalkEmulation; } TracWysiwyg.instances = []; TracWysiwyg.count = 0; TracWysiwyg.tracPaths = null; TracWysiwyg.newInstance = function(textarea, options) { var instance = new TracWysiwyg(textarea, options); TracWysiwyg.instances.push(instance); return instance; }; TracWysiwyg.findInstance = function(textarea) { var instances = TracWysiwyg.instances; var length = instances.length; for (var i = 0; i < length; i++) { var instance = instances[i]; if (instance.textarea == textarea) { return instance; } } return null; }; TracWysiwyg.getTracPaths = function() { var stylesheets = []; var paths = { stylesheets: stylesheets }; var d = document; var head = d.getElementsByTagName("head")[0]; var links = head.getElementsByTagName("link"); var length = links.length; for (var i = 0; i < length; i++) { var link = links[i]; var href = link.getAttribute("href") || ""; var type = link.getAttribute("type") || ""; switch ((link.getAttribute("rel") || "").toLowerCase()) { case "tracwysiwyg.base": paths.base = href; break; case "tracwysiwyg.stylesheet": stylesheets.push(href); break; } } if (paths.base && stylesheets.length > 0) { return paths; } return null; }; TracWysiwyg.getOptions = function() { var options = {}; if (typeof window._tracwysiwyg != "undefined") { options = _tracwysiwyg; } return options; }; TracWysiwyg.getEditorMode = function() { if (TracWysiwyg.editorMode) { return TracWysiwyg.editorMode; } var mode = null; var cookies = (document.cookie || "").split(";"); var length = cookies.length; for (var i = 0; i < length; i++) { var match = /^\s*tracwysiwyg=(\S*)/.exec(cookies[i]); if (match) { switch (match[1]) { case "wysiwyg": mode = match[1]; break; default: // "textarea" mode = null; break; } break; } } TracWysiwyg.editorMode = mode || "textarea"; return TracWysiwyg.editorMode; }; TracWysiwyg.setEditorMode = function(mode) { switch (mode) { case "wysiwyg": break; default: // "textarea" mode = "textarea"; break; } TracWysiwyg.editorMode = mode; var now = new Date(); if (!/\/$/.test(TracWysiwyg.tracPaths.base)) { expires = new Date(now.getTime() - 86400000); pieces = [ "tracwysiwyg=", "path=" + TracWysiwyg.tracPaths.base + "/", "expires=" + expires.toUTCString() ]; document.cookie = pieces.join("; "); } var expires = new Date(now.getTime() + 365 * 86400 * 1000); var pieces = [ "tracwysiwyg=" + mode, "path=" + TracWysiwyg.tracPaths.base, "expires=" + expires.toUTCString() ]; document.cookie = pieces.join("; "); }; TracWysiwyg.removeEvent = function(element, type, func) { jQuery(element).unbind(type, func); }; TracWysiwyg.stopEvent = function(event) { if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; } }; TracWysiwyg.setStyle = function(element, object) { var style = element.style; for (var name in object) { style[name] = object[name]; } }; if (document.defaultView) { TracWysiwyg.getStyle = function(element, name) { var value = element.style[name]; if (!value) { var style = element.ownerDocument.defaultView.getComputedStyle(element, null) value = style ? style[name] : null; } return value; }; } else { TracWysiwyg.getStyle = function(element, name) { return element.style[name] || element.currentStyle[name]; }; } TracWysiwyg.elementPosition = function(element) { function vector(left, top) { var value = [ left, top ]; value.left = left; value.top = top; return value; } var position = TracWysiwyg.getStyle(element, "position"); var left = 0, top = 0; for (var node = element; node; node = node.offsetParent) { left += node.offsetLeft || 0; top += node.offsetTop || 0; } if (position != "absolute") { return vector(left, top); } var offset = TracWysiwyg.elementPosition(element.offsetParent); return vector(left - offset.left, top - offset.top); }; TracWysiwyg.getSelfOrAncestor = function(element, name) { var target = element; var d = element.ownerDocument; if (name instanceof RegExp) { while (target && target != d) { switch (target.nodeType) { case 1: // element if (name.test(target.tagName.toLowerCase())) { return target; } break; case 11: // fragment return null; } target = target.parentNode; } } else { name = name.toLowerCase(); while (target && target != d) { switch (target.nodeType) { case 1: // element if (target.tagName.toLowerCase() == name) { return target; } break; case 11: // fragment return null; } target = target.parentNode; } } return null; }; TracWysiwyg.serializeToHref = function(attrs) { var texts = []; for (var name in attrs) { if (/^data(?:-|$)/.exec(name)) { texts.push(encodeURIComponent(name) + "=" + encodeURIComponent(attrs[name])); } } return "#" + texts.join("&"); }; TracWysiwyg.unserializeFromHref = function(href, name) { var attrs = {}; if (href.indexOf("#") !== -1) { var pieces = href.replace(/^[^#]*#/, '').split(/&/g); var length = pieces.length; for (var i = 0; i < length; i++) { var pair = pieces[i].split(/=/g, 2); attrs[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } } return name ? attrs[name] : attrs; }; TracWysiwyg.getTextContent = (function() { var anonymous = document.createElement("div"); if (typeof anonymous.textContent != "undefined") { return function(element) { return element.textContent }; } else if (typeof anonymous.innerText != "undefined") { return function(element) { return element.innerText }; } else { return function(element) { return null }; } })(); TracWysiwyg.initialize = function() { if ("replace".replace(/[a-e]/g, function(m) { return "*" }) != "r*pl***") { return; } if (typeof document.designMode == "undefined") { return; } TracWysiwyg.tracPaths = TracWysiwyg.getTracPaths(); if (!TracWysiwyg.tracPaths) { return; } var options = TracWysiwyg.getOptions(); var textareas = document.getElementsByTagName("textarea"); for (var i = 0; i < textareas.length; i++) { var textarea = textareas[i]; if (/\bwikitext\b/.test(textarea.className || "")) { TracWysiwyg.newInstance(textarea, options); } } }; trac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/htdocs/toolbar.png0000644000175000017500000001136010672463456022022 0ustar wmbwmbPNG  IHDRoT pHYs  IDATxytTUTe'T8$"F`[FisPEpa4=:8=l3b;i[D#l-!IJBR*{珪o4ݹS{Ww~}ORJ0 gsiZ[ZM&7oӲ'P1glTU"ydbt:]CJN;SؐJ!)/+׮Ͼ E`MM xF'bŮ0u6n^?Jmmm/ddfN2<##8H6WB aՕRv  BHUzdSfJ)AH "A*T!P$(SPH/Kq;EAAߺ':NNEgTVTos-G>v)S|)Waz=&O@oMbt;`ӉbiogQtV+SN!ɖDjni:97 TwPQ^?':n5S>[٧xt̿6EC aws%8yS-y\.mx;456q{X-8m4rnbwŇ8u4_="##P"%t$sl6j]"aΓR" h ^M*<=J(TjҒSlHÀ߯J5o>J˚IΌn2zre|v6hM&#I6RdK⦜1gzqx ~Ή_qԙУQadM"99+>ucǎmq]u LNI&>>^#Ix\-=abw}'.r݉b=V+eT@)W:.yo_>ԴT-j8q"RJjkjinn!--ظa !!ظXΕ#'&Mv01 Ξ9˜sXzOrӧEdfevt2mZ6wͿ+fde"M*TwFZW71qDV>EAme22Jn cB )_Z~.8W6K.ɭI![:o:<nK)xXUu ro-9_G 9ꨯC*g{Ǎ/=E󰾡]IBTU%mr'~>!&^O{[-^D :y(|>,&>!>6BZ[Z :ZۈN>O1њZ7<ޡv5KݐM_ȑhokg$mrUUVc99t:bd1̦r2Ȍ|{{ aaFffi)g}RXڹsl: sis%_fMIIg,Ƚ'O|ŲrRq69yżn>?zXbccIIMk]Q~xiΞ>KEE%wsFsgOp{=ȢŋPCOVleR uuDFZB /r]?+|}qqDƒܷ?*RRӜ=SBEEwοs(S<DTUź@J5'p|y<Z[H%K}]=Vi3ñ7Hjkf :k&$Lr U^wE||f AS~̬ &' ^egs#ؒp:]_S \Ӓ9CKbjkkCέC3y &P$9|rͻ7Աw^gG1Mt$M C~<&9971iR\ 0cW'|RU ˗/[͛9<٬Xhym6ZZZ:u*=%nLnذA&h%pgl?,..fMO[xip8x|ꩧGNc씫ñj<GFC6 #aw|;z;vcq\yaÆ6{ Kx-xẍR\.|#m{t:-Z4^:ͬ_EQXv7 چYF?Z݆{9~ӟOS@__A<6mڤEv~{pɚC"""FC^p333X7qa H%ugů+xLj}O êfwrlmlazhK ukG,ԠNܹ^.|`TBR<Tقu25x<[NU @03=7 > HAm<_PUθ}>d(?׸y 3!|x^F#>ٌ!""UUQN(ft:]x^B( @UUt:b0xIHHS7|zt:z=>_S*믿Nrrrד˗/B;UUUgrƍl7˖-[x駵jjv bٵk(~[obŊª*ݻY|9FL\\\nmmeϞ=j@ +!0 Z;F,YfqFVZb۩{˖a?XS)0pw}EBB/2K. iݾeZ|DDiSCAE|X1K/%ݿ7lxW|FFz_)%V #.6^q[۹pw~: 7p<]EQIx؄h@7 @^o@ 1L: `7oIENDB`trac-wysiwyg-0.12.0.3+r10725/0.12/tracwysiwyg/htdocs/editor.css0000644000175000017500000000024611211421434021627 0ustar wmbwmbpre.wiki { overflow: visible !important; word-wrap: break-word !important; white-space: -moz-pre-wrap !important; white-space: pre-wrap !important; } trac-wysiwyg-0.12.0.3+r10725/0.12/setup.cfg0000644000175000017500000000004310672463456015607 0ustar wmbwmb[egg_info] tag_svn_revision = true trac-wysiwyg-0.12.0.3+r10725/0.12/setup.py0000644000175000017500000000113411463324376015476 0ustar wmbwmb#!/usr/bin/env python # -*- coding: utf-8 -*- from setuptools import setup, find_packages setup( name = 'TracWysiwyg', version = '0.12.0.3', description = 'TracWiki WYSIWYG Editor', license = 'BSD', url = 'http://trac-hacks.org/wiki/TracWysiwygPlugin', author = 'Jun Omae', author_email = 'omae@opengroove.com', packages = find_packages(exclude=['*.tests*']), package_data = { 'tracwysiwyg' : [ 'htdocs/*.js', 'htdocs/*.css', 'htdocs/*.png' ], }, entry_points = { 'trac.plugins': [ 'tracwysiwyg = tracwysiwyg', ], } ) trac-wysiwyg-0.12.0.3+r10725/0.12/tests/0000755000175000017500000000000011677636642015140 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.12/tests/testcase.js0000644000175000017500000022252611642344654017311 0ustar wmbwmbaddEvent(window, "load", function() { TracWysiwyg.tracPaths = { base: ".", stylesheets: [] }; var options = TracWysiwyg.getOptions(); var instance = new TracWysiwyg(document.getElementById("textarea"), options); var contentDocument = instance.contentDocument; var d = document; var wysiwygHtml = d.getElementById("wysiwyg-html"); var showWysiwygHtml = d.getElementById("show-wysiwyg-html"); setTimeout(function() { if (showWysiwygHtml.checked) { var body = contentDocument.body; var browserIE = body.attachEvent ? true : false; var elements = body.getElementsByTagName("br"); var count = 0; var html = body.innerHTML.replace(/<[Bb][Rr] *[^>\/]*/g, function(value) { var element = elements[count++]; var attributes = element.attributes; var length = attributes.length; if (length == 0) return value; var texts = [ value ]; for (var i = 0; i < length; i++) { var attr = attributes[i]; if (!browserIE || !!element[attr.name]) { texts.push(' ', attr.name, '="', attr.value, '"'); } } return texts.join(""); }); if (wysiwygHtml.value != html) { wysiwygHtml.value = html; } } setTimeout(arguments.callee, 500); }, 500); function generate(dom, wikitext, options, withoutDomToWikitext, withoutWikitextToFragment) { dom = dom.cloneNode(true); var anonymous = dom.ownerDocument.createElement("div"); anonymous.appendChild(dom); if (!withoutWikitextToFragment) { var fragment = instance.wikitextToFragment(wikitext, contentDocument, options); var generated = contentDocument.createElement("div"); generated.appendChild(fragment); var generatedHtml = generated.innerHTML; if (!generated.addEventListener || window.opera) { generatedHtml = generatedHtml.replace(/\n\r/g, "\uffff").replace(/\uffff\n?/g, "\n"); } this.assertEqual(anonymous.innerHTML, generatedHtml, "wikitextToFragment"); } if (!withoutDomToWikitext) { this.assertEqual(wikitext, instance.domToWikitext(anonymous, options), "domToWikitext"); } } function generateFragment(dom, wikitext, options) { generate.call(this, dom, wikitext, options, true, false); } function generateWikitext(dom, wikitext, options) { generate.call(this, dom, wikitext, options, false, true); } function run() { var unit = new TracWysiwyg.TestUnit(); var fragment = unit.fragment; var element = unit.element; var br = function() { return element("br") }; var a = function(link, label) { var attrs = { href: "#data-tracwysiwyg-link=" + encodeURIComponent(link), title: link, "data-tracwysiwyg-link": link, onclick: "return false;" }; return element("a", attrs, label || link); }; unit.add("treeWalk", function() { var list; function iterator(node) { var value; if (node) { switch (node.nodeType) { case 1: value = node.tagName.toLowerCase(); break; case 3: value = "#text"; break; } } else { value = "(null)"; } list.push(value); } function doTreeWalk(expected, dom) { list = []; instance.treeWalk(dom, iterator); this.assertEqual(expected, list.join(" ")); list = []; instance._treeWalkEmulation(dom, iterator); this.assertEqual(expected, list.join(" ")); } doTreeWalk.call(this, "p #text (null)", element("div", element("p", "paragraph"))); doTreeWalk.call(this, "#text (null)", element("div", element("p", "paragraph")).firstChild); doTreeWalk.call(this, "(null)", element("div", element("p")).firstChild); var dom = element("div"); dom.innerHTML = [ '

Tables

', '

', 'Simple tables can be created like this:', '

', '
||Cell 1||Cell 2||Cell 3||',
                '||Cell 4||Cell 5||Cell 6||',
                '

', 'Display:', '

', '', '
Cell 1Cell 2Cell 3', '
Cell 4Cell 5Cell 6', '
', '

', 'Note that more complex tables can be created using', 'reStructuredText.', '

' ].join(""); var expected = [ 'h2', '#text', 'p', '#text', 'pre', '#text', 'p', '#text', 'table', 'tbody', 'tr', 'td', '#text', 'td', '#text', 'td', '#text', 'tr', 'td', '#text', 'td', '#text', 'td', '#text', 'p', '#text', 'a', '#text', '#text', '(null)'].join(" "); doTreeWalk.call(this, expected, dom); }); unit.add("isLastChildInBlockNode", function() { var dom = fragment( element("p", element("br")), element("p", "foobar", element("br"), "foobar"), element("p", element("b", "foobar", element("br"))), element("p", element("b", "foobar"), element("br")), element("br")); var count = 0; function assert(expected, node) { this.assertEqual(expected, instance.isLastChildInBlockNode(node), "#" + (count++)); } assert.call(this, true, dom.childNodes[0].childNodes[0]); assert.call(this, false, dom.childNodes[1].childNodes[0]); assert.call(this, false, dom.childNodes[1].childNodes[1]); assert.call(this, true, dom.childNodes[1].childNodes[2]); assert.call(this, false, dom.childNodes[2].childNodes[0].childNodes[0]); assert.call(this, true, dom.childNodes[2].childNodes[0].childNodes[1]); assert.call(this, false, dom.childNodes[3].childNodes[0].childNodes[0]); assert.call(this, true, dom.childNodes[3].childNodes[1]); assert.call(this, true, dom.childNodes[4]); }); unit.add("code block", function() { var dom = fragment( element("p", element("tt", "abc")), element("pre", { "class": "wiki" }, "{{{code-block")); var wikitext = [ "`abc`", "", "{{{", "{{{code-block", "}}}" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("code block nest", function() { var dom = fragment( element("pre", { "class": "wiki" }, "#!python\n= level 1\n{{{\n= level 2\n}}}\n= level 1")); var wikitext = [ "{{{", "#!python", "= level 1", "{{{", "= level 2", "}}}", "= level 1", "}}}" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("paragraph", function() { var dom = fragment( element("p", "Paragraph continued..."), element("p", "Second paragraph continued...")); generateFragment.call(this, dom, [ "Paragraph", "continued...", "", "Second paragraph", "continued...", "" ].join("\n")); generate.call(this, dom, [ "Paragraph continued...", "", "Second paragraph continued..." ].join("\n")); }); unit.add("hr", function() { var dom = fragment( element("p", "Paragraph"), element("hr"), element("ul", element("li", "item 1"), element("ol", element("li", "item 1.1"))), element("hr")); generateFragment.call(this, dom, [ "Paragraph", "----", " * item 1", " 1. item 1.1", "----" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "----", " * item 1", " 1. item 1.1", "", "----" ].join("\n")); }); unit.add("bold italic", function() { var dom = element("p", element("b", element("i", "bold italic"))); var wikitext = "'''''bold italic'''''"; generate.call(this, dom, wikitext); }); unit.add("bold", function() { var wikitext = [ "The quick '''brown''' fox.", "", "The quick '''brown''' fox." ].join("\n"); generateWikitext.call(this, fragment( element("p", "The quick ", element("b", "brown"), " fox."), element("p", "The quick ", element("strong", "brown"), " fox.")), wikitext); generateFragment.call(this, fragment( element("p", "The quick ", element("b", "brown"), " fox."), element("p", "The quick ", element("b", "brown"), " fox.")), wikitext); }); unit.add("italic", function() { var wikitext = [ "The quick ''brown'' fox.", "", "The quick ''brown'' fox." ].join("\n"); generateWikitext.call(this, fragment( element("p", "The quick ", element("i", "brown"), " fox."), element("p", "The quick ", element("em", "brown"), " fox.")), wikitext); generateFragment.call(this, fragment( element("p", "The quick ", element("i", "brown"), " fox."), element("p", "The quick ", element("i", "brown"), " fox.")), wikitext); }); unit.add("underline", function() { var dom = element("p", element("u", "underline")); var wikitext = "__underline__"; generate.call(this, dom, wikitext); }); unit.add("strike-through", function() { var dom = element("p", element("del", "strike-through")); var wikitext = "~~strike-through~~"; generate.call(this, dom, wikitext); }); unit.add("superscript", function() { var dom = element("p", element("sup", "superscript")); var wikitext = "^superscript^"; generate.call(this, dom, wikitext); }); unit.add("subscript", function() { var dom = element("p", element("sub", "subscript")); var wikitext = ",,subscript,,"; generate.call(this, dom, wikitext); }); unit.add("monospace", function() { var dom = element("p", element("tt", "monospace"), ", ", element("tt", "mono`s`pace"), ", ", element("tt", "mono{{{s}}}pace")); var wikitext = "`monospace`, {{{mono`s`pace}}}, `mono{{{s}}}pace`"; generate.call(this, dom, wikitext); }); unit.add("italic -> bold", function() { var dom = element("p", "normal", element("i", "italic"), element("b", "bold"), "normal"); var wikitext = "normal''italic'''''bold'''normal"; generate.call(this, dom, wikitext); }); unit.add("bold -> italic", function() { var dom = element("p", "normal", element("b", "bold"), element("i", "italic"), "normal"); var wikitext = "normal'''bold'''''italic''normal"; generate.call(this, dom, wikitext); }); unit.add("[ italic [ xyz ] bold ]", function() { var dom = element("p", "normal", element("i", "italic", element("b", "xyz")), element("b", "bold"), "normal"); var wikitext = "normal''italic'''xyz''bold'''normal"; generate.call(this, dom, wikitext); }); unit.add("overlapped markups", function() { var dom = element("p", "normal", element("b", "bold", element("i", "italic", element("u", "underline", element("del", "strike-through", element("sup", "superscript", element("sub", "subscript"))))), element("u", element("del", element("sup", element("sub", "i")))), element("del", element("sup", element("sub", "u"))), element("sup", element("sub", "strike")), element("sub", "sup"), "sub"), "."); var wikitext = "normal'''bold''italic__underline~~strike-through^superscript,,subscript''i__u~~strike^sup,,sub'''."; generateFragment.call(this, dom, wikitext); }); unit.add("repeated markups", function() { generateWikitext.call(this, element("p", "ab", element("b", "cd"), element("b", "ef"), "gh"), "ab'''cdef'''gh"); generateWikitext.call(this, element("p", "ab", element("i", "cd"), element("i", "ef"), "gh"), "ab''cdef''gh"); generateWikitext.call(this, element("p", "ab", element("u", "cd"), element("u", "ef"), "gh"), "ab__cdef__gh"); generateWikitext.call(this, element("p", "ab", element("sup", "cd"), element("sup", "ef"), "gh"), "ab^cdef^gh"); generateWikitext.call(this, element("p", "ab", element("sub", "cd"), element("sub", "ef"), "gh"), "ab,,cdef,,gh"); generateWikitext.call(this, element("p", "ab", element("tt", "cd"), element("tt", "ef"), "gh"), "ab`cd``ef`gh"); generateWikitext.call(this, element("p", "ab", element("i", element("b", "cd")), element("b", element("i", "ef")), "gh"), "ab'''''cdef'''''gh"); }); unit.add("markups without text", function() { generateWikitext.call(this, element("p", "abc", element("b", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("i", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("u", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("sup", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("sub", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("tt", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("b", element("i", "")), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("i", element("b", "")), "def"), "abcdef"); }); unit.add("! bold italic", function() { var dom = element("p", element("b", element("i", "bold''''' italic")), "."); var wikitext = "'''''bold!''''' italic'''''."; generate.call(this, dom, wikitext); }); unit.add("! bold", function() { var dom = element("p", element("b", "bold''' bold"), "."); var wikitext = "'''bold!''' bold'''."; generate.call(this, dom, wikitext); }); unit.add("! italic", function() { var dom = element("p", element("i", "italic'' italic"), "."); var wikitext = "''italic!'' italic''."; generate.call(this, dom, wikitext); }); unit.add("! underline", function() { var dom = element("p", element("u", "underline__ underline"), "."); var wikitext = "__underline!__ underline__."; generate.call(this, dom, wikitext); }); unit.add("! strike-through", function() { var dom = element("p", element("del", "strike~~through"), "."); var wikitext = "~~strike!~~through~~."; generate.call(this, dom, wikitext); }); unit.add("! superscript", function() { var dom = element("p", element("sup", "superscript^ superscript"), "."); var wikitext = "^superscript!^ superscript^."; generate.call(this, dom, wikitext); }); unit.add("! subscript", function() { var dom = element("p", element("sub", "subscript,, subscript"), "."); var wikitext = ",,subscript!,, subscript,,."; generate.call(this, dom, wikitext); }); unit.add("! monospace", function() { var dom = element("p", "{{{monospace}}} or `monospace`"); var wikitext = "!{{{monospace}}} or !`monospace`"; generate.call(this, dom, wikitext); }); unit.add("!||, !=||", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "foo||bar!||||==||foobar")))), element("p", "||||cell=||= =||||=cell|| Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||foo!||bar!!||||=!=||foobar", "!||||cell!=||=", "!=||||=cell!||", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| foo!||bar!!||||=!=||foobar ||", "", "!||||cell!=||= !=||||=cell!|| Paragraph" ].join("\n")); }); unit.add("#ticket", function() { var dom = element("p", a("ticket:1234", "#1234"), " #2345 ඀"); var wikitext = "#1234 !#2345 ඀"; generate.call(this, dom, wikitext); }); unit.add("{report}", function() { var dom = element("p", "{987}", a("report:123", "{123}")); var wikitext = "!{987}{123}"; generate.call(this, dom, wikitext); }); unit.add("[changeset]", function() { var dom = element("p", a("changeset:123", "[123]"), ", ", a("changeset:234", "r234"), ", ", a("changeset:345/trunk", "[345/trunk]"), ", [123], r234, [345/trunk], ar123"); generate.call(this, dom, "[123], r234, [345/trunk], ![123], !r234, ![345/trunk], ar123"); }); unit.add("[log]", function() { var dom = element("p", "log - ", a("log:@1:3", "r1:3"), ", r1:3, ", a("log:@1:3", "[1:3]"), ", [1:3], ", a("log:@1:3", "log:@1:3"), ", log:@1:3, ", a("log:trunk@1:3", "log:trunk@1:3"), ", log:trunk@1:3"); generate.call(this, dom, "log - r1:3, !r1:3, [1:3], ![1:3], log:@1:3, !log:@1:3, log:trunk@1:3, !log:trunk@1:3"); }); unit.add("wiki:TracLinks", function() { var dom = element("p", a("link:WikiName", "link:WikiName"), " ", a('link:"Foo Bar"', 'link:"Foo Bar"'), " ", a('link:"Foo Bar#baz"', 'link:"Foo Bar#baz"'), " ", a("link:'Foo Bar'", "link:'Foo Bar'"), " ", a("link:'Foo Bar#baz'", "link:'Foo Bar#baz'"), " ", a("svn+ssh://example.com/trunk", "svn+ssh://example.com/trunk"), " ", a("svn+ssh://example.com/trunk", "repository"), " ", a("rfc-2396.compatible://link", "rfc-2396.compatible://link"), " ", a("rfc-2396.compatible://link", "RFC 2396"), " ", "21:09,", element("u", "underline"), ",abc123 !21:09,", element("u", "underline"), ",abc123", " ", a("foo:bar", "foo:bar"), " begin", a("foo:bar", "foo:bar"), " ", a("foo:bar", "foo:bar"), "end begin", a("wiki:WikiStart", "WikiStart"), "end link:'Foo Bar#baz'"); generateFragment.call(this, dom, [ "link:WikiName", 'link:"Foo Bar" link:"Foo Bar#baz"', "link:'Foo Bar' link:'Foo Bar#baz'", "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]", "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]", "21:09,__underline__,abc123 !21:09,__underline__,abc123", "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end", "!link:'Foo Bar#baz'" ].join(" ")); generate.call(this, dom, [ "link:WikiName", 'link:"Foo Bar" link:"Foo Bar#baz"', "link:'Foo Bar' link:'Foo Bar#baz'", "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]", "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]", "21:09,__underline__,abc123 !21:09,__underline__,abc123", "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end", "!link:'Foo Bar#baz'" ].join(" ")); }); unit.add("[wiki:TracLinks label]", function() { var dom = element("p", a("link:WikiName", "WikiName"), " ", a("link:WikiName", "wiki name"), " ", a("wiki:WikiName", "wiki]name"), " ", a("wiki:WikiName", "wiki name"), " ", a('link:"Foo Bar"', "Foo Bar"), " ", a('link:"Foo Bar#baz"', "Foo Bar#baz"), " ", a('link:"Foo Bar"', "bar foo"), " ", a('link:"Foo Bar#baz"', 'foo "foobar" bar'), " ", a("link:'Foo Bar'", "Foo Bar"), " ", a("link:'Foo Bar#baz'", "Foo Bar#baz"), " ", a("link:'Foo Bar'", "foo bar"), " ", a("link:'Foo Bar#baz'", "foo 'foobar' bar"), " [link:'Foo Bar#baz'] [link:'Foo Bar#baz' label]"); generateFragment.call(this, dom, [ "[link:WikiName]", "[link:WikiName 'wiki name']", '[wiki:WikiName "wiki]name"]', "[WikiName 'wiki name']", '[link:"Foo Bar"] [link:"Foo Bar#baz"]', '[link:"Foo Bar" "bar foo"] [link:"Foo Bar#baz" foo "foobar" bar]', "[link:'Foo Bar'] [link:'Foo Bar#baz']", "[link:'Foo Bar' 'foo bar'] [link:'Foo Bar#baz' foo 'foobar' bar]", "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" ")); generate.call(this, dom, [ "[link:WikiName]", "[link:WikiName wiki name]", '[wiki:WikiName "wiki]name"]', "[wiki:WikiName wiki name]", '[link:"Foo Bar" Foo Bar] [link:"Foo Bar#baz" Foo Bar#baz]', '[link:"Foo Bar" bar foo] [link:"Foo Bar#baz" foo "foobar" bar]', "[link:'Foo Bar' Foo Bar] [link:'Foo Bar#baz' Foo Bar#baz]", "[link:'Foo Bar' foo bar] [link:'Foo Bar#baz' foo 'foobar' bar]", "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" ")); }); unit.add("[/relative label]", function() { var dom = element("p", a("../trac", "Trac"), " ", a("/newticket?component=tracwysiwygplugin", "here"), " ", a("//hostname", "host"), " ", a("//hostname/images", "images"), " ", a("#anchor", "anchor")); var wikitext = [ "[../trac Trac]", "[/newticket?component=tracwysiwygplugin here]", "[//hostname host]", "[//hostname/images images]", "[#anchor anchor]" ].join(" "); generate.call(this, dom, wikitext); }); unit.add("", function() { var dom = fragment( element("p", "<", a("link:1"), ">"), element("p", "Thing<", a("link:2 and (3)"), ">"), element("p", ""), element("p", "Thing")); var wikitext = [ "", "", "Thing", "", "!", "", "Thing!" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("[=#anchor]", function() { var dom = fragment( element("p", "This is the ", element("span", { "class": "wikianchor", id: "init" }), " initialization routine: ..."), element("p", "Look for ", element("span", { "class": "wikianchor", id : "extra" }, element("i", "additional explanations")), " here."), element("p", "これは", element("span", { "class": "wikianchor", id: "初期化" }), "初期化ルーチン: ..."), element("p", element("span", { "class": "wikianchor", id : "追加" }, element("i", "追加説明")), "はここを見てください。")); var wikitext = [ "This is the [=#init] initialization routine: ...", "", "Look for [=#extra ''additional explanations''] here.", "", "これは[=#初期化]初期化ルーチン: ...", "", "[=#追加 ''追加説明'']はここを見てください。" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("[[macro]]", function() { var dom = element("p", "Line break ", element("br"), " another line", element("br"), "last line [[bR]] ![[Br]] [[Macro]] ![[Macro]] [[Image?]] ![[Image?]] [[?]] ![[?]]"); generateFragment.call(this, dom, "Line break [[BR]] another line[[br]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]] [[Image?]] ![[Image?]] [[?]] ![[?]]"); generate.call(this, dom, "Line break [[BR]] another line[[BR]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]] [[Image?]] ![[Image?]] [[?]] ![[?]]"); }); unit.add("WikiPageName", function() { var dom = fragment( element("p", a("wiki:CamelCase", "CamelCase"), " CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor"), element("p", a("wiki:WikiStart", "WikiStart"), " Wiki", a("wiki:Start", "Start"), " ", a("wiki:Wiki", "Wiki"), "Start Wiki", a("wiki:Start", "Start"), "Wiki")); generate.call(this, dom, [ "CamelCase !CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor", "", "WikiStart Wiki[wiki:Start] [wiki:Wiki]Start Wiki[wiki:Start]Wiki" ].join("\n")); }); unit.add('["internal free link"]', function() { var dom = element("p", "link - ", a('wiki:"internal free link"', "internal free link"), ' - ["free link"]'); generate.call(this, dom, 'link - [wiki:"internal free link" internal free link] - !["free link"]'); }); unit.add("traclink + underline", function() { var dom = element("p", element("u", a("ticket:123", "#123")), " ", a("ticket:123", element("u", "#123")), " ", element("u", a("report:123", "{123}")), " ", a("report:123", element("u", "{123}")), " ", element("u", a("changeset:123", "[123]")), " ", a("changeset:123", element("u", "[123]")), " ", element("u", a("changeset:123", "r123")), " ", a("changeset:123", element("u", "r123")), " ", element("u", a("log:@123:234", "[123:234]")), " ", a("log:@123:234", element("u", "[123:234]")), " ", element("u", a("wiki:WikiStart", "wiki:WikiStart")), " ", a("wiki:WikiStart", element("u", "wiki:WikiStart")), " ", element("u", a("wiki:WikiStart", "WikiStart")), " ", a("wiki:WikiStart", element("u", "WikiStart"))); generateWikitext.call(this, dom, [ '__#123__', '__#123__', '__{123}__', '__{123}__', '__[123]__', '__[123]__', '__[changeset:123 r123]__', '__[changeset:123 r123]__', '__[123:234]__', '__[123:234]__', '__[wiki:WikiStart wiki:WikiStart]__', '__[wiki:WikiStart wiki:WikiStart]__', '__[wiki:WikiStart]__', '__[wiki:WikiStart]__' ].join(" ")); }); unit.add("token + br", function() { var dom = fragment( element("p", "head ", a("http://localhost/", "http://localhost/"), element("br"), "tail"), element("p", "head http://localhost/", element("br"), "tail"), element("p", "head ", element("tt", "teletype"), element("br"), "tail"), element("p", "head ", a("wiki:TracLinks", "TracLinks"), element("br"), "tail"), element("p", "head ", a("http://localhost/", "http://localhost/"), " ", a("wiki:TracLinks", "wiki:TracLinks"), element("br"), "tail"), element("p", "head http://localhost/ wiki:TracLinks", element("br"), "tail")); generateWikitext.call(this, dom, [ "head http://localhost/ [[BR]]tail", "", "head !http://localhost/ [[BR]]tail", "", "head `teletype`[[BR]]tail", "", "head TracLinks[[BR]]tail", "", "head http://localhost/ wiki:TracLinks [[BR]]tail", "", "head !http://localhost/ !wiki:TracLinks [[BR]]tail" ].join("\n")); }); if (window.getSelection) { unit.add("block + br", function() { function br() { return element("br"); } var wikitext = [ "text, br", "", "text'', br[[BR]]''", "", "|| 1,1[[BR]] || || 1,3 ||", "|| || 2,2[[BR]][[BR]] ||", "", " * list, br[[BR]]", " * list, br", " * ", "", "text, br[[BR]]" ].join("\n") generateWikitext.call(this, fragment( element("p", "text, br", br()), element("p", "text", element("i", ", br", br()), br()), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br(), br()), element("td", br()), element("td", "1,3", br())), element("tr", element("td", br()), element("td", "2,2", br(), br(), br())))), element("ul", element("li", "list, br", br(), br()), element("li", "list, br", br()), element("li")), element("p", "text, br", br(), br())), wikitext); generateFragment.call(this, fragment( element("p", "text, br"), element("p", "text", element("i", ", br", br()), br()), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br(), br()), element("td", br()), element("td", "1,3")), element("tr", element("td", br()), element("td", "2,2", br(), br(), br())))), element("ul", element("li", "list, br", br(), br()), element("li", "list, br"), element("li", br())), element("p", "text, br", br(), br())), wikitext); }); } else { unit.add("block + br", function() { function br() { return element("br"); } var wikitext = [ "text, br", "", "text'', br[[BR]]''", "", "|| 1,1[[BR]] || || 1,3 ||", "|| || 2,2[[BR]][[BR]] ||", "", " * list, br[[BR]]", " * list, br", " * ", "", "text, br[[BR]]" ].join("\n") generate.call(this, fragment( element("p", "text, br"), element("p", "text", element("i", ", br", br())), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br()), element("td"), element("td", "1,3")), element("tr", element("td"), element("td", "2,2", br(), br())))), element("ul", element("li", "list, br", br()), element("li", "list, br"), element("li")), element("p", "text, br", br())), wikitext); }); } unit.add("citation", function() { var dom = fragment( element("blockquote", { "class": "citation" }, element("p", "This is the quoted text continued"), element("blockquote", { "class": "citation" }, element("p", "a nested quote"), element("blockquote", { "class": "citation" }, element("p", "a nested-nested quote")))), element("p", "A comment on the above"), element("blockquote", { "class": "citation" }, element("blockquote", { "class": "citation" }, element("p", "start 2nd level")), element("p", "first level"))); generateFragment.call(this, dom, [ "> This is the quoted text", "> continued", "> > a nested quote", "> > > a nested-nested quote", "A comment on the above", "> > start 2nd level", ">first level" ].join("\n")); generate.call(this, dom, [ "> This is the quoted text continued", "> > a nested quote", "> > > a nested-nested quote", "", "A comment on the above", "", "> > start 2nd level", "> first level" ].join("\n")); }); unit.add("header", function() { var dom = fragment( element("h1", "Heading 1"), element("h2", { id: "anchor-2" }, "Heading 2"), element("h3", element("u", "Heading"), " ", element("i", "3")), element("h4", { id: "アンカー-4" }, "Heading 4 with ", a("wiki:WikiStart", "link")), element("h5", "Heading 5"), element("h6", { id: "anchor-6" }, "Heading 6")); generate.call(this, dom, [ "= Heading 1 =", "== Heading 2 == #anchor-2", "=== __Heading__ ''3'' ===", "==== Heading 4 with [wiki:WikiStart link] ==== #アンカー-4", "===== Heading 5 =====", "====== Heading 6 ====== #anchor-6" ].join("\n")); }); unit.add("header 2", function() { var dom = fragment( element("h1", "Heading 1"), element("h2", { id: "anchor-2" }, "Heading 2"), element("h3", element("u", "Heading"), " ", element("i", "3")), element("h4", { id: "アンカー-4" }, "Heading 4 with ", a("wiki:WikiStart", "link")), element("h5", "Heading 5"), element("h6", { id: "anchor-6" }, "Heading 6")); generateFragment.call(this, dom, [ "= Heading 1 ", "== Heading 2 #anchor-2", "=== __Heading__ ''3'' ", "==== Heading 4 with [wiki:WikiStart link] #アンカー-4", "===== Heading 5 ", "====== Heading 6 #anchor-6" ].join("\n")); }); unit.add("list", function() { var dom = fragment( element("p", "Paragraph"), element("ul", element("li", "foo bar boo baz"), element("ul", element("li", "Subitem Subitem line 2")), element("li", "item 2 item 2 line 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " * foo bar", " boo baz", " * Subitem", " Subitem line 2", " * item 2", " item 2 line 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " * foo bar boo baz", " * Subitem Subitem line 2", " * item 2 item 2 line 2", "", "Paragraph" ].join("\n")); }); unit.add("list 2", function() { var dom = fragment( element("ul", element("li", "foo bar boo baz"), element("ul", element("li", "Subitem 1"), element("ul", element("li", "nested item 1"), element("li", "nested item 2 nested item 2 continued")), element("li", "Subitem 2 subitem 2 continued"), element("li", "Subitem 3 subitem 3 continued")), element("li", "item 2 item 2 line 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ " * foo bar", " boo baz", " * Subitem 1", " - nested item 1", " - nested item 2", " nested item 2 continued", " * Subitem 2", " subitem 2 continued", " * Subitem 3", " subitem 3 continued", " * item 2", " item 2 line 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ " * foo bar boo baz", " * Subitem 1", " * nested item 1", " * nested item 2 nested item 2 continued", " * Subitem 2 subitem 2 continued", " * Subitem 3 subitem 3 continued", " * item 2 item 2 line 2", "", "Paragraph" ].join("\n")); }); unit.add("ordered list", function() { var dom = fragment( element("p", "Paragraph"), element("ol", element("li", "item 1"), element("ol", { "class": "arabiczero" }, element("li", "item 1.1"), element("li", "item 1.2"), element("ol", { "class": "loweralpha" }, element("li", "item 1.2.a"), element("li", "item 1.2.b")), element("li", "item 1.3"), element("ol", { "class": "loweralpha" }, element("li", "item 1.3.a"), element("li", "item 1.3.b")), element("li", "item 1.4"), element("ol", { "class": "upperalpha" }, element("li", "item 1.4.A"), element("li", "item 1.4.B"), element("li", "item 1.4.C")), element("li", "item 1.5"), element("ol", { "class": "upperalpha" }, element("li", "item 1.5.A")), element("li", "item 1.6"), element("ol", { "class": "lowerroman" }, element("li", "item 1.6.i"), element("li", "item 1.6.ii")), element("li", "item 1.7"), element("ol", { "class": "upperroman" }, element("li", "item 1.7.I"), element("li", "item 1.7.II")))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " 1. item 1", " 0. item 1.1", " 2. item 1.2", " a. item 1.2.a", " z. item 1.2.b", " a. item 1.3", " b. item 1.3.a", " y. item 1.3.b", " Z. item 1.4", " A. item 1.4.A", " z. item 1.4.B", " z. item 1.4.C", " ii. item 1.5", " C. item 1.5.A", " XVI. item 1.6", " i. item 1.6.i", " x. item 1.6.ii", " 0. item 1.7", " I. item 1.7.I", " III. item 1.7.II", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " 1. item 1", " 0. item 1.1", " 0. item 1.2", " a. item 1.2.a", " a. item 1.2.b", " 0. item 1.3", " a. item 1.3.a", " a. item 1.3.b", " 0. item 1.4", " A. item 1.4.A", " A. item 1.4.B", " A. item 1.4.C", " 0. item 1.5", " A. item 1.5.A", " 0. item 1.6", " i. item 1.6.i", " i. item 1.6.ii", " 0. item 1.7", " I. item 1.7.I", " I. item 1.7.II", "", "Paragraph" ].join("\n")); }); unit.add("list + ordered list", function() { var dom = fragment( element("ul", element("li", "Item 1"), element("ul", element("li", "Item 1.1")), element("li", "Item 2")), element("ol", element("li", "Item 1"), element("ol", { "class": "loweralpha" }, element("li", "Item 1.a"), element("li", "Item 1.b"), element("ol", { "class": "lowerroman" }, element("li", "Item 1.b.i"), element("li", "Item 1.b.ii"))), element("li", "Item 2")), element("p", "And numbered lists can also be given an explicit number:"), element("ol", { start: 3 }, element("li", "Item 3"))); generateFragment.call(this, dom, [ " * Item 1", " * Item 1.1", " * Item 2", " 1. Item 1", " a. Item 1.a", " a. Item 1.b", " i. Item 1.b.i", " i. Item 1.b.ii", " 1. Item 2", "And numbered lists can also be given an explicit number:", " 3. Item 3" ].join("\n")); generate.call(this, dom, [ " * Item 1", " * Item 1.1", " * Item 2", "", " 1. Item 1", " a. Item 1.a", " a. Item 1.b", " i. Item 1.b.i", " i. Item 1.b.ii", " 1. Item 2", "", "And numbered lists can also be given an explicit number:", "", " 3. Item 3" ].join("\n")); }); unit.add("list at beginning of line", function() { var dom = fragment( element("ul", element("li", "item 1"), element("li", "item 2"), element("ul", element("li", "sub 2.1"), element("li", "sub 2.2"))), element("ol", { "class": "loweralpha" }, element("li", "item A"), element("li", "item B")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "- item 1", "- item 2", " - sub 2.1", " - sub 2.2", "a. item A", "b. item B", "Paragraph" ].join("\n")); generate.call(this, dom, [ " * item 1", " * item 2", " * sub 2.1", " * sub 2.2", "", " a. item A", " a. item B", "", "Paragraph" ].join("\n")); }); unit.add("list + code block", function() { var dom = fragment( element("p", "Paragraph"), element("ul", element("li", "item 1", element("pre", { "class": "wiki" }, "code")), element("ul", element("li", "item 1.1", element("pre", { "class": "wiki" }, "code"), "cont.", element("pre", { "class": "wiki" }, "code"))), element("li", "item 2", element("pre", { "class": "wiki" }, "code"))), element("ol", element("li", "item 1"))); generateFragment.call(this, dom, [ "Paragraph", " * item 1", "{{{", "code", "}}}", " * item 1.1", "{{{", "code", "}}}", " cont.", "{{{", "code", "}}}", " * item 2", "{{{", "code", "}}}", " 1. item 1" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " * item 1", "{{{", "code", "}}}", " * item 1.1", "{{{", "code", "}}}", " cont.", "{{{", "code", "}}}", " * item 2", "{{{", "code", "}}}", "", " 1. item 1" ].join("\n")); }); unit.add("list + citation", function() { var dom = fragment( element('ol', element('li', 'item 1')), element('blockquote', { 'class': 'citation' }, element("p", "citation 1")), element('ul', element('li', 'item 2'), element("ol", element('li', 'item 2.1'), element('li', 'item 2.2'))), element('blockquote', { 'class': 'citation' }, element("p", "citation 2 citation 3")), element('ol', element('li', 'item 3'))); generateFragment.call(this, dom, [ ' 1. item 1', '> citation 1', ' * item 2', ' 1. item 2.1', ' 1. item 2.2', '> citation 2', '> citation 3', ' 1. item 3' ].join("\n")); generateWikitext.call(this, dom, [ ' 1. item 1', '', '> citation 1', '', ' * item 2', ' 1. item 2.1', ' 1. item 2.2', '', '> citation 2 citation 3', '', ' 1. item 3' ].join("\n")); }); unit.add("definition", function() { var dom = element("dl", element("dt", "python"), element("dd", "www.python.org :: cont."), element("dt", element("b", "trac")), element("dd", element("b", "trac"), ".edgewall.org cont.", " ", element("tt", "trac-hacks::"), " trac-hacks.org")); generateFragment.call(this, dom, [ " python:: www.python.org :: cont.", " '''trac''':: '''trac'''.edgewall.org", " cont.", " `trac-hacks::` trac-hacks.org" ].join("\n")); generate.call(this, dom, [ " python:: www.python.org :: cont.", " '''trac''':: '''trac'''.edgewall.org cont. `trac-hacks::` trac-hacks.org" ].join("\n")); }); unit.add("blockquote", function() { var dom = fragment( element("p", "Paragraph"), element("blockquote", element("p", "blockquote 1 cont. 1"), element("blockquote", element("p", "blockquote 1.1"), element("blockquote", element("p", "blockquote 1.1.1 cont. 1.1.1")), element("p", "blockquote 1.2")), element("p", "blockquote 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " blockquote 1", " cont. 1", " blockquote 1.1", " blockquote 1.1.1", " cont. 1.1.1", " blockquote 1.2", " blockquote 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " blockquote 1 cont. 1", " blockquote 1.1", " blockquote 1.1.1 cont. 1.1.1", " blockquote 1.2", " blockquote 2", "", "Paragraph" ].join("\n")); }); unit.add("table", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2")), element("tr", element("td", "2.1")), element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3"), " ", element("tt", "-"))))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||1.1||1.2||", "||2.1", "||3.1||__3.2__||`3` `-`", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| 1.1 || 1.2 ||", "|| 2.1 ||", "|| 3.1 || __3.2__ || `3` `-` ||", "", "Paragraph" ].join("\n")); }); unit.add("colspan", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2", { colSpan: 2 })), element("tr", element("td", "2.1", { colSpan: 3 })), element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3.3"))))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||1.1||||1.2", "||||||2.1", "||3.1||__3.2__||`3.3`", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| 1.1 |||| 1.2 ||", "|||||| 2.1 ||", "|| 3.1 || __3.2__ || `3.3` ||", "", "Paragraph" ].join("\n")); }); unit.add("table header", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("th", "1.1"), element("td", "1.2", { colSpan: 2 })), element("tr", element("th", "2.1", { colSpan: 3 })), element("tr", element("td", "3.1"), element("th", element("u", "3.2")), element("td", element("tt", "3.3"))))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||=1.1=||||1.2", "||||||=2.1=||", "||3.1||=__3.2__=||`3.3`", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "||= 1.1 =|||| 1.2 ||", "||||||= 2.1 =||", "|| 3.1 ||= __3.2__ =|| `3.3` ||", "", "Paragraph" ].join("\n")); }); unit.add("table with alignment", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("th", "1.1"), element("td", "1.2", { colSpan: 2, align: "right" })), element("tr", element("th", "2.1", { colSpan: 3, align: "left" })), element("tr", element("td", "3||1", { align: "right" }), element("th", element("u", "3.2")), element("td", element("tt", "3.3"), { align: "left" })), element("tr", element("th", "4.1", { align: "center" }), element("td", "4.2"), element("td", "4.3", { align: "center" })))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||=1.1=|||| 1.2", "||||||=2.1 =||", "|| 3!||1||= __3.2__ =||`3.3` ||", "||= 4.1 =|| 4.2 || 4.3 ||", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "||= 1.1 =|||| 1.2||", "||||||=2.1 =||", "|| 3!||1||= __3.2__ =||`3.3` ||", "||= 4.1 =|| 4.2 || 4.3 ||", "", "Paragraph" ].join("\n")); }); unit.add("table with row continuation", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2"), element("td", "1.3")), element("tr", element("td", "2.1")), element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3.3"))))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||1.1||1.2|| \\", "||1.3", "||2.1", "||3.1||__3.2__||`3.3`||\\", "Paragraph" ].join("\n")); }); unit.add("table + rule", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1st")))), element("p", element("b", "bold")), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "2nd")))), element("p", "'''normal")); generateFragment.call(this, dom, [ "||1st||", "'''bold'''", "||2nd||", "!'''normal" ].join("\n")); generate.call(this, dom, [ "|| 1st ||", "", "'''bold'''", "", "|| 2nd ||", "", "!'''normal" ].join("\n")); }); unit.add("blockquote + table", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "pre.1"), element("td", "pre.2")))), element("blockquote", element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2")), element("tr", element("td", "2.1")))), element("blockquote", element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "deep"))))), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3.3")))))), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "post.1"), element("td", "post.2")))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||pre.1||pre.2||", " ||1.1||1.2||", " ||2.1", " ||deep||", " ||3.1||__3.2__||`3.3`", "||post.1||post.2||", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| pre.1 || pre.2 ||", "", " || 1.1 || 1.2 ||", " || 2.1 ||", " || deep ||", " || 3.1 || __3.2__ || `3.3` ||", "", "|| post.1 || post.2 ||", "", "Paragraph" ].join("\n")); }); unit.add("table [ paragraph, ul ]", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", element("p", "1.1")), element("td", element("ul", element("li", "item 1"), element("li", "item 2")))), element("tr", element("td", element("p", "2.1"), element("ul", element("li", "item 3"), element("li", "item 4"))))))); generateWikitext.call(this, dom, [ "|| 1.1 || * item 1[[BR]] * item 2 ||", "|| 2.1[[BR]][[BR]] * item 3[[BR]] * item 4 ||" ].join("\n")); }); unit.add("table with incomplete markups", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", element("b", element("i", "'"))), element("td", element("b", "bold"))) ) ) ); generateFragment.call(this, dom, "|| '''''' || '''bold''' ||"); }); unit.add("table from word", function() { var dom = element("div"); dom.innerHTML = [ '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '
', '

a

', '

b

', '
', '', '

b

', '
', '

c

', '
', '', '

d

', '
', '' ].join("\n"); generateWikitext.call(this, dom, [ "|| a[[BR]][[BR]]b || b ||", "|| c || d ||" ].join("\n")); }); unit.add("domToWikitext for code block", function() { var br = function() { return element("br") }; var dom = fragment( element("h1", "Heading", br(), "1"), element("h2", "Heading", br(), "2"), element("h3", "Heading", br(), "3"), element("h4", "Heading", br(), "4"), element("h5", "Heading", br(), "5"), element("h6", "Heading", br(), "6"), element("p", "var TracWysiwyg = function(textarea) {", br(), "...", br(), "}"), element("blockquote", { "class": "citation" }, element("p", "citation", br(), "continued")), element("blockquote", element("p", "quote", br(), "continued")), element("ul", element("li", "item 1", br(), "continued"), element("ol", element("li", "item", br(), "1.1"))), element("dl", element("dt", "def to_s(", br(), ")"), element("dd", "dt", br(), "dd")), element("table", element("tbody", element("tr", element("td", "cell", br(), "1"), element("th", "cell", br(), "2"))))); var wikitext = instance.domToWikitext(dom, { formatCodeBlock: true }); this.assertEqual([ "= Heading 1 =", "== Heading 2 ==", "=== Heading 3 ===", "==== Heading 4 ====", "===== Heading 5 =====", "====== Heading 6 ======", "var TracWysiwyg = function(textarea) {", "...", "}", "", "> citation", "> continued", "", " quote", " continued", "", " * item 1", " continued", " 1. item", " 1.1", "", " def to_s( ):: dt", " dd", "", "|| cell[[BR]]1 ||= cell[[BR]]2 =||" ].join("\n"), wikitext); }); unit.add("escape newlines", function() { var dom = fragment( element("h1", "header"), element("blockquote", { "class": "citation" }, element("p", br(), "preserve", br(), "newlines", br(), br(), element("i", "(since 0.11)"), br(), br(), br())), element("p", "Whether Wiki formatter should respect the new lines present", br(), "in the Wiki text. If set to ", element("b", "default"), ", this is equivalent to", br(), element("i", "yes"), " for new environments but keeps the old behavior for", br(), "upgraded environments (i.e. 'no')."), element("p", "must_preserve_newlines"), element("ul", element("li", "first", br(), "word"), element("li", "second", br(), "word")), element("dl", element("dt", "trac"), element("dd", "trac.edgewall.org", br(), "trac-hacks.org")), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "cell", br(), "cell"))))); generate.call(this, dom, [ "= header =", "> ", "> preserve", "> newlines", "> ", "> ''(since 0.11)''", "> ", "> ", "", "Whether Wiki formatter should respect the new lines present", "in the Wiki text. If set to '''default''', this is equivalent to", "''yes'' for new environments but keeps the old behavior for", "upgraded environments (i.e. 'no').", "", "must_preserve_newlines", "", " * first[[BR]]word", " * second[[BR]]word", "", " trac:: trac.edgewall.org[[BR]]trac-hacks.org", "", "|| cell[[BR]]cell ||" ].join("\n"), { escapeNewlines: true }); }); unit.add("selectRange", function() { var d = instance.contentDocument; function _element() { var args = [ d ]; args.push.apply(args, arguments); return element.apply(this, args); } function _text() { var args = [ d ]; args.push.apply(args, arguments); return text.apply(this, args); } function assertRangeText(expected, start, startOffset, end, endOffset) { instance.selectRange(start, startOffset, end, endOffset); if (expected instanceof RegExp) { unit.assertMatch(expected, instance.getSelectionText()); } else { unit.assertEqual(expected, instance.getSelectionText()); } } var body = d.body; while (body.childNodes.length > 0) { body.removeChild(body.lastChild); } body.appendChild(fragment(d, _element("p", "The", " quick", " brown", _element("b", " fox", " jumps", " over"), " the", " lazy", " dog."), _element("p", "Brick ", "quiz ", "whangs ", "jumpy ", "veldt ", "fox."))); var paragraph1 = body.childNodes[0]; var paragraph2 = body.childNodes[1]; var bold = paragraph1.childNodes[3]; assertRangeText("The", paragraph1.childNodes[0], 0, paragraph1.childNodes[0], 3); assertRangeText("he", paragraph1.childNodes[0], 1, paragraph1.childNodes[0], 3); assertRangeText("e quick brow", paragraph1.childNodes[0], 2, paragraph1.childNodes[2], 5); assertRangeText("ick brown", paragraph1.childNodes[1], 3, paragraph1.childNodes[2], 6); assertRangeText("ick brown fox j", paragraph1.childNodes[1], 3, bold.childNodes[1], 2); assertRangeText("ver the laz", bold.childNodes[2], 2, paragraph1.childNodes[5], 4); assertRangeText(" the lazy", paragraph1.childNodes[4], 0, paragraph1.childNodes[5], 5); assertRangeText("lazy dog.", paragraph1.childNodes[5], 1, paragraph1.childNodes[6], 5); assertRangeText(/^fox jumps over the lazy dog\.[\r\n]*Brick quiz whangs$/, bold.childNodes[0], 1, paragraph2.childNodes[2], 6); assertRangeText(" fox jumps over", paragraph1, 3, paragraph1, 4); assertRangeText(" dog.", paragraph1, 6, paragraph1, 7); assertRangeText("", paragraph1, 7, paragraph1, 7); assertRangeText("quick brown fox jumps over", paragraph1.childNodes[1], 1, paragraph1, 4); assertRangeText(" fox jumps over t", paragraph1, 3, paragraph1.childNodes[4], 2); }); unit.run(); } var button = document.createElement("button"); button.innerHTML = "run »"; button.style.textDecoration = "underline"; document.body.appendChild(button); addEvent(button, "click", run); button.focus(); }); trac-wysiwyg-0.12.0.3+r10725/0.12/tests/testunit.js0000644000175000017500000001527311642336132017344 0ustar wmbwmbTracWysiwyg.TestUnit = function() { this.cases = {}; this.assertCounts = {}; this.current = null; }; (function() { var prototype = TracWysiwyg.TestUnit.prototype; prototype.inspect = function(value) { var type = typeof value; switch (type) { case "string": return value.replace(/[\u0000-\u001f\\\u007f\ufffe\uffff]/g, function(m) { var code = m.charCodeAt(0); switch (code) { case 9: return "\\t"; case 10: return "\\n"; case 11: return "\\v"; case 12: return "\\f"; case 13: return "\\r"; case 92: return "\\\\"; } return "\\u" + (0x10000 + code).toString(16).substring(1); }); break; case "object": case "function": if (value instanceof RegExp) { return value.toString(); } } return "{%}".replace("%", type) + value.toString(); }; prototype.fragment = function() { var start = 0; var arg = arguments[0]; var d; if (arg.nodeType != 9) { d = document; } else { d = arg; start = 1; } var fragment = d.createDocumentFragment(); var length = arguments.length; for (var i = start; i < length; i++) { fragment.appendChild(arguments[i]); } return fragment; }; prototype.element = function(tag) { var start = 0; var arg = arguments[start++]; var d, tag; if (typeof arg == "string") { d = document; tag = arg; } else { d = arg; tag = arguments[start++]; } var element = d.createElement(tag); for (var i = start; i < arguments.length; i++) { arg = arguments[i]; switch (typeof arg) { case "object": if (typeof arg.nodeType == "undefined") { for (var name in arg) { var value = arg[name]; switch (name) { case "id": element.id = value; break; case "class": case "className": element.className = value; break; default: element.setAttribute(name, value); break; } } continue; } break; case "string": arg = d.createTextNode(arg); break; } element.appendChild(arg); } return element; }; prototype.text = function() { var start = 0; var arg = arguments[start++]; var d, text; if (typeof arg == "string") { d = document; text = arg; } else { d = arg; text = arguments[start++]; } return d.createTextNode(text); }; prototype.$ = function(id) { return typeof id == "string" ? document.getElementById(id) : id; }; prototype.add = function(name, method) { if (name in this.cases) { throw "'" + name + "' is in use."; } this.cases[name] = method; this.assertCounts[name] = 0; }; prototype.assertEqual = function(expected, actual, label) { var count = ++this.assertCounts[this.current]; if (typeof (expected) == typeof (actual) && expected == actual) { return true; } throw (label || "") + "[" + count + "]\n" + this.inspect(expected) + " (" + expected.length + ")\n" + this.inspect(actual) + " (" + actual.length + ")"; }; prototype.assertMatch = function(pattern, string, label) { var count = ++this.assertCounts[this.current]; if (pattern.test(string)) { return true; } throw (label || "") + "[" + count + "]\n" + this.inspect(pattern) + "\n" + this.inspect(string) + " (" + string.length + ")"; }; prototype.run = function() { var self = this var $ = this.$, element = this.element, text = this.text; var d = document; var cases = this.cases; var assertCounts = this.assertCounts; var names = []; for (var name in cases) { names.push(name); assertCounts[name] = 0; } var container = $("testunit"); var count; if (container) { container.parentNode.removeChild(container); } container = element( "table", { id: "testunit" }, element("caption", { id: "testunit.summary" }), element("tbody", { id: "testunit.body" })); d.body.appendChild(container); var body = $("testunit.body"); var summary = $("testunit.summary"); for (count = 0; count < names.length; count++) { body.appendChild( element("tr", element("td", names[count]), element("td", { id: "testcase." + count }, "..."))); } count = 0; var success = 0; var invoke = function() { if (count >= names.length) { self.current = null; return; } var current = names[count]; self.current = current; var cell = $("testcase." + count); cell.className = "current"; try { cases[current].call(self); cell.className = "success"; cell.replaceChild(text("OK"), cell.firstChild); success++; } catch (e) { cell.className = "failure"; var message = e.message || e.toString(); if (e.stack) { message = [ message, e.stack ].join("\n\n"); } cell.replaceChild( element("textarea", { id: "testcase." + count + ".textarea", rows: message.split("\n").length, cols: 80, readonly: "readonly" }), cell.firstChild); $("testcase." + count + ".textarea").value = message; } summary.innerHTML = success + " / " + names.length; count++; setTimeout(invoke, 10); }; invoke(); }; })(); trac-wysiwyg-0.12.0.3+r10725/0.12/tests/index.html0000644000175000017500000000401211463324376017121 0ustar wmbwmb tracwysiwyg test
 
trac-wysiwyg-0.12.0.3+r10725/0.12/tests/trac.js0000644000175000017500000000101010714574614016406 0ustar wmbwmbfunction addEvent(element, type, listener) { if (element.addEventListener) { element.addEventListener(type, listener, false); return true; } else if (element.attachEvent) { return element.attachEvent("on" + type, listener); } return false; } function getAncestorByTagName(node, tag) { tag = tag.toLowerCase(); do { node = node.parentNode; } while (node.nodeType == 1 && node.tagName.toLowerCase() != tag); return node.nodeType == 1 ? node : null; } trac-wysiwyg-0.12.0.3+r10725/0.12/MANIFEST.in0000644000175000017500000000014210672463456015524 0ustar wmbwmbinclude tracwysiwyg/htdocs/*.js include tracwysiwyg/htdocs/*.css include tracwysiwyg/htdocs/*.png trac-wysiwyg-0.12.0.3+r10725/0.12/bookmarklet.js0000644000175000017500000000471411314717400016630 0ustar wmbwmb/* * javascript:(function(d,u){var s=d.createElement('script');s.charset='utf-8';s.src=u;d.getElementsByTagName('head')[0].appendChild(s)})(document,'http://trac-hacks.org/svn/tracwysiwygplugin/0.12/bookmarklet.js') */ (function() { var w = window; var d = document; var base = 'http://trac-hacks.org/svn/tracwysiwygplugin/0.12/tracwysiwyg/htdocs/'; var head = d.getElementsByTagName('head')[0]; var script = d.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('charset', 'utf-8'); script.src = base + 'wysiwyg.js'; head.appendChild(script); var link = d.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type', 'text/css'); link.setAttribute('href', base + 'wysiwyg.css'); head.appendChild(link); function getTracPaths() { var paths = { stylesheets: [] }; var links = head.getElementsByTagName('link'); var length = links.length; for (var i = 0; i < length; i++) { var link = links[i]; var rel = (link.getAttribute('rel') || '').toLowerCase(); var type = (link.getAttribute('type') || '').toLowerCase(); var href = link.getAttribute('href') || ''; switch (rel) { case 'help': if (!paths.base && /\/wiki\/TracGuide$/.test(href)) { paths.base = href.slice(0, -14); } break; case 'search': if (!paths.search && !type && /\/search$/.test(href)) { paths.search = href; paths.base = href.slice(0, -6); } break; case 'stylesheet': if (/\/css\/trac\.css$/.test(href)) { paths.stylesheets.push(href); } break; } } if (paths.base && paths.stylesheets.length > 0) { if (!paths.search) { paths.search = paths.base + 'search'; } paths.stylesheets.push(base + 'editor.css'); return paths; } return null; } function lazy() { switch (typeof w.TracWysiwyg) { case 'undefined': setTimeout(lazy, 100); return; case 'function': TracWysiwyg.getTracPaths = getTracPaths; TracWysiwyg.initialize(); break; } } lazy(); })(); trac-wysiwyg-0.12.0.3+r10725/0.10/0000755000175000017500000000000011677636642013774 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/0000755000175000017500000000000011677636642016370 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/__init__.py0000644000175000017500000000400511361753254020465 0ustar wmbwmb# -*- coding: utf-8 -*- import re from trac.core import Component, implements from trac.config import ListOption from trac.web.api import IRequestFilter from trac.web.chrome import ITemplateProvider, add_link, add_stylesheet, add_script from trac.web.href import Href from trac.util.html import Markup __all__ = ['WysiwygModule'] class WysiwygModule(Component): implements(ITemplateProvider, IRequestFilter) wysiwyg_stylesheets = ListOption('tracwysiwyg', 'wysiwyg_stylesheets', doc="""Add stylesheets to the WYSIWYG editor""") # ITemplateProvider#get_htdocs_dirs def get_htdocs_dirs(self): from pkg_resources import resource_filename return [('tracwysiwyg', resource_filename(__name__, 'htdocs'))] # ITemplateProvider#get_templates_dirs def get_templates_dirs(self): return [] # IRequestFilter#pre_process_request def pre_process_request(self, req, handler): return handler # IRequestFilter#post_process_request def post_process_request(self, req, template, content_type): add_link(req, 'tracwysiwyg-base', req.href() or '/') stylesheets = ['chrome/common/css/trac.css', 'chrome/tracwysiwyg/editor.css'] stylesheets += self.wysiwyg_stylesheets for stylesheet in stylesheets: add_link(req, 'tracwysiwyg-stylesheet', _expand_filename(req, stylesheet)) add_stylesheet(req, 'tracwysiwyg/wysiwyg.css') add_script(req, 'tracwysiwyg/wysiwyg.js') footer = req.hdf['project.footer'] + '' req.hdf['project.footer'] = Markup(footer) return (template, content_type) def _expand_filename(req, filename): if filename.startswith('chrome/common/') and 'htdocs_location' in req.hdf: href = Href(req.hdf['htdocs_location']) return href(filename[14:]) if filename.startswith('/') or re.match(r'https?://', filename): href = Href(filename) return href() return req.href(filename) trac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/htdocs/0000755000175000017500000000000011677636642017654 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/htdocs/wysiwyg.css0000644000175000017500000001035611306772706022104 0ustar wmbwmbiframe.wysiwyg { border: 1px solid #d7d7d7; clear: both; display: block; } iframe.wysiwyg:focus { border: 1px solid #886; } .editor-toggle { float: right; font-size: 80%; } .wysiwyg-toolbar { border: solid #d7d7d7; border-width: 1px 1px 1px 0; height: 18px; width: 400px; float: left; } .wysiwyg-toolbar ul, .wysiwyg-toolbar li { list-style-type: none; margin: 0px; padding: 0px; } .wysiwyg-toolbar li { float: left; display: block; } .wysiwyg-toolbar li :link, .wysiwyg-toolbar li :visited { background: transparent url(toolbar.png) no-repeat; border: 1px solid #fff; border-left-color: #d7d7d7; cursor: default; display: block; width: 20px; height: 16px; color: #777; } .wysiwyg-toolbar li.selected :link, .wysiwyg-toolbar li.selected :visited { border: 1px solid #7c4; } .wysiwyg-toolbar li a:hover, .wysiwyg-toolbar li.selected a:hover { background-color: transparent; border: 1px solid #fb2; color: #886; } .wysiwyg-toolbar li a#wt-style { width: 62px; white-space: nowrap; overflow-x: hidden; line-height: 1.2; padding-left: 2px; padding-right: 2px; background-image: url(../common/desc.png); background-position: right bottom; } .wysiwyg-toolbar li a#wt-style span { display: none; } .wysiwyg-toolbar li.wysiwyg-menu-style a#wt-style span.wysiwyg-menu-style { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-paragraph a#wt-style span.wysiwyg-menu-paragraph { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading1 a#wt-style span.wysiwyg-menu-heading1 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading2 a#wt-style span.wysiwyg-menu-heading2 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading3 a#wt-style span.wysiwyg-menu-heading3 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading4 a#wt-style span.wysiwyg-menu-heading4 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading5 a#wt-style span.wysiwyg-menu-heading5 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading6 a#wt-style span.wysiwyg-menu-heading6 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-code a#wt-style span.wysiwyg-menu-code { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-quote a#wt-style span.wysiwyg-menu-quote { display: inline; } .wysiwyg-toolbar li a#wt-em { background-position: 0 0; } .wysiwyg-toolbar li a#wt-strong { background-position: 0 -16px; } .wysiwyg-toolbar li a#wt-underline { background-position: 0 -32px; } .wysiwyg-toolbar li a#wt-monospace { background-position: 0 -160px; } .wysiwyg-toolbar li a#wt-link { background-position: 0 -96px; } .wysiwyg-toolbar li a#wt-unlink { background-position: 0 -112px; } .wysiwyg-toolbar li a#wt-ol { background-position: 0 -176px; } .wysiwyg-toolbar li a#wt-ul { background-position: 0 -192px; } .wysiwyg-toolbar li a#wt-outdent { background-position: 0 -208px; } .wysiwyg-toolbar li a#wt-indent { background-position: 0 -224px; } .wysiwyg-toolbar li a#wt-table { background-position: 0 -240px; } .wysiwyg-toolbar li a#wt-hr { background-position: 0 -128px; } .wysiwyg-toolbar li a#wt-br { background-position: 0 -144px; } .wysiwyg-toolbar li a#wt-remove { background-position: 0 -256px; } .wysiwyg-toolbar li a#wt-decorationmenu, .wysiwyg-toolbar li a#wt-tablemenu { width: 10px; background-image: url(../common/desc.png); background-position: center bottom; } .wysiwyg-menu { border: 1px solid #d7d7d7; padding: 1px 2px; background-color: #fff; -moz-opacity: 0.90; opacity: 0.90; } .wysiwyg-menu p, .wysiwyg-menu h1, .wysiwyg-menu h2, .wysiwyg-menu h3, .wysiwyg-menu h4, .wysiwyg-menu h5, .wysiwyg-menu h6, .wysiwyg-menu pre.wiki, .wysiwyg-menu blockquote.citation { margin: 0px; } .wysiwyg-menu ul, .wysiwyg-menu li { list-style-type: none; margin: 0px; padding: 0px; } .wysiwyg-menu :link, .wysiwyg-menu :visited { display: block; padding: 1px; border: 1px solid #fff; color: #000; } .wysiwyg-menu .selected :link, .wysiwyg-menu .selected :visited { border: 1px solid #7c4; } .wysiwyg-menu a:hover, .wysiwyg-menu .selected a:hover { border: 1px solid #fb2; } .wysiwyg-menu .menu { font-size: 85%; } trac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/htdocs/wysiwyg.js0000644000175000017500000040167411642344654021737 0ustar wmbwmbvar TracWysiwyg = function(textarea) { var self = this; var editorMode = TracWysiwyg.getEditorMode(); this.autolink = true; this.textarea = textarea; var wikitextToolbar = textarea.previousSibling; if (wikitextToolbar && (wikitextToolbar.nodeType != 1 || wikitextToolbar.className != "wikitoolbar")) { wikitextToolbar = null; } this.wikitextToolbar = wikitextToolbar; var anonymous = document.createElement("div"); anonymous.innerHTML = ''; var frame = anonymous.firstChild; textarea.parentNode.insertBefore(frame, textarea.nextSibling); this.frame = frame; this.contentWindow = frame.contentWindow; this.contentDocument = this.contentWindow.document; this.initializeEditor(this.contentDocument); this.wysiwygToolbar = this.createWysiwygToolbar(document); this.styleMenu = this.createStyleMenu(document); this.decorationMenu = this.createDecorationMenu(document); this.tableMenu = this.createTableMenu(document); this.menus = [ this.styleMenu, this.decorationMenu, this.tableMenu ]; this.toolbarButtons = this.setupMenuEvents(); this.toggleEditorButtons = null; this.autolinkButton = null; this.savedWysiwygHTML = null; this.setupToggleEditorButtons(); this.setupSyncResizingTextArea(); var styleStatic = { position: "static", left: "-9999px", top: "-9999px" }; var styleAbsolute = { position: "absolute", left: "-9999px", top: "-9999px" }; switch (editorMode) { case "textarea": TracWysiwyg.setStyle(textarea, styleStatic); if (wikitextToolbar) { TracWysiwyg.setStyle(wikitextToolbar, styleStatic); } TracWysiwyg.setStyle(frame, { position: "absolute", left: "-9999px", top: TracWysiwyg.elementPosition(textarea).top + "px" }); TracWysiwyg.setStyle(this.wysiwygToolbar, styleAbsolute); TracWysiwyg.setStyle(this.autolinkButton.parentNode, { display: "none" }); textarea.setAttribute("tabIndex", ""); frame.setAttribute("tabIndex", "-1"); break; case "wysiwyg": TracWysiwyg.setStyle(textarea, { position: "absolute", left: "-9999px", top: TracWysiwyg.elementPosition(textarea).top + "px" }); if (wikitextToolbar) { TracWysiwyg.setStyle(wikitextToolbar, styleAbsolute); } TracWysiwyg.setStyle(frame, styleStatic); TracWysiwyg.setStyle(this.wysiwygToolbar, styleStatic); TracWysiwyg.setStyle(this.autolinkButton.parentNode, { display: "" }); textarea.setAttribute("tabIndex", "-1"); frame.setAttribute("tabIndex", ""); break; } frame.parentNode.insertBefore(this.wysiwygToolbar, frame); var body = document.body; for (var i = 0; i < this.menus.length; i++) { body.insertBefore(this.menus[i], body.firstChild); } var element = this.wikitextToolbar || this.textarea; element.parentNode.insertBefore(this.toggleEditorButtons, element); function lazySetup() { if (self.contentDocument.body) { var exception; try { self.execCommand("useCSS", false); } catch (e) { } try { self.execCommand("styleWithCSS", false); } catch (e) { } if (editorMode == "wysiwyg") { try { self.loadWysiwygDocument() } catch (e) { exception = e } } self.setupEditorEvents(); self.setupFormEvent(); if (exception) { self.textarea.style.position = "static"; if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "static"; } self.frame.style.position = self.wysiwygToolbar.style.position = "absolute"; self.autolinkButton.parentNode.style.display = "none"; alert("Failed to activate the wysiwyg editor."); throw exception; } } else { setTimeout(lazySetup, 100); } } lazySetup(); }; TracWysiwyg.prototype.initializeEditor = function(d) { var l = window.location; var html = []; html.push( '\n', '', '', '', ''); var stylesheets = TracWysiwyg.tracPaths.stylesheets; if (!stylesheets) { // Work around wysiwyg stops with Agilo var base = TracWysiwyg.tracPaths.base.replace(/\/*$/, "/"); stylesheets = [ base + "chrome/common/css/trac.css", base + "chrome/tracwysiwyg/editor.css" ]; } var length = stylesheets.length; for (var i = 0; i < length; i++) { html.push(''); } html.push('', '', '', ''); var first = !window.opera && d.addEventListener ? true : false; if (first) { d.designMode = "On"; } d.open(); d.write(html.join("")); d.close(); if (!first) { d.designMode = "On"; if (d != this.contentWindow.document) { this.contentDocument = this.contentWindow.document; } } }; TracWysiwyg.prototype.toggleAutolink = function() { this.autolink = !this.autolink; this.autolinkButton.checked = this.autolink; }; TracWysiwyg.prototype.listenerToggleAutolink = function(input) { var self = this; return function(event) { self.autolink = input.checked; }; }; TracWysiwyg.prototype.listenerToggleEditor = function(type) { var self = this; switch (type) { case "textarea": return function(event) { if (self.textarea.style.position == "absolute") { self.hideAllMenus(); self.loadTracWikiText(); self.textarea.style.position = "static"; self.textarea.setAttribute("tabIndex", ""); if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "static"; } self.frame.style.position = self.wysiwygToolbar.style.position = "absolute"; self.frame.setAttribute("tabIndex", "-1"); self.autolinkButton.parentNode.style.display = "none"; TracWysiwyg.setEditorMode(type); } self.focusTextarea(); }; case "wysiwyg": return function(event) { if (self.frame.style.position == "absolute") { try { self.loadWysiwygDocument(); } catch (e) { TracWysiwyg.stopEvent(event || window.event); alert("Failed to activate the wysiwyg editor."); throw e; } self.syncResizingTextArea(); self.textarea.style.position = "absolute"; self.textarea.setAttribute("tabIndex", "-1"); if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "absolute"; } self.frame.style.position = self.wysiwygToolbar.style.position = "static"; self.frame.setAttribute("tabIndex", ""); self.autolinkButton.parentNode.style.display = ""; TracWysiwyg.setEditorMode(type); } self.focusWysiwyg(); }; } }; TracWysiwyg.prototype.activeEditor = function() { return this.textarea.style.position == "absolute" ? "wysiwyg" : "textarea"; }; TracWysiwyg.prototype.setupFormEvent = function() { var self = this; function listener(event) { var textarea = self.textarea; try { if (textarea.style.position == "absolute") { var body = self.contentDocument.body; if (self.savedWysiwygHTML !== null && body.innerHTML != self.savedWysiwygHTML) { textarea.value = self.domToWikitext(body); } } } catch (e) { TracWysiwyg.stopEvent(event || window.event); } } addEvent(this.textarea.form, "submit", listener); }; TracWysiwyg.prototype.createWysiwygToolbar = function(d) { var html = [ '' ]; var div = d.createElement("div"); div.className = "wysiwyg-toolbar"; div.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return div; }; TracWysiwyg.prototype.createStyleMenu = function(d) { var html = [ '

Normal

', '

Header 1

', '

Header 2

', '

Header 3

', '

Header 4

', '
Header 5
', '
Header 6
', '
Code block
', '
Quote
' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.createDecorationMenu = function(d) { var html = [ '' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.createTableMenu = function(d) { var html = [ '' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.setupMenuEvents = function() { function addToolbarEvent(element, self, args) { var method = args.shift(); addEvent(element, "click", function(event) { var w = self.contentWindow; TracWysiwyg.stopEvent(event || w.event); var keepMenus = false, exception; try { keepMenus = method.apply(self, args) } catch (e) { exception = e } if (!keepMenus) { self.hideAllMenus(); } element.blur(); w.focus(); if (exception) { throw exception; } }); } function argsByType(self, name, element) { switch (name) { case "style": return [ self.toggleMenu, self.styleMenu, element ]; case "strong": return [ self.execDecorate, "bold" ]; case "em": return [ self.execDecorate, "italic" ]; case "underline": return [ self.execDecorate, "underline" ]; case "strike": return [ self.execDecorate, "strikethrough" ]; case "sub": return [ self.execDecorate, "subscript" ]; case "sup": return [ self.execDecorate, "superscript" ]; case "monospace": return [ self.execDecorate, "monospace" ]; case "decorationmenu": return [ self.toggleMenu, self.decorationMenu, element ]; case "remove": return [ self.execCommand, "removeformat" ]; case "paragraph": return [ self.formatParagraph ]; case "heading1": return [ self.formatHeaderBlock, "h1" ]; case "heading2": return [ self.formatHeaderBlock, "h2" ]; case "heading3": return [ self.formatHeaderBlock, "h3" ]; case "heading4": return [ self.formatHeaderBlock, "h4" ]; case "heading5": return [ self.formatHeaderBlock, "h5" ]; case "heading6": return [ self.formatHeaderBlock, "h6" ]; case "link": return [ self.createLink ]; case "unlink": return [ self.execCommand, "unlink" ]; case "ol": return [ self.insertOrderedList ]; case "ul": return [ self.insertUnorderedList ]; case "outdent": return [ self.outdent ]; case "indent": return [ self.indent ]; case "table": return [ self.insertTable ]; case "tablemenu": return [ self.toggleMenu, self.tableMenu, element ]; case "insert-row-before": return [ self.insertTableRow, false ]; case "insert-row-after": return [ self.insertTableRow, true ]; case "insert-col-before": return [ self.insertTableColumn, false ]; case "insert-col-after": return [ self.insertTableColumn, true ]; case "delete-row": return [ self.deleteTableRow ]; case "delete-col": return [ self.deleteTableColumn ]; case "code": return [ self.formatCodeBlock ]; case "quote": return [ self.formatQuoteBlock ]; case "hr": return [ self.insertHorizontalRule ]; case "br": return [ self.insertLineBreak ]; } return null; } function setup(container) { var elements = container.getElementsByTagName("a"); var length = elements.length; for (var i = 0; i < length; i++) { var element = elements[i]; var name = element.id.replace(/^wt-/, ""); var args = argsByType(this, name, element); if (args) { addToolbarEvent(element, this, args); buttons[name] = element; } } } var buttons = {}; setup.call(this, this.wysiwygToolbar); for (var i = 0; i < this.menus.length; i++) { setup.call(this, this.menus[i]); } return buttons; }; TracWysiwyg.prototype.toggleMenu = function(menu, element) { if (parseInt(menu.style.left, 10) < 0) { this.hideAllMenus(menu); var position = TracWysiwyg.elementPosition(element); TracWysiwyg.setStyle(menu, { left: position[0] + "px", top: (position[1] + 18) + "px" }); } else { this.hideAllMenus(); } return true; }; TracWysiwyg.prototype.hideAllMenus = function(except) { var menus = this.menus; var length = menus.length; for (var i = 0; i < length; i++) { if (menus[i] != except) { TracWysiwyg.setStyle(menus[i], { left: "-1000px", top: "-1000px" }); } } }; TracWysiwyg.prototype.execDecorate = function(name) { if (this.selectionContainsTagName("pre")) { return; } var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var position = this.getSelectionPosition(); var ancestor = {}; ancestor.start = getSelfOrAncestor(position.start, /^(?:a|tt)$/); ancestor.end = getSelfOrAncestor(position.end, /^(?:a|tt)$/); this.expandSelectionToElement(ancestor); if (name != "monospace") { this.execCommand(name); } else { this.execDecorateMonospace(); } this.selectionChanged(); }; TracWysiwyg.prototype.execDecorateMonospace = function() { var html = this.getSelectionHTML(); var removePattern = /|<\/tt>/gi; if (/^/i.test(html) && /<\/tt>$/i.test(html)) { html = html.replace(removePattern, ""); } else { var id = this.generateDomId(); html = '' + html.replace(removePattern, "") + ""; } this.insertHTML(html); var node = this.contentDocument.getElementById(id); if (node) { this.selectNode(node); } }; TracWysiwyg.prototype.execCommand = function(name, arg) { return this.contentDocument.execCommand(name, false, arg); }; TracWysiwyg.prototype.setupEditorEvents = function() { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var self = this; var d = this.contentDocument; var w = this.contentWindow; var ime = false; function listenerKeydown(event) { var method = null; var args = null; event = event || self.contentWindow.event; var keyCode = event.keyCode; switch (keyCode) { case 0x09: // TAB var range = self.getSelectionRange(); var stop = false; var element = getSelfOrAncestor(range.startContainer, /^(?:li|pre|table)$/); if (element) { switch (element.tagName.toLowerCase()) { case "li": self.execCommand(event.shiftKey ? "outdent" : "indent"); self.selectionChanged(); stop = true; break; case "pre": self.insertHTML("\t"); stop = true; break; case "table": if (getSelfOrAncestor(range.endContainer, "table") == element) { self.moveFocusInTable(!event.shiftKey); self.selectionChanged(); stop = true; } break; } } if (stop) { TracWysiwyg.stopEvent(event); } return; case 0xe5: ime = true; break; } switch ((keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0)) { case 0x40000042: // C-b method = self.execDecorate; args = [ "bold" ]; break; case 0x40000049: // C-i method = self.execDecorate; args = [ "italic" ]; break; case 0x4000004c: // C-l method = self.toggleAutolink; args = []; break; case 0x40000055: // C-u method = self.execDecorate; args = [ "underline" ]; break; case 0x40000059: // C-y method = self.execCommand; args = [ "redo" ]; break; case 0x4000005a: // C-z method = self.execCommand; args = [ "undo" ]; break; } if (method !== null) { TracWysiwyg.stopEvent(event); method.apply(self, args); self.selectionChanged(); } else if (keyCode) { var focus = self.getFocusNode(); if (!getSelfOrAncestor(focus, /^(?:p|li|h[1-6]|t[dh]|d[td]|pre|blockquote)$/)) { self.execCommand("formatblock", "

"); } } } addEvent(d, window.opera ? "keypress" : "keydown", listenerKeydown); function listenerKeypress(event) { event = event || self.contentWindow.event; var modifier = (event.ctrlKey ? 0x40000000 : 0) | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0); switch (event.charCode || event.keyCode) { case 0x20: // SPACE self.detectTracLink(event); return; case 0x0d: // ENTER self.detectTracLink(event); switch (modifier) { case 0: if (self.insertParagraphOnEnter) { self.insertParagraphOnEnter(event); } break; case 0x20000000: // Shift if (self.insertLineBreakOnShiftEnter) { self.insertLineBreakOnShiftEnter(event); } break; } return; } } addEvent(d, "keypress", listenerKeypress); function listenerKeyup(event) { var keyCode = event.keyCode; if (ime) { switch (keyCode) { case 0x20: // SPACE self.detectTracLink(event); break; } ime = false; } self.selectionChanged(); } addEvent(d, "keyup", listenerKeyup); function listenerMouseup(event) { self.selectionChanged(); } addEvent(d, "mouseup", listenerMouseup); function listenerClick(event) { self.hideAllMenus(); self.selectionChanged(); } addEvent(d, "click", listenerClick); }; TracWysiwyg.prototype.loadWysiwygDocument = function() { var d = this.contentDocument; var container = d.body; var tmp; while (tmp = container.lastChild) { container.removeChild(tmp); } var fragment = this.wikitextToFragment(this.textarea.value, d); container.appendChild(fragment); this.savedWysiwygHTML = container.innerHTML; }; TracWysiwyg.prototype.focusWysiwyg = function() { var self = this; var w = this.contentWindow; function lazy() { w.focus(); try { self.execCommand("useCSS", false); } catch (e) { } try { self.execCommand("styleWithCSS", false); } catch (e) { } self.selectionChanged(); } setTimeout(lazy, 10); }; TracWysiwyg.prototype.loadTracWikiText = function() { this.textarea.value = this.domToWikitext(this.contentDocument.body); this.savedWysiwygHTML = null; }; TracWysiwyg.prototype.focusTextarea = function() { this.textarea.focus(); }; TracWysiwyg.prototype.setupToggleEditorButtons = function() { var div = document.createElement("div"); var mode = TracWysiwyg.editorMode; var html = '' + '' + ' ' + ' ' + '  '; div.className = "editor-toggle"; div.innerHTML = html.replace(/@/g, ++TracWysiwyg.count); this.toggleEditorButtons = div; var buttons = div.getElementsByTagName("input"); for (var i = 0; i < buttons.length; i++) { var button = buttons[i]; switch (button.type) { case "checkbox": var listener = this.listenerToggleAutolink(button); addEvent(button, "click", listener); addEvent(button, "keypress", listener); this.autolinkButton = button; break; case "radio": addEvent(button, "click", this.listenerToggleEditor(button.value)); break; } } }; TracWysiwyg.prototype.setupSyncResizingTextArea = function() { var editrows = document.getElementById("editrows"); if (editrows) { var self = this; function timeout() { self.syncResizingTextArea(); } addEvent(editrows, "change", function() { setTimeout(timeout, 100) }); } }; TracWysiwyg.prototype.syncResizingTextArea = function() { var height = this.textarea.offsetHeight; var frame = this.frame; if (height > 0 && frame.height != height) { frame.height = height; } }; TracWysiwyg.prototype.detectTracLink = function(event) { if (!this.autolink) { return; } var range = this.getSelectionRange(); var node = range.startContainer; if (!node || !range.collapsed) { return; } var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; if (getSelfOrAncestor(node, /^(?:a|tt|pre)$/)) { return; } var offset = range.startOffset; if (node.nodeType != 3) { node = node.childNodes[offset]; while (node && node.nodeType != 3) { node = node.lastChild; } if (!node) { return; } offset = node.nodeValue.length; } else if (offset == 0) { node = node.previousSibling; if (!node || node.nodeType == 1) { return; } offset = node.nodeValue.length; } var startContainer = node; var endContainer = node; var text = [ node.nodeValue.substring(0, offset) ]; for ( ; ; ) { if (/[ \t\r\n\f\v]/.test(text[text.length - 1])) { break; } node = node.previousSibling; if (!node || node.nodeType == 1) { break; } text.push(node.nodeValue); startContainer = node; } text.reverse(); text = text.join(""); if (!text) { return; } var pattern = this.wikiDetectTracLinkPattern; pattern.lastIndex = /[^ \t\r\n\f\v]*$/.exec(text).index; var match, tmp; for (tmp = pattern.exec(text); tmp; tmp = pattern.exec(text)) { match = tmp; } if (!match) { return; } var label = match[0]; var link = this.normalizeTracLink(label); var id = this.generateDomId(); var anchor = this.createAnchor(link, label, { id: id, "data-tracwysiwyg-autolink": "true" }); var anonymous = this.contentDocument.createElement("div"); anonymous.appendChild(anchor); var html = anonymous.innerHTML; node = endContainer; var startOffset = match.index; while (startContainer != node && startOffset >= startContainer.nodeValue.length) { startOffset -= startContainer.nodeValue.length; startContainer = startContainer.nextSibling; } var endOffset = startOffset + label.length; endContainer = startContainer; while (endContainer != node && endOffset >= endContainer.nodeValue.length) { endOffset -= endContainer.nodeValue.length; endContainer = endContainer.nextSibling; } this.selectRange(startContainer, startOffset, endContainer, endOffset); offset = text.length - match.index - label.length; if (offset == 0) { switch (event.keyCode) { case 0x20: // SPACE this.insertHTML(html + "\u00a0"); TracWysiwyg.stopEvent(event); return; case 0x0d: // ENTER if (event.shiftKey) { if (window.opera || !anonymous.addEventListener) { this.insertHTML(html + "
"); if (window.opera) { anchor = this.contentDocument.getElementById(id); node = anchor.parentNode; offset = node.childNodes.length; this.selectRange(node, offset, node, offset); } TracWysiwyg.stopEvent(event); return; } } this.insertHTML(html); anchor = this.contentDocument.getElementById(id); node = event.shiftKey ? anchor.parentNode : anchor; offset = node.childNodes.length; this.selectRange(node, offset, node, offset); return; } } this.insertHTML(html); anchor = this.contentDocument.getElementById(id); node = anchor.nextSibling; if (!node) { node = anchor.parentNode; offset = node.childNodes.length; } this.selectRange(node, offset, node, offset); }; TracWysiwyg.prototype.formatParagraph = function() { if (this.selectionContainsTagName("table")) { return; } this.execCommand("formatblock", "

"); this.selectionChanged(); }; TracWysiwyg.prototype.formatHeaderBlock = function(name) { if (this.selectionContainsTagName("table")) { return; } this.execCommand("formatblock", "<" + name + ">"); this.selectionChanged(); }; TracWysiwyg.prototype.insertOrderedList = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("insertorderedlist"); this.selectionChanged(); }; TracWysiwyg.prototype.insertUnorderedList = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("insertunorderedlist"); this.selectionChanged(); }; TracWysiwyg.prototype.outdent = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("outdent"); }; TracWysiwyg.prototype.indent = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("indent"); }; TracWysiwyg.prototype.insertTable = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var id = this.generateDomId(); this.insertHTML(this.tableHTML(id, 2, 3)); var element = this.contentDocument.getElementById(id) if (element) { this.selectNodeContents(element); } this.selectionChanged(); }; TracWysiwyg.prototype._tableHTML = function(row, col) { var tr = "" + ((1 << col) - 1).toString(2).replace(/1/g, "") + ""; var html = [ '', '', ((1 << row) - 1).toString(2).replace(/1/g, tr), '', '
' ]; return html.join(""); }; TracWysiwyg.prototype._getFocusForTable = function() { var hash = { node: null, cell: null, row: null, table: null }; hash.node = this.getFocusNode(); hash.cell = hash.node ? TracWysiwyg.getSelfOrAncestor(hash.node, /^t[dh]$/) : null; hash.row = hash.cell ? TracWysiwyg.getSelfOrAncestor(hash.cell, "tr") : null; hash.table = hash.row ? TracWysiwyg.getSelfOrAncestor(hash.row, "table") : null; return hash; }; TracWysiwyg.prototype.insertTableRow = function(after) { var focus = this._getFocusForTable(); if (focus.table && focus.row) { var d = this.contentDocument; var cells = focus.row.getElementsByTagName("td"); var row = focus.table.insertRow(focus.row.rowIndex + (after ? 1 : 0)); for (var j = 0; j < cells.length; j++) { this.insertTableCell(row, 0); } } }; TracWysiwyg.prototype.insertTableColumn = function(after) { var focus = this._getFocusForTable(); if (focus.table && focus.cell) { var d = this.contentDocument; var rows = focus.table.rows; var length = rows.length; var cellIndex = focus.cell.cellIndex + (after ? 1 : 0); for (var i = 0; i < length; i++) { var row = rows[i]; this.insertTableCell(row, Math.min(cellIndex, row.cells.length)); } } }; TracWysiwyg.prototype.deleteTableRow = function() { var focus = this._getFocusForTable(); if (focus.table && focus.row) { focus.table.deleteRow(focus.row.rowIndex); } }; TracWysiwyg.prototype.deleteTableColumn = function() { var focus = this._getFocusForTable(); if (focus.table && focus.cell) { var rows = focus.table.rows; var length = rows.length; var cellIndex = focus.cell.cellIndex; for (var i = 0; i < length; i++) { var row = rows[i]; if (cellIndex < row.cells.length) { row.deleteCell(cellIndex); } } } }; TracWysiwyg.prototype.moveFocusInTable = function(forward) { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var focus = this.getFocusNode(); var element = getSelfOrAncestor(focus, /^(?:t[dhr]|table)$/); var target, table, rows, cells; switch (element.tagName.toLowerCase()) { case "td": case "th": focus = element; var row = getSelfOrAncestor(element, "tr"); cells = row.cells; if (forward) { if (focus.cellIndex + 1 < cells.length) { target = cells[focus.cellIndex + 1]; } else { table = getSelfOrAncestor(row, /^(?:tbody|table)$/); rows = table.rows; target = row.rowIndex + 1 < rows.length ? rows[row.rowIndex + 1].cells[0] : null; } } else { if (focus.cellIndex > 0) { target = cells[focus.cellIndex - 1]; } else { table = getSelfOrAncestor(row, /^(?:tbody|table)$/); rows = table.rows; if (row.rowIndex > 0) { cells = rows[row.rowIndex - 1].cells; target = cells[cells.length - 1]; } else { target = null; } } } break; case "tr": cells = element.cells; target = cells[forward ? 0 : cells.length - 1]; break; case "tbody": case "table": rows = element.rows; cells = rows[forward ? 0 : rows.length - 1].cells; target = cells[forward ? 0 : cells.length - 1]; break; } if (target) { this.selectNodeContents(target); } else if (table) { table = getSelfOrAncestor(table, "table"); var parent = table.parentNode; var elements = parent.childNodes; var length = elements.length; for (var offset = 0; offset < length; offset++) { if (table == elements[offset]) { if (forward) { offset++; } this.selectRange(parent, offset, parent, offset); } } } }; TracWysiwyg.prototype.formatCodeBlock = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var text = this.getSelectionText(); if (!text) { var node = this.getFocusNode(); while (node.nodeType == 3) { node = node.parentNode; } text = TracWysiwyg.getTextContent(node); this.selectNode(node); } var fragment = this.getSelectionFragment(); text = this.domToWikitext(fragment, { formatCodeBlock: true }).replace(/\s+$/, ""); var d = this.contentDocument; var anonymous = d.createElement("div"); var pre = d.createElement("pre"); pre.className = "wiki"; anonymous.appendChild(pre); if (text) { pre.appendChild(d.createTextNode(text)); } this.insertHTML(anonymous.innerHTML); this.selectionChanged(); }; TracWysiwyg.prototype.formatQuoteBlock = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var d = this.contentDocument; var anonymous = d.createElement("div"); var container = d.createElement("blockquote"); container.className = "citation"; var fragment = this.getSelectionFragment(); var childNodes = fragment.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { var child = childNodes[i]; var text = null; switch (child.nodeType) { case 1: if (child.tagName.toLowerCase() != "blockquote" || child.className != "citation") { text = TracWysiwyg.getTextContent(child); } break; case 3: text = child.nodeValue; break; default: continue; } if (text !== null) { if (!text) { continue; } var tmp = d.createElement("p"); tmp.appendChild(d.createTextNode(text)); child = tmp; } container.insertBefore(child, container.firstChild); } if (container.childNodes.length == 0) { container.appendChild(d.createElement("p")); } anonymous.appendChild(container); this.insertHTML(anonymous.innerHTML); this.selectionChanged(); }; TracWysiwyg.prototype.insertHorizontalRule = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } if (!this.execCommand("inserthorizontalrule")) { this.insertHTML("


"); } this.selectionChanged(); }; TracWysiwyg.prototype.createLink = function() { if (this.selectionContainsTagName("pre")) { return; } var focus = this.getFocusNode(); var anchor = TracWysiwyg.getSelfOrAncestor(focus, "a"); var expand = anchor || TracWysiwyg.getSelfOrAncestor(focus, "tt"); var currLink; if (anchor) { var attrs; var autolink = anchor.getAttribute("data-tracwysiwyg-autolink"); if (autolink === null) { attrs = TracWysiwyg.unserializeFromHref(anchor.href); autolink = attrs["data-tracwysiwyg-autolink"]; } if (autolink == "true") { var pattern = this.wikiDetectTracLinkPattern; pattern.lastIndex = 0; var label = TracWysiwyg.getTextContent(anchor); var match = pattern.exec(label); if (match && match.index == 0 && match[0].length == label.length) { currLink = this.normalizeTracLink(label); } } if (!currLink) { currLink = anchor.getAttribute("data-tracwysiwyg-link") || attrs["data-tracwysiwyg-link"] || anchor.href; } } else { currLink = ""; } if (expand) { this.selectNodeContents(expand); } var text = this.getSelectionText() || ""; var newLink = (prompt(text ? "Enter TracLink:" : "Insert TracLink:", currLink) || "").replace(/^\s+|\s+$/g, ""); if (newLink && newLink != currLink) { text = text || newLink; newLink = this.normalizeTracLink(newLink); var id = this.generateDomId(); var d = this.contentDocument; var anonymous = d.createElement("div"); anchor = this.createAnchor(newLink, text, { id: id }); anonymous.appendChild(anchor); this.insertHTML(anonymous.innerHTML); anchor = d.getElementById(id); if (anchor) { this.selectNodeContents(anchor); } } this.selectionChanged(); }; TracWysiwyg.prototype.createAnchor = function(link, label, attrs) { var d = this.contentDocument; var anchor = d.createElement("a"); var href = {}; for (var name in attrs) { var value = attrs[name]; href[name] = value; anchor.setAttribute(name, value); } href["data-tracwysiwyg-link"] = link; anchor.href = TracWysiwyg.serializeToHref(href); anchor.title = link; anchor.setAttribute("data-tracwysiwyg-link", link); anchor.setAttribute("onclick", "return false;"); anchor.appendChild(d.createTextNode(label)); return anchor; }; TracWysiwyg.prototype.collectChildNodes = function(dest, source) { var childNodes = source.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { dest.insertBefore(childNodes[i], dest.firstChild); } }; TracWysiwyg.prototype.generateDomId = function() { var d = this.contentDocument; for ( ; ; ) { var id = "tmp-" + (new Date().valueOf().toString(36)); if (!d.getElementById(id)) { return id; } } }; TracWysiwyg.prototype.selectionChanged = function() { var status = { strong: false, em: false, underline: false, strike: false, sub: false, sup: false, monospace: false, paragraph: false, heading1: false, heading2: false, heading3: false, heading4: false, heading5: false, heading6: false, link: false, ol: false, ul: false, outdent: false, indent: false, table: false, code: false, quote: false, hr: false, br: false }; var tagNameToKey = { b: "strong", i: "em", u: "underline", del: "strike", tt: "monospace", p: "paragraph", h1: "heading1", h2: "heading2", h3: "heading3", h4: "heading4", h5: "heading5", h6: "heading6", a: "link", pre: "code", blockquote: "quote" }; var position = this.getSelectionPosition(); var node; if (position.start) { node = position.start == position.end ? position.start.firstChild : position.start.nextSibling; node = node || position.start; } else { node = null; } while (node) { if (node.nodeType == 1) { var name = node.tagName.toLowerCase(); if (name in tagNameToKey) { name = tagNameToKey[name]; } status[name] = true; } node = node.parentNode; } var toolbarButtons = this.toolbarButtons; for (var name in status) { var button = toolbarButtons[name]; if (button) { var parent = button.parentNode; parent.className = (parent.className || "").replace(/ *\bselected\b|$/, status[name] ? " selected" : ""); } } var styles = [ "quote", "paragraph", "code", "heading1", "heading2", "heading3", "heading4", "heading5", "heading6" ]; var styleButton = toolbarButtons["style"]; var styleButtonClass = "wysiwyg-menu-style"; for (var i = 0; i < styles.length; i++) { var name = styles[i]; if (status[name]) { styleButtonClass = "wysiwyg-menu-" + name; break; } } styleButton.parentNode.className = styleButtonClass; }; (function() { var _linkScheme = "[\\w.+-]+"; // cf. WikiSystem.XML_NAME, http://www.w3.org/TR/REC-xml/#id var _xmlName = "[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD](?:[-:_.A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]*[-_A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD])?" var _quotedString = "'[^']+'|" + '"[^"]+"'; var _changesetId = "(?:\\d+|[a-fA-F\\d]{6,})"; var _ticketLink = "#\\d+"; var _reportLink = "\\{\\d+\\}"; var _changesetPath = "/[^\\]]*"; var _changesetLinkBracket = "\\[" + _changesetId + "(?:" + _changesetPath + ")?\\]"; var _changesetLinkRev = "r" + _changesetId + "\\b(?!:" + _changesetId + ")"; var _logLinkBracket = "\\[" + _changesetId + "[-:]" + _changesetId + "(?:" + _changesetPath + ")?\\]"; var _logLinkRev = "r" + _changesetId + "[-:]" + _changesetId + "\\b"; var _tracLink = _linkScheme + ":(?:" + _quotedString + "|[a-zA-Z0-9/?!#@](?:(?:\\|(?=[^| \\t\\r\\f\\v])|[^|<> \\t\\r\\f\\v])*[a-zA-Z0-9/=])?)"; var _wikiPageName = "[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+(?:#[\\w:][-\\w\\d.:]*)?" + "(?=:(?:$|[ \\t\\r\\f\\v])|[^:a-zA-Z]|[ \\t\\r\\f\\v]|$)"; var wikiInlineRules = []; wikiInlineRules.push("!?'''''"); // 1. bolditalic wikiInlineRules.push("!?'''"); // 2. bold wikiInlineRules.push("!?''"); // 3. italic wikiInlineRules.push("!?__"); // 4. underline wikiInlineRules.push("!?~~"); // 5. strike wikiInlineRules.push("!?,,"); // 6. subscript wikiInlineRules.push("!?\\^"); // 7. superscript wikiInlineRules.push("!?\\{\\{\\{.*?\\}\\}\\}"); // 8. code block wikiInlineRules.push("!?`.*?`"); // 9. inline wikiInlineRules.push("[!&]?" + _ticketLink); // 10. ticket wikiInlineRules.push("!?" + _reportLink); // 11. report // 12. changeset wikiInlineRules.push("!?" + _changesetLinkBracket + "|(?:\\b|!)" + _changesetLinkRev); // 13. log wikiInlineRules.push("!?" + _logLinkBracket + "|(?:\\b|!)" + _logLinkRev); wikiInlineRules.push("!?" + _tracLink); // 14. wiki:TracLinks wikiInlineRules.push("!?\\[(?:" // 15. [wiki:TracLinks label] or [/relative label] + "[/.#][^ \\t\\r\\f\\v[\\]]*|" + _linkScheme + ":(?:" + _quotedString + "|[^\\] \\t\\r\\f\\v]*)|" + _wikiPageName + "[ \\t\\r\\f\\v]+(?:" + _quotedString + "|[^\\]]+)" + ")(?:[ \\t\\r\\f\\v]+(?:" + _quotedString + "|[^\\]]+))?\\]"); // 16. [[macro]] wikiInlineRules.push("!?\\[\\[[\\w/+-]+(?:\\]\\]|\\(.*?\\)\\]\\])"); // 17. WikiPageName wikiInlineRules.push("(?:\\b|!)" + _wikiPageName); // 18. ["internal free link"] wikiInlineRules.push("!?\\[(?:" + _quotedString + ")\\]"); var wikiRules = []; wikiRules.push.apply(wikiRules, wikiInlineRules); wikiRules.push("^(?: *>)+[ \\t\\r\\f\\v]*"); // -1. citation // -2. header wikiRules.push("^[ \\t\\r\\f\\v]*={1,6}[ \\t\\r\\f\\v]+.*?[ \\t\\r\\f\\v]+={1,6}(?:[ \\t\\r\\f\\v]+#" + _xmlName + ")?[ \\t\\r\\f\\v]*$"); // -3. list wikiRules.push("^ +(?:[-*]|[0-9]+\\.|[a-zA-Z]\\.|[ivxIVX]{1,5}\\.) "); // -4. definition wikiRules.push("^[ \\t\\r\\f\\v]+(?:`[^`]*`|\\{\\{\\{.*?\\}\\}\\}|[^`{:]|:[^:])+::(?:[ \\t\\r\\f\\v]+|$)"); wikiRules.push("^[ \\t\\r\\f\\v]+(?=[^ \\t\\r\\f\\v])"); // -5. leading space wikiRules.push("\\|\\|[ \\t\\r\\f\\v]*$"); // -6. closing table row wikiRules.push("\\|\\|"); // -7. cell var wikiSyntaxRules = []; wikiSyntaxRules.push(_ticketLink); wikiSyntaxRules.push(_reportLink); wikiSyntaxRules.push(_changesetLinkBracket); wikiSyntaxRules.push(_changesetLinkRev); wikiSyntaxRules.push(_logLinkBracket); wikiSyntaxRules.push(_logLinkRev); var wikiDetectTracLinkRules = []; wikiDetectTracLinkRules.push(_ticketLink); wikiDetectTracLinkRules.push(_reportLink); wikiDetectTracLinkRules.push(_changesetLinkBracket); wikiDetectTracLinkRules.push("\\b" + _changesetLinkRev); wikiDetectTracLinkRules.push(_logLinkBracket); wikiDetectTracLinkRules.push("\\b" + _logLinkRev); wikiDetectTracLinkRules.push(_tracLink); wikiDetectTracLinkRules.push("\\b" + _wikiPageName); var wikiInlineRulesPattern = new RegExp("(?:" + wikiInlineRules.join("|") + ")", "g"); var wikiRulesPattern = new RegExp("(?:(" + wikiRules.join(")|(") + "))", "g"); var wikiSyntaxPattern = new RegExp("^(?:" + wikiSyntaxRules.join("|") + ")$"); var wikiSyntaxLogPattern = new RegExp("^[\\[r]" + _changesetId + "[-:]"); var wikiDetectTracLinkPattern = new RegExp("(?:" + wikiDetectTracLinkRules.join("|") + ")", "g"); TracWysiwyg.prototype._linkScheme = _linkScheme; TracWysiwyg.prototype._quotedString = _quotedString; TracWysiwyg.prototype._changesetId = _changesetId; TracWysiwyg.prototype._tracLink = _tracLink; TracWysiwyg.prototype._wikiPageName = _wikiPageName; TracWysiwyg.prototype.wikiInlineRules = wikiInlineRules; TracWysiwyg.prototype.wikiRules = wikiRules; TracWysiwyg.prototype.xmlNamePattern = new RegExp("^" + _xmlName + "$"); TracWysiwyg.prototype.wikiInlineRulesPattern = wikiInlineRulesPattern; TracWysiwyg.prototype.wikiRulesPattern = wikiRulesPattern; TracWysiwyg.prototype.wikiSyntaxPattern = wikiSyntaxPattern; TracWysiwyg.prototype.wikiSyntaxLogPattern = wikiSyntaxLogPattern; TracWysiwyg.prototype.wikiDetectTracLinkPattern = wikiDetectTracLinkPattern; })(); TracWysiwyg.prototype.normalizeTracLink = function(link) { link = this.convertWikiSyntax(link); if (/^[\/.#]/.test(link)) { link = encode(link); } if (!/^[\w.+-]+:/.test(link)) { link = "wiki:" + link; } if (/^wiki:[^\"\']/.test(link) && /\s/.test(link)) { if (link.indexOf('"') === -1) { link = 'wiki:"' + link + '"'; } else if (link.indexOf("'") === -1) { link = "wiki:'" + link + "'"; } else { link = 'wiki:"' + link.replace(/"/g, "%22") + '"'; } } return link; }; TracWysiwyg.prototype.convertWikiSyntax = function(link) { var match = this.wikiSyntaxPattern.exec(link); if (match) { switch (match[0].charCodeAt(0)) { case 0x7b: // "{" link = "report:" + link.slice(1, -1); break; case 0x5b: // "[" link = (this.wikiSyntaxLogPattern.test(link) ? "log:@" : "changeset:") + link.slice(1, -1); break; case 0x23: // # link = "ticket:" + link.substring(1); break; case 0x72: // r link = (this.wikiSyntaxLogPattern.test(link) ? "log:@" : "changeset:") + link.substring(1); break; } } return link; }; TracWysiwyg.prototype.isInlineNode = function(node) { if (node) { switch (node.nodeType) { case 1: return (node.tagName.toLowerCase() in this.wikiInlineTags); case 3: return true; } } return false; }; (function() { var blocks = { p: true, blockquote: true, div: true, li: true, ul: true, ol: true, dl: true, dt: true, dd: true, h1: true, h2: true, h3: true, h4: true, h5: true, h6: true, table: true, thead: true, tbody: true, tr: true, td: true, th: true }; function generator(prop, blocks) { return function (node) { if (!node) { return false; } for ( ; ; ) { if (node[prop]) { return false; } node = node.parentNode; if (!node) { return true; } if (node.nodeType == 1 && node.tagName.toLowerCase() in blocks) { return true; } } return false; }; } TracWysiwyg.prototype.isLastChildInBlockNode = generator("nextSibling", blocks); TracWysiwyg.prototype.isFirstChildInBlockNode = generator("previousSibling", blocks); })(); TracWysiwyg.prototype.wikitextToFragment = function(wikitext, contentDocument) { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var _linkScheme = this._linkScheme; var _quotedString = this._quotedString; var wikiInlineRules = this.wikiInlineRules; var wikiRulesPattern = new RegExp(this.wikiRulesPattern.source, "g"); var self = this; var fragment = contentDocument.createDocumentFragment(); var holder = fragment; var lines = wikitext.split("\n"); var codeText = null; var currentHeader = null; var quoteDepth = []; var listDepth = []; var decorationStatus; var decorationStack; var inCodeBlock, inParagraph, inDefList, inTable, inTableRow; inCodeBlock = inParagraph = inDefList = inTable = inTableRow = false; function handleCodeBlock(line) { if (/^ *\{\{\{ *$/.test(line)) { inCodeBlock++; if (inCodeBlock == 1) { closeParagraph(); codeText = []; } else { codeText.push(line); } } else if (/^ *\}\}\} *$/.test(line)) { inCodeBlock--; if (inCodeBlock == 0) { var pre = contentDocument.createElement("pre"); pre.className = "wiki"; pre.appendChild(contentDocument.createTextNode(codeText.join( pre.addEventListener && !window.opera ? "\n" : "\n\r"))); holder.appendChild(pre); codeText = []; } else { codeText.push(line); } } else { codeText.push(line); } } function handleCitation(value) { var quote = /^(?: *>)+/.exec(value)[0]; var depth = quote.replace(/ +/g, "").length; if (depth > quoteDepth.length) { closeToFragment("blockquote"); while (depth > quoteDepth.length) { openQuote((new RegExp("^(?: *>){" + (quoteDepth.length + 1) + "}")).exec(quote)[0].length, true); } } else if (depth == quoteDepth.length) { // nothing to do } else { closeParagraph(); while (depth < quoteDepth.length) { closeQuote(); } } } function openQuote(length, citation) { var target = holder; if (target != fragment) { target = getSelfOrAncestor(target, "blockquote"); } var element = contentDocument.createElement("blockquote"); if (citation) { element.className = "citation"; } (target || fragment).appendChild(element); holder = element; quoteDepth.push(length); } function closeQuote() { var target = getSelfOrAncestor(holder, "blockquote"); holder = target.parentNode; quoteDepth.pop(); } function handleHeader(line) { var match = /^\s*(=+)[ \t\r\f\v]+.*?[ \t\r\f\v]+(=+)(?:[ \t\r\f\v]+#([^ \t\r\f\v]+)[ \t\r\f\v]*)?$/.exec(line); if (!match || match[1].length != match[2].length) { return null; } closeToFragment(); var tag = "h" + match[1].length; var element = contentDocument.createElement(tag); if (match[3]) { element.id = match[3]; } fragment.appendChild(element); holder = element; return tag; } function closeHeader() { if (currentHeader) { var target = getSelfOrAncestor(holder, currentHeader); holder = target.parentNode; currentHeader = null; } } function handleInline(name) { if (name == "bolditalic") { if (decorationStatus.italic) { handleInline("italic"); handleInline("bold"); } else { handleInline("bold"); handleInline("italic"); } return; } var d = contentDocument; if (decorationStatus[name]) { var tagNames = []; for (var index = decorationStack.length - 1; index >= 0; index--) { var tagName = holder.tagName; holder = holder.parentNode; if (decorationStack[index] == name) { break; } tagNames.push(tagName); } decorationStack.splice(index, 1); decorationStatus[name] = false; while (tagNames.length > 0) { var element = d.createElement(tagNames.pop()); holder.appendChild(element); holder = element; } return; } var tagName; switch (name) { case "bold": tagName = "b"; break; case "italic": tagName = "i"; break; case "underline": tagName = "u"; break; case "strike": tagName = "del"; break; case "subscript": tagName = "sub"; break; case "superscript": tagName = "sup"; break; } if (holder == fragment) { openParagraph(); } element = d.createElement(tagName); holder.appendChild(element); holder = element; decorationStatus[name] = true; decorationStack.push(name); } function handleInlineCode(value, length) { var d = contentDocument; var element = d.createElement("tt"); value = value.slice(length, -length); if (value.length > 0) { element.appendChild(d.createTextNode(value)); holder.appendChild(element); } } function createAnchor(link, label) { var anchor = self.createAnchor(link, label); holder.appendChild(anchor); } function handleTracLinks(value) { var match = handleTracLinks.pattern.exec(value); if (match) { var link = match[1]; if (!/^(?:[\w.+-]+:|[\/.#].*)/.test(link)) { link = "wiki:" + link; } var text = (match[2] || match[1].replace(/^[\w.+-]+:/, "")).replace(/^(["'])(.*)\1$/g, "$2"); createAnchor(link, text); } else { holder.appendChild(contentDocument.createTextNode(value)); } } handleTracLinks.pattern = new RegExp("\\[" + "((?:" + _linkScheme + ":)?(?:" + _quotedString + "|[^\\]\\s]+))" + "(?:\\s+(.*))?\\]"); function handleTracWikiLink(value) { createAnchor(value, value); } function handleWikiPageName(name, label) { createAnchor("wiki:" + name, label || name); } function handleTracOtherLinks(value) { createAnchor(self.convertWikiSyntax(value), value); } function handleTracTicketLink(value) { if (!/^&/.test(value)) { handleTracOtherLinks(value); return true; } return false; } function handleList(value) { var match = /^( +)(?:([-*])|((?:([0-9]+)|([a-z])|([A-Z])|[ivxIVX]{1,5})))/.exec(value); var tag, className, depth, start; if (!match) { holder.appendChild(contentDocument.createTextNode(value)); return; } depth = match[1].length; if (match[2]) { tag = "ul"; } else if (match[3]) { tag = "ol"; switch (match[3]) { case "0": className = "arabiczero"; break; case "1": break; case "i": className = "lowerroman"; break; case "I": className = "upperroman"; break; default: if (match[4]) { start = parseInt(match[4], 10); } else if (match[5]) { className = "loweralpha"; } else if (match[6]) { className = "upperalpha"; } break; } } var last = listDepth.length - 1; if (depth > (last >= 0 ? listDepth[last] : 0)) { closeToFragment("li"); openList(tag, className, start, depth); } else { var container, list; if (listDepth.length > 1 && depth < listDepth[last]) { do { if (depth >= listDepth[last]) { break; } closeList(); last = listDepth.length - 1; } while (listDepth.length > 1); container = holder; } else { list = getSelfOrAncestor(holder, "li"); self.appendBogusLineBreak(list); container = list.parentNode; } if (tag != container.tagName.toLowerCase()) { holder = container.parentNode; listDepth.pop(); openList(tag, className, start, depth); } else { var tmp = contentDocument.createElement("li"); container.appendChild(tmp); holder = tmp; listDepth[last] = depth; } } } function openList(tag, className, start, depth) { var d = contentDocument; var h = holder; var container = d.createElement(tag); if (className) { container.className = className; } if (start) { container.setAttribute("start", start); } var list = d.createElement("li"); container.appendChild(list); var target; if (h == fragment) { target = fragment; } else { target = getSelfOrAncestor(h, "li"); target = target ? target.parentNode : h; } target.appendChild(container); holder = list; listDepth.push(depth); } function closeList() { var h = holder; var target = getSelfOrAncestor(h, "li"); if (target) { self.appendBogusLineBreak(target); holder = target.parentNode.parentNode; } else { holder = h.parentNode; } listDepth.pop(); } function handleDefinition(value) { var d = contentDocument; var h = holder; var dl = null; if (inDefList) { dl = getSelfOrAncestor(h, "dl"); } else { closeParagraph(); dl = d.createElement("dl"); fragment.appendChild(dl); inDefList = true; } var match = /^ +(.*?)\s*::/.exec(value); var dt = d.createElement("dt"); var oneliner = self.wikitextToOnelinerFragment(match[1], d); dt.appendChild(oneliner); dl.appendChild(dt); var dd = d.createElement("dd"); dl.appendChild(dd); holder = dd; } function closeDefList() { var element = getSelfOrAncestor(holder, "dl"); if (element) { holder = element.parentNode; } inDefList = false; } function handleIndent(value) { var depth = value.length; var last = quoteDepth.length - 1; if (depth > (last >= 0 ? quoteDepth[last] : 0)) { closeParagraph(); closeTable(); openQuote(depth, false); } else { while (quoteDepth.length > 0) { if (depth >= quoteDepth[last]) { break; } closeToFragment("blockquote"); closeQuote(); last = quoteDepth.length - 1; } quoteDepth[last] = depth; } } function openParagraph() { if (!inParagraph) { var element = contentDocument.createElement("p"); holder.appendChild(element); holder = element; inParagraph = true; } } function closeParagraph() { if (inParagraph) { var target = holder; if (target != fragment) { target = getSelfOrAncestor(target, "p"); self.appendBogusLineBreak(target); } holder = target.parentNode; inParagraph = false; } } function handleTableCell(action) { var d = contentDocument; var h, table, tbody; if (!inTable) { closeToFragment("blockquote"); h = holder; table = d.createElement("table"); table.className = "wiki"; tbody = d.createElement("tbody"); table.appendChild(tbody); h.appendChild(table); inTable = true; inTableRow = false; } else { h = holder; tbody = getSelfOrAncestor(h, "tbody"); } if (inTableRow) { var cell = getSelfOrAncestor(h, "td"); if (cell) { self.appendBogusLineBreak(cell); } } var row; switch (action) { case 1: row = d.createElement("tr"); tbody.appendChild(row); inTableRow = true; break; case 0: row = getSelfOrAncestor(h, "tr"); break; case -1: if (inTableRow) { var target = getSelfOrAncestor(h, "tr"); holder = target.parentNode; inTableRow = false; } return; } var cell = d.createElement("td"); row.appendChild(cell); holder = cell; decorationStatus = {}; } function closeTable() { if (inTable) { var target = getSelfOrAncestor(holder, "table"); holder = target.parentNode; inTable = inTableRow = false; } } function closeToFragment(stopTag) { var element = holder; var _fragment = fragment; stopTag = stopTag ? stopTag.toLowerCase() : null; while (element != _fragment) { var tag = element.tagName.toLowerCase(); if (tag == stopTag) { holder = element; return; } var method; switch (tag) { case "p": method = closeParagraph; break; case "li": case "ul": case "ol": method = closeList; break; case "dd": method = closeDefList; break; case "blockquote": method = closeQuote; break; case "td": case "tr": case "tbody": case "table": method = closeTable; break; default: break; } if (method) { method(); element = holder; } else { element = element.parentNode; } } holder = _fragment; } function getMatchNumber(match) { var length = match.length; for (var i = 1; i < length; i++) { if (match[i]) { var inlines = wikiInlineRules.length return i <= inlines ? i : inlines - i; } } return null; } for (var indexLines = 0; indexLines < lines.length; indexLines++) { var line = lines[indexLines].replace(/\r$/, ""); if (inCodeBlock || /^ *\{\{\{ *$/.test(line)) { handleCodeBlock(line); continue; } if (/^----/.test(line)) { closeToFragment(); fragment.appendChild(contentDocument.createElement("hr")); continue; } if (line.length == 0) { closeToFragment(); continue; } line = line.replace(/\t/g, " "); line = line.replace(/\u00a0/g, " "); wikiRulesPattern.lastIndex = 0; var prevIndex = wikiRulesPattern.lastIndex; decorationStatus = {}; decorationStack = []; for ( ; ; ) { var match = wikiRulesPattern.exec(line); var matchNumber = null; var text = null; if (match) { matchNumber = getMatchNumber(match); if (prevIndex < match.index) { text = line.substring(prevIndex, match.index); } } else { text = line.substring(prevIndex); } if ((prevIndex == 0 && text || match && match.index == 0 && matchNumber > 0) && (!inParagraph || quoteDepth.length > 0) && (!inDefList || !/^ /.test(line))) { closeToFragment(); } if (text || match && matchNumber > 0) { if (inParagraph && (prevIndex == 0 || /^(?:(?: *>)+\s*|\s+)$/.test(line.substring(0, prevIndex)))) { text = text ? (" " + text) : " "; } if (!inTable && quoteDepth.length > 0 || holder == fragment) { if (!inParagraph) { openParagraph(); } } if (text) { holder.appendChild(contentDocument.createTextNode(text)); } } if (!match) { break; } prevIndex = wikiRulesPattern.lastIndex; var matchText = match[0]; if (!/^!/.test(matchText)) { // start '!' switch (matchNumber) { case 1: // bolditalic handleInline("bolditalic"); continue; case 2: // bold handleInline("bold"); continue; case 3: // italic handleInline("italic"); continue; case 4: // underline handleInline("underline"); continue; case 5: // strike handleInline("strike"); continue; case 6: // subscript handleInline("subscript"); continue; case 7: // superscript handleInline("superscript"); continue; case 8: // code block handleInlineCode(matchText, 3); continue; case 9: // inline handleInlineCode(matchText, 1); continue; case 10: // ticket if (handleTracTicketLink(matchText)) { continue; } break; case 11: // report case 12: // changeset case 13: // log handleTracOtherLinks(matchText); continue; case 14: // wiki:TracLinks handleTracWikiLink(matchText); continue; case 15: // [wiki:TracLinks label] handleTracLinks(matchText); continue; case 16: // [[macro]] break; case 17: // WikiPageName handleWikiPageName(matchText); continue; case 18: // ["internal free link"] handleWikiPageName(matchText.slice(1, -1), matchText.slice(2, -2)); continue; case -1: // citation handleCitation(matchText); continue; case -2: // header currentHeader = handleHeader(matchText); if (currentHeader) { line = line.replace(/[ \t\r\f\v]+=+(?:[ \t\r\f\v]+#[^ \t\r\f\v]+)?[ \t\r\f\v]*$/, ""); wikiRulesPattern.lastIndex = prevIndex = line.match(/^\s*=+[ \t\r\f\v]*/)[0].length; continue; } break; case -3: // list handleList(matchText) continue; case -4: // definition handleDefinition(matchText); continue; case -5: // leading space if (listDepth.length == 0 && !inDefList) { handleIndent(matchText); continue; } if (!this.isInlineNode(holder.lastChild)) { continue; } matchText = matchText.replace(/^\s+/, " "); break; case -6: // closing table row if (inTable) { handleTableCell(-1); continue; } break; case -7: // cell if (quoteDepth.length > 0 && match.index == 0) { closeToFragment(); } for ( ; ; ) { // lookahead next double pipes var m = wikiRulesPattern.exec(line); switch (m ? getMatchNumber(m) : 0) { case 0: case -6: case -7: var end = m ? m.index : line.length; if (prevIndex < end) { line = line.substring(0, prevIndex) + line.substring(prevIndex, end).replace(/^[ \t\r\n\f\v]+|[ \t\r\n\f\v]+$/g, "") + line.substring(end); } break; default: continue; } break; } wikiRulesPattern.lastIndex = prevIndex; handleTableCell(inTableRow ? 0 : 1); continue; } } if (matchText) { if (listDepth.length == 0 && !currentHeader && !inDefList && !inTable) { openParagraph(); } var tmp; if (matchNumber == 16) { tmp = /^!?\[\[br\]\]$/i.test(matchText) ? (matchText.charCodeAt(0) == 0x21 ? contentDocument.createTextNode(matchText.substring(1)) : contentDocument.createElement("br")) : contentDocument.createTextNode(matchText); } else { tmp = contentDocument.createTextNode(/^!/.test(matchText) ? matchText.substring(1) : matchText); } holder.appendChild(tmp); } } if (currentHeader) { closeHeader(); } if (inTable) { handleTableCell(-1); } } closeToFragment(); return fragment; }; TracWysiwyg.prototype.wikitextToOnelinerFragment = function(wikitext, contentDocument) { var source = this.wikitextToFragment(wikitext, contentDocument); var fragment = contentDocument.createDocumentFragment(); this.collectChildNodes(fragment, source.firstChild); return fragment; }; TracWysiwyg.prototype.wikiOpenTokens = { "h1": "= ", "h2": "== ", "h3": "=== ", "h4": "==== ", "h5": "===== ", "h6": "====== ", "b": "'''", "strong": "'''", "i": "''", "em": "''", "u": "__", "del": "~~", "strike": "~~", "sub": ",,", "sup": "^", "hr": "----\n", "dl": true, "dt": " ", "dd": " ", "table": true, "tbody": true }; TracWysiwyg.prototype.wikiCloseTokens = { "#text": true, "a": true, "tt": true, "h1": " =", "h2": " ==", "h3": " ===", "h4": " ====", "h5": " =====", "h6": " ======", "b": "'''", "strong": "'''", "i": "''", "em": "''", "u": "__", "del": "~~", "strike": "~~", "sub": ",,", "sup": "^", "br": true, "hr": true, "dl": "\n", "dt": "::", "dd": "\n", "tbody": true, "tr": "||\n", "td": true, "th": true }; TracWysiwyg.prototype.wikiBlockTags = { "h1": true, "h2": true, "h3": true, "h4": true, "h5": true, "h6": true, "table": true, "dl": true, "hr": true }; TracWysiwyg.prototype.wikiInlineTags = { "a": true, "tt": true, "b": true, "strong": true, "i": true, "em": true, "u": true, "del": true, "strike": true, "sub": true, "sup": true, "br": true, "span": true }; TracWysiwyg.prototype.domToWikitext = function(root, options) { options = options || {}; var formatCodeBlock = !!options.formatCodeBlock; var self = this; var getTextContent = TracWysiwyg.getTextContent; var wikiOpenTokens = this.wikiOpenTokens; var wikiCloseTokens = this.wikiCloseTokens; var wikiInlineTags = this.wikiInlineTags; var wikiBlockTags = this.wikiBlockTags; var xmlNamePattern = this.xmlNamePattern; var wikiInlineRulesPattern = this.wikiInlineRulesPattern; var wikiSyntaxPattern = this.wikiSyntaxPattern; var tracLinkPattern = new RegExp("^" + this._tracLink + "$"); var wikiPageNamePattern = new RegExp("^" + this._wikiPageName + "$"); var decorationTokenPattern = /^(?:'''|''|__|\^|,,)$/; var texts = []; var stack = []; var last = root; var listDepth = 0; var quoteDepth = 0; var quoteCitation = false; var inCodeBlock = false; var skipNode = null; function escapeText(s) { var match = /^!?\[\[(.+)\]\]$/.exec(s); if (match) { return match[1].toLowerCase() != "br" ? s : "!" + s; } if (/^&#\d+/.test(s)) { return s; } return "!" + s; } function isTailEscape() { var t = texts; var length = t.length; return length > 0 ? /!$/.test(t[length - 1]) : false; } function tokenFromSpan(node) { if (node.className == "underline") { return wikiOpenTokens["u"]; } var style = node.style; if (style.fontWeight == "bold") { return wikiOpenTokens["b"]; } if (style.fontStyle == "italic") { return wikiOpenTokens["i"]; } switch (style.textDecoration) { case "underline": return wikiOpenTokens["u"]; case "line-through": return wikiOpenTokens["del"]; } switch (style.verticalAlign) { case "sub": return wikiOpenTokens["sub"]; case "sup": return wikiOpenTokens["sup"]; } return undefined; } function nodeDecorations(node) { var _wikiOpenTokens = wikiOpenTokens; var _decorationTokenPattern = decorationTokenPattern; var hash = {}; for ( ; ; ) { var childNodes = node.childNodes; if (!childNodes || childNodes.length != 1) { break; } var child = childNodes[0]; if (child.nodeType != 1) { break; } var token = _wikiOpenTokens[child.tagName.toLowerCase()]; if (_decorationTokenPattern.test(token)) { hash[token] = true; } node = child; } return hash; } function pushTextWithDecorations(text, node, traclink) { var _texts = texts; var _decorationTokenPattern = decorationTokenPattern; var decorationsHash = nodeDecorations(node); var decorations = []; var cancelDecorations = []; while (_texts.length > 0) { var token = _texts[_texts.length - 1]; if (_decorationTokenPattern.test(token)) { if (decorationsHash[token]) { delete decorationsHash[token]; cancelDecorations.push(_texts.pop()); continue; } if ((token == "'''" || token == "''") && _texts.length > 1) { var moreToken = _texts[_texts.length - 2]; if (_decorationTokenPattern.test(moreToken) && token + moreToken == "'''''" && decorationsHash[moreToken]) { delete decorationsHash[moreToken]; cancelDecorations.push(moreToken); _texts[_texts.length - 2] = _texts[_texts.length - 1]; _texts.pop(); } } } break; } for (var token in decorationsHash) { decorations.push(token); } decorations.sort(); if (decorations.length > 0) { _texts.push.apply(_texts, decorations); } if (traclink) { if (_texts.length > 0 && /[\w.+-]$/.test(_texts[_texts.length - 1])) { _texts.push(traclink); } else { text = new String(text); text["tracwysiwyg-traclink"] = traclink; _texts.push(text); } } else { _texts.push(text); } if (decorations.length > 0) { decorations.reverse(); _texts.push.apply(_texts, decorations); } if (cancelDecorations.length > 0) { cancelDecorations.reverse(); _texts.push.apply(_texts, cancelDecorations); } } function pushToken(token) { var _texts = texts; var _decorationTokenPattern = decorationTokenPattern; var length = _texts.length; if (length == 0 || !_decorationTokenPattern.test(token)) { _texts.push(token); return; } var last = _texts[length - 1]; if (!_decorationTokenPattern.test(last)) { _texts.push(token); return; } if (last == token) { _texts.pop(); return; } if (length < 2 || last + token != "'''''") { _texts.push(token); return; } if (_texts[length - 2] == token) { _texts[length - 2] = _texts[length - 1]; _texts.pop(); } else { _texts.push(token); } } function tracLinkText(link, label) { if (!/\]/.test(label) && !/^[\"\']/.test(label)) { return "[" + link + " " + label + "]"; } if (!/\"/.test(label)) { return "[" + link + ' "' + label + '"]'; } if (!/\'/.test(label)) { return "[" + link + " '" + label + "']"; } return "[" + link + ' "' + label.replace(/"+/g, "") + '"]'; } function pushAnchor(node) { var link = node.getAttribute("data-tracwysiwyg-link"); var autolink = node.getAttribute("data-tracwysiwyg-autolink"); var attrs; if (link === null) { attrs = TracWysiwyg.unserializeFromHref(node.href); link = attrs["data-tracwysiwyg-link"]; autolink = attrs["data-tracwysiwyg-autolink"]; } link = (link || node.href).replace(/^\s+|\s+$/g, ""); var label = getTextContent(node).replace(/^\s+|\s+$/g, ""); if (!label) { return; } var text = null; var traclink = null; if (autolink == "true") { if (wikiPageNamePattern.test(label)) { text = label; link = "wiki:" + label; traclink = "[wiki:" + label + "]"; } else if (wikiSyntaxPattern.test(label)) { text = label; link = self.convertWikiSyntax(label); } else if (tracLinkPattern.test(label)) { text = link = label; } } else { if (link == label && tracLinkPattern.test(label)) { text = label; } } if (!text) { var match = /^([\w.+-]+):(@?(.*))$/.exec(link); if (match) { if (label == match[2]) { if (match[1] == "wiki" && wikiPageNamePattern.test(match[2])) { text = match[2]; traclink = "[wiki:" + text + "]"; } else { text = "[" + link + "]"; } } else { var usingLabel = false; switch (match[1]) { case "changeset": usingLabel = label == "[" + match[2] + "]" || /^\d+$/.test(match[2]) && label == "r" + match[2]; break; case "log": usingLabel = label == "[" + match[3] + "]" || label == "r" + match[3]; break; case "report": usingLabel = label == "{" + match[2] + "}"; break; case "ticket": usingLabel = label == "#" + match[2]; break; } if (usingLabel) { text = label; } } } } if (isTailEscape()) { texts.push(" "); } if (text === null) { text = tracLinkText(link, label); } if (!traclink && /^[\w.+-]/.test(text)) { traclink = tracLinkText(link, label); } pushTextWithDecorations(text, node, traclink); } function string(source, times) { var value = (1 << times) - 1; if (value <= 0) { return ""; } else { return value.toString(2).replace(/1/g, source); } } function open(name, node) { if (skipNode !== null) { return; } var _texts = texts; var token = wikiOpenTokens[name]; if (token !== undefined) { if (name in wikiBlockTags && self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } if (token !== true) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } } else { switch (name) { case "#text": var value = node.nodeValue; if (value) { if (!inCodeBlock) { if (value && !self.isInlineNode(node.previousSibling || node.parentNode)) { value = value.replace(/^[ \t\r\n\f\v]+/g, ""); } if (value && !self.isInlineNode(node.nextSibling || node.parentNode)) { value = value.replace(/[ \t\r\n\f\v]+$/g, ""); } value = value.replace(/\r?\n/g, " "); if (!formatCodeBlock) { value = value.replace(wikiInlineRulesPattern, escapeText); } } if (value) { var length = _texts.length; var prev = length > 0 ? _texts[length - 1] : null; if (prev && prev["tracwysiwyg-traclink"] && tracLinkPattern.test(prev + value.substring(0, 1))) { _texts[length - 1] = prev["tracwysiwyg-traclink"]; } _texts.push(value); } } break; case "p": if (quoteDepth > 0) { _texts.push(string(quoteCitation ? "> " : " ", quoteDepth)); } else if (!/[^ \t\r\n\f\v]/.test(getTextContent(node))) { skipNode = node; } break; case "a": skipNode = node; pushAnchor(node); break; case "li": _texts.push(" " + string(" ", listDepth - 1)); var container = node.parentNode; if ((container.tagName || "").toLowerCase() == "ol") { var start = container.getAttribute("start") || ""; if (start != "1" && /^(?:[0-9]+|[a-zA-Z]|[ivxIVX]{1,5})$/.test(start)) { _texts.push(start, ". "); } else { switch (container.className) { case "arabiczero": _texts.push("0. "); break; case "lowerroman": _texts.push("i. "); break; case "upperroman": _texts.push("I. "); break; case "loweralpha": _texts.push("a. "); break; case "upperalpha": _texts.push("A. "); break; default: _texts.push("1. "); break; } } } else { _texts.push("* "); } break; case "ul": case "ol": if (listDepth == 0) { if (self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } } else if (listDepth > 0) { if (node.parentNode.tagName.toLowerCase() == "li") { _texts.push("\n"); } } listDepth++; break; case "br": if (!self.isBogusLineBreak(node)) { var value; if (inCodeBlock) { value = "\n"; } else if (formatCodeBlock) { switch (((node.parentNode || {}).tagName || "").toLowerCase()) { case "li": value = "\n " + string(" ", listDepth); break; case "p": case "blockquote": value = "\n"; if (quoteDepth > 0) { value += string(quoteCitation ? "> " : " ", quoteDepth); } break; case "dd": value = "\n "; break; case "dt": case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": value = " "; break; default: value = "\n"; break; } } else { var length = _texts.length; if (length > 0) { var lastText = _texts[length - 1]; var tmp = lastText + "[[BR]]"; var _wikiInlineRulesPattern = wikiInlineRulesPattern; _wikiInlineRulesPattern.lastIndex = 0; var lastMatch, match; while (match = _wikiInlineRulesPattern.exec(tmp)) { lastMatch = match; } if (lastMatch && lastMatch.index < lastText.length && lastMatch.index + lastMatch[0].length > lastText.length) { value = " [[BR]]"; } } if (!value) { value = "[[BR]]"; } } _texts.push(value); } break; case "pre": _texts.push( /^(?:li|dd)$/i.test(node.parentNode.tagName) || self.isInlineNode(node.previousSibling) ? "\n{{{\n" : "{{{\n"); inCodeBlock = true; break; case "blockquote": if (self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } quoteDepth++; if (quoteDepth == 1) { quoteCitation = (node.className == "citation"); } break; case "td": case "th": skipNode = node; _texts.push("||"); var text = self.domToWikitext(node).replace(/ *\n/g, "[[BR]]").replace(/^ +| +$/g, ""); _texts.push(text ? " " + text + " " : " "); break; case "tr": if (quoteDepth > 0) { _texts.push(string(quoteCitation ? ">" : " ", quoteDepth)); } break; case "tt": skipNode = node; var value = getTextContent(node); var text; if (value) { if (isTailEscape()) { _texts.push(" "); } if (!/`/.test(value)) { text = "`" + value + "`"; } else if (!/\{\{\{|\}\}\}/.test(value)) { text = "{{{" + value + "}}}"; } else { text = value.replace(/[^`]+|`+/g, function(m) { return m.charCodeAt(0) != 0x60 ? "`" + m + "`" : "{{{" + m + "}}}"; }); } pushTextWithDecorations(text, node); } break; case "span": var token = tokenFromSpan(node); if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } break; case "script": case "style": skipNode = node; break; } } } function close(name, node) { if (skipNode !== null) { if (skipNode == node) { skipNode = null; } return; } var _texts = texts; var token = wikiCloseTokens[name]; if (token === true) { // nothing to do } else if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } else { switch (name) { case "p": _texts.push(quoteDepth == 0 ? "\n\n" : "\n"); break; case "li": if (node.getElementsByTagName("li").length == 0) { _texts.push("\n"); } break; case "ul": case "ol": listDepth--; if (listDepth == 0) { _texts.push("\n"); } break; case "pre": var text; var parentNode = node.parentNode; if (parentNode && /^(?:li|dd)$/i.test(parentNode.tagName)) { var nextSibling = node.nextSibling; if (!nextSibling) { text = "\n}}}"; } else if (nextSibling.nodeType != 1) { text = "\n}}}\n"; } else if (nextSibling.tagName.toLowerCase() == "pre") { text = "\n}}}"; } else { text = "\n}}}\n"; } if (text.slice(-1) == "\n") { text += listDepth > 0 ? " " + string(" ", listDepth) : " "; } } else { text = "\n}}}\n"; } _texts.push(text); inCodeBlock = false; break; case "blockquote": quoteDepth--; if (quoteDepth == 0) { _texts.push("\n"); } break; case "span": var token = tokenFromSpan(node); if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } _texts.push(token); } break; case "table": if (quoteDepth == 0) { _texts.push("\n"); } break; } } if (/^h[1-6]$/.test(name)) { if (xmlNamePattern.test(node.id || "")) { _texts.push(" #", node.id); } _texts.push("\n"); } } function iterator(node) { var name = null; switch (node && node.nodeType) { case 1: // element name = node.tagName.toLowerCase(); break; case 3: // text name = "#text"; break; } if (node && last == node.parentNode) { // down // nothing to do } else if (node && last == node.previousSibling) { // forward close(stack.pop(), last); } else { // up, forward var tmp = last; var nodeParent = node ? node.parentNode : root; for ( ; ; ) { var parent = tmp.parentNode; if (parent == node) { break; } close(stack.pop(), tmp); if (parent == nodeParent || !parent) { if (!node) { return; } break; } tmp = parent; } } open(name, node); stack.push(name); last = node; } this.treeWalk(root, iterator); return texts.join("").replace(/^(?: *\n)+|(?: *\n)+$/g, ""); }; if (window.getSelection) { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { var wikiInlineTags = this.wikiInlineTags; var last = element.lastChild; for ( ; ; ) { if (!last) { break; } if (last.nodeType != 1) { return; } var name = last.tagName.toLowerCase(); if (name == "br") { break; } if (!(name in wikiInlineTags)) { return; } last = last.lastChild || last.previousSibling; } var br = this.contentDocument.createElement("br"); element.appendChild(br); }; TracWysiwyg.prototype.isBogusLineBreak = TracWysiwyg.prototype.isLastChildInBlockNode; TracWysiwyg.prototype.insertParagraphOnEnter = function(event) { var range = this.getSelectionRange(); var node = range.endContainer; var header = null; if (node && node.nodeType == 3 && range.endOffset == node.nodeValue.length) { var nextSibling = node.nextSibling; if (!nextSibling || nextSibling.tagName.toLowerCase() == "br") { while (node) { if (node.nodeType == 1 && /^h[1-6]$/i.exec(node.tagName)) { header = node; break; } node = node.parentNode; } if (header) { var parent = header.parentNode; var childNodes = parent.childNodes; var length = childNodes.length; for (var offset = 0; offset < length; offset++) { if (childNodes[offset] == header) { offset++; break; } } this.selectRange(parent, offset, parent, offset); this.insertHTML('


'); TracWysiwyg.stopEvent(event); } } } }; TracWysiwyg.prototype.tableHTML = function(id, row, col) { var html = this._tableHTML(row, col); return html.replace(/<\/td>/g, '
').replace(//, ''); }; TracWysiwyg.prototype.insertTableCell = function(row, index) { var cell = row.insertCell(index); this.appendBogusLineBreak(cell); return cell; }; TracWysiwyg.prototype.getFocusNode = function() { return this.contentWindow.getSelection().focusNode; }; if (window.opera) { TracWysiwyg.prototype.insertLineBreak = function() { this.execCommand("inserthtml", "
"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; } else if (window.getSelection().setBaseAndExtent) { // Safari 2+ TracWysiwyg.prototype.insertLineBreak = function() { this.execCommand("insertlinebreak"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = function(event) { this.insertLineBreak(); TracWysiwyg.stopEvent(event); }; } else { // Firefox 2+ TracWysiwyg.prototype.insertLineBreak = function() { var d = this.contentDocument; var event = d.createEvent("KeyboardEvent"); event.initKeyEvent("keypress", true, true, null, false, false, true, false, 0x000d, 0); d.body.dispatchEvent(event); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; } if (window.getSelection().removeAllRanges) { TracWysiwyg.prototype.selectNode = function(node) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.selectNode(node); selection.addRange(range); }; TracWysiwyg.prototype.selectNodeContents = function(node) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.selectNodeContents(node); selection.addRange(range); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.setStart(start, startOffset); range.setEnd(end, endOffset); selection.addRange(range); }; TracWysiwyg.prototype.getNativeSelectionRange = function() { var selection = this.contentWindow.getSelection(); return selection.rangeCount > 0 ? selection.getRangeAt(0) : null; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { if (arg.start || arg.end) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange() || this.contentDocument.createRange(); selection.removeAllRanges(); if (arg.start) { range.setStartBefore(arg.start); } if (arg.end) { range.setEndAfter(arg.end); } selection.addRange(range); } }; TracWysiwyg.prototype.insertHTML = function(html) { this.execCommand("inserthtml", html); }; } else { // Safari 2 TracWysiwyg.prototype.selectNode = function(node) { var selection = this.contentWindow.getSelection(); var range = this.contentDocument.createRange(); range.selectNode(node); selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); range.detach(); }; TracWysiwyg.prototype.selectNodeContents = function(node) { this.selectRange(node, 0, node, node.childNodes.length); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var selection = this.contentWindow.getSelection(); selection.setBaseAndExtent(start, startOffset, end, endOffset); }; TracWysiwyg.prototype.getNativeSelectionRange = function() { var selection = this.contentWindow.getSelection(); if (selection.anchorNode) { var range = this.contentDocument.createRange(); range.setStart(selection.baseNode, selection.baseOffset); range.setEnd(selection.extentNode, selection.extentOffset); if (range.collapsed && !selection.isCollapsed) { range.setStart(selection.extentNode, selection.extentOffset); range.setEnd(selection.baseNode, selection.baseOffset); } return range; } return null; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { if (arg.start || arg.end) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange(); if (arg.start) { range.setStartBefore(arg.start); } if (arg.end) { range.setEndAfter(arg.end); } selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); range.detach(); } }; TracWysiwyg.prototype.insertHTML = function(html) { var range = this.getNativeSelectionRange(); if (range) { var d = this.contentDocument; var tmp = d.createRange(); tmp.setStart(d.body, 0); tmp.setEnd(d.body, 0); var fragment = tmp.createContextualFragment(html); range.deleteContents(); range.insertNode(fragment); range.detach(); tmp.detach(); } }; } TracWysiwyg.prototype.getSelectionRange = TracWysiwyg.prototype.getNativeSelectionRange; TracWysiwyg.prototype.getSelectionText = function() { var range = this.getNativeSelectionRange(); return range ? range.toString() : null; }; TracWysiwyg.prototype.getSelectionHTML = function() { var fragment = this.getSelectionFragment(); var anonymous = this.contentDocument.createElement("div"); anonymous.appendChild(fragment); return anonymous.innerHTML; }; TracWysiwyg.prototype.getSelectionFragment = function() { var range = this.getNativeSelectionRange(); return range ? range.cloneContents() : this.contentDocument.createDocumentFragment(); }; TracWysiwyg.prototype.getSelectionPosition = function() { var range = this.getNativeSelectionRange(); var position = { start: null, end: null }; if (range) { position.start = range.startContainer; position.end = range.endContainer; } return position; }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange(); if (!range) { return false; } var ancestor = range.commonAncestorContainer; if (!ancestor) { return false; } if (TracWysiwyg.getSelfOrAncestor(ancestor, name)) { return true; } if (ancestor.nodeType != 1) { return false; } var elements = ancestor.getElementsByTagName(name); var length = elements.length; for (var i = 0; i < length; i++) { if (selection.containsNode(elements[i], true)) { return true; } } return false; }; } else if (document.selection) { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { }; TracWysiwyg.prototype.isBogusLineBreak = function(node) { return false }; TracWysiwyg.prototype.insertParagraphOnEnter = null; TracWysiwyg.prototype.insertLineBreak = function() { this.insertHTML("
"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; TracWysiwyg.prototype.tableHTML = function(id, row, col) { var html = this._tableHTML(row, col); return html.replace(//, ''); }; TracWysiwyg.prototype.insertTableCell = function(row, index) { return row.insertCell(index); }; TracWysiwyg.prototype.getFocusNode = function() { this.contentWindow.focus(); var d = this.contentDocument; var range = d.selection.createRange(); var node = range.item ? range.item(0) : range.parentElement(); return node.ownerDocument == d ? node : null; }; TracWysiwyg.prototype.selectNode = function(node) { var d = this.contentDocument; var body = d.body; var range; d.selection.empty(); try { range = body.createControlRange(); range.addElement(node); } catch (e) { range = body.createTextRange(); range.moveToElementText(node); } range.select(); }; TracWysiwyg.prototype.selectNodeContents = function(node) { var d = this.contentDocument; d.selection.empty(); var range = d.body.createTextRange(); range.moveToElementText(node); range.select(); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var d = this.contentDocument; var body = d.body; d.selection.empty(); var range = endPoint(start, startOffset); if (start != end || startOffset != endOffset) { range.setEndPoint("EndToEnd", endPoint(end, endOffset)); } range.select(); function endPoint(node, offset) { var range; if (node.nodeType == 1) { var childNodes = node.childNodes; if (offset >= childNodes.length) { range = body.createTextRange(); range.moveToElementText(node); range.collapse(false); return range; } node = childNodes[offset]; if (node.nodeType == 1) { range = body.createTextRange(); range.moveToElementText(node); range.collapse(true); switch (node.tagName.toLowerCase()) { case "table": range.move("character", -1); break; } return range; } return endPoint(node, 0); } if (node.nodeType != 3) { throw "selectRange: nodeType != @".replace(/@/, node.nodeType); } range = body.createTextRange(); var element = node.previousSibling; while (element) { var nodeType = element.nodeType; if (nodeType == 1) { range.moveToElementText(element); range.collapse(false); break; } if (nodeType == 3) { offset += element.nodeValue.length; } element = element.previousSibling; } if (!element) { range.moveToElementText(node.parentNode); range.collapse(true); } if (offset != 0) { range.move("character", offset); } return range; } }; TracWysiwyg.prototype.getSelectionRange = function() { var body = this.contentDocument.body; var pseudo = {}; var start = this.getNativeSelectionRange(); if (start.item) { var element = start.item(0); var parent = element.parentNode; var childNodes = parent.childNodes; var length = childNodes.length; for (var i = 0; i < length; i++) { if (childNodes[i] == element) { pseudo.startOffset = i; pseudo.endOffset = i + 1; break; } } pseudo.collapsed = false; pseudo.startContainer = pseudo.endContainer = parent; return pseudo; } var end = start.duplicate(); pseudo.collapsed = start.compareEndPoints("StartToEnd", end) == 0; start.collapse(true); end.collapse(false); function nextElement(range) { var parent = range.parentElement(); var childNodes = parent.childNodes; var length = childNodes.length; for (var i = 0; i < length; i++) { var node = childNodes[i]; if (node.nodeType == 1) { var tmp = body.createTextRange(); tmp.moveToElementText(node); if (range.compareEndPoints("EndToStart", tmp) <= 0) { return node; } } } return null; } function nodeOffset(range, parent, element, index, length) { var tmp = body.createTextRange(); tmp.moveToElementText(element || parent); tmp.collapse(!!element); tmp.move("character", -index); for ( ; length >= 0; length--) { if (tmp.compareEndPoints("EndToStart", range) == 0) { return length; } tmp.move("character", -1); } return null; } function setContainerOffset(range, containerKey, offsetKey) { var parent = range.parentElement(); var element = nextElement(range); var index = 0; var node = element ? element.previousSibling : parent.lastChild; var offset, length; while (node && node.nodeType == 3) { length = node.nodeValue.length; offset = nodeOffset(range, parent, element, index, length); if (offset !== null) { pseudo[containerKey] = node; pseudo[offsetKey] = offset; return; } index += length; node = node.previousSibling; } var childNodes = parent.childNodes; length = childNodes.length; if (length > 0) { pseudo[containerKey] = parent; pseudo[offsetKey] = containerKey == "startContainer" ? 0 : length - 1; return; } element = parent; parent = element.parentNode; childNodes = parent.childNodes; length = childNodes.length; for (offset = 0; offset < length; offset++) { if (element == childNodes[offset]) { pseudo[containerKey] = parent; pseudo[offsetKey] = offset; return; } } } setContainerOffset(start, "startContainer", "startOffset"); setContainerOffset(end, "endContainer", "endOffset"); return pseudo; }; TracWysiwyg.prototype.getNativeSelectionRange = function() { this.contentWindow.focus(); return this.contentDocument.selection.createRange(); }; TracWysiwyg.prototype.getSelectionText = function() { var range = this.getNativeSelectionRange(); if (range) { return range.item ? range.item(0).innerText : range.text; } return null; }; TracWysiwyg.prototype.getSelectionHTML = function() { var range = this.getNativeSelectionRange(); if (range) { return range.item ? range.item(0).innerHTML : range.htmlText; } return null; }; TracWysiwyg.prototype.getSelectionFragment = function() { var d = this.contentDocument; var fragment = d.createDocumentFragment(); var anonymous = d.createElement("div"); anonymous.innerHTML = this.getSelectionHTML(); this.collectChildNodes(fragment, anonymous); return fragment; }; TracWysiwyg.prototype.getSelectionPosition = function() { this.contentWindow.focus(); var d = this.contentDocument; var range = d.selection.createRange(); var startNode = null; var endNode = null; if (range.item) { if (range.item(0).ownerDocument == d) { startNode = range.item(0); endNode = range.item(range.length - 1); } } else { if (range.parentElement().ownerDocument == d) { var startRange = range.duplicate(); startRange.collapse(true); startNode = startRange.parentElement(); var endRange = range.duplicate(); endRange.collapse(false); endNode = endRange.parentElement(); } } return { start: startNode, end: endNode }; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { this.contentWindow.focus(); var d = this.contentDocument; var body = d.body; var range = d.selection.createRange(); var tmp; if (arg.start) { tmp = body.createTextRange(); tmp.moveToElementText(arg.start); range.setEndPoint("StartToStart", tmp); } if (arg.end) { tmp = body.createTextRange(); tmp.moveToElementText(arg.end); range.setEndPoint("EndToEnd", tmp); } if (tmp) { range.select(); } }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { this.contentWindow.focus(); var d = this.contentDocument; var selection = d.selection; var range = selection.createRange(); var parent = range.item ? range.item(0) : range.parentElement(); if (!parent) { return false; } if (TracWysiwyg.getSelfOrAncestor(parent, name)) { return true; } var elements = parent.getElementsByTagName(name); var length = elements.length; for (var i = 0; i < length; i++) { var testRange = selection.createRange(); testRange.moveToElementText(elements[i]); if (range.compareEndPoints("StartToEnd", testRange) <= 0 && range.compareEndPoints("EndToStart", testRange) >= 0) { return true; } } return false; }; TracWysiwyg.prototype.insertHTML = function(html) { this.contentWindow.focus(); var selection = this.contentDocument.selection; var range = selection.createRange(); range.pasteHTML(html.replace(/\t/g, " ")); range.collapse(false); range.select(); range = this.contentDocument.selection.createRange(); }; } else { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { }; TracWysiwyg.prototype.insertParagraphOnEnter = null; TracWysiwyg.prototype.insertLineBreak = function() { }; TracWysiwyg.prototype.insertTableCell = function(row, index) { return null }; TracWysiwyg.prototype.getFocusNode = function() { return null }; TracWysiwyg.prototype.selectNode = function(node) { }; TracWysiwyg.prototype.selectNodeContents = function(node) { return null }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { }; TracWysiwyg.prototype.getSelectionRange = function() { return null }; TracWysiwyg.prototype.getNativeSelectionRange = function() { return null }; TracWysiwyg.prototype.getSelectionText = function() { return null }; TracWysiwyg.prototype.getSelectionHTML = function() { return null }; TracWysiwyg.prototype.getSelectionFragment = function() { return null }; TracWysiwyg.prototype.getSelectionPosition = function() { return null }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { return false }; TracWysiwyg.prototype.insertHTML = function(html) { }; } TracWysiwyg.prototype._treeWalkEmulation = function(root, iterator) { if (!root.firstChild) { iterator(null); return; } var element = root; var tmp; while (element) { if (tmp = element.firstChild) { element = tmp; } else if (tmp = element.nextSibling) { element = tmp; } else { for ( ; ; ) { element = element.parentNode; if (element == root || !element) { iterator(null); return; } if (tmp = element.nextSibling) { element = tmp; break; } } } iterator(element); } }; if (document.createTreeWalker) { TracWysiwyg.prototype.treeWalk = function(root, iterator) { var walker = root.ownerDocument.createTreeWalker( root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, true); while (walker.nextNode()) { iterator(walker.currentNode); } iterator(null); }; } else { TracWysiwyg.prototype.treeWalk = TracWysiwyg.prototype._treeWalkEmulation; } TracWysiwyg.instances = []; TracWysiwyg.count = 0; TracWysiwyg.tracPaths = null; TracWysiwyg.newInstance = function(textarea) { var instance = new TracWysiwyg(textarea); TracWysiwyg.instances.push(instance); return instance; }; TracWysiwyg.findInstance = function(textarea) { var instances = TracWysiwyg.instances; var length = instances.length; for (var i = 0; i < length; i++) { var instance = instances[i]; if (instance.textarea == textarea) { return instance; } } return null; }; TracWysiwyg.getTracPaths = function() { var stylesheets = []; var paths = { stylesheets: stylesheets }; var d = document; var head = d.getElementsByTagName("head")[0]; var links = head.getElementsByTagName("link"); var length = links.length; for (var i = 0; i < length; i++) { var link = links[i]; var href = link.getAttribute("href") || ""; var type = link.getAttribute("type") || ""; switch ((link.getAttribute("rel") || "").toLowerCase()) { case "tracwysiwyg-base": paths.base = href; break; case "tracwysiwyg-stylesheet": stylesheets.push(href); break; } } if (paths.base && stylesheets.length > 0) { return paths; } return null; }; TracWysiwyg.getEditorMode = function() { if (TracWysiwyg.editorMode) { return TracWysiwyg.editorMode; } var mode = null; var cookies = (document.cookie || "").split(";"); var length = cookies.length; for (var i = 0; i < length; i++) { var match = /^\s*tracwysiwyg=(\S*)/.exec(cookies[i]); if (match) { switch (match[1]) { case "wysiwyg": mode = match[1]; break; default: // "textarea" mode = null; break; } break; } } TracWysiwyg.editorMode = mode || "textarea"; return TracWysiwyg.editorMode; }; TracWysiwyg.setEditorMode = function(mode) { switch (mode) { case "wysiwyg": break; default: // "textarea" mode = "textarea"; break; } TracWysiwyg.editorMode = mode; var now = new Date(); if (!/\/$/.test(TracWysiwyg.tracPaths.base)) { expires = new Date(now.getTime() - 86400000); pieces = [ "tracwysiwyg=", "path=" + TracWysiwyg.tracPaths.base + "/", "expires=" + expires.toUTCString() ]; document.cookie = pieces.join("; "); } var expires = new Date(now.getTime() + 365 * 86400 * 1000); var pieces = [ "tracwysiwyg=" + mode, "path=" + TracWysiwyg.tracPaths.base, "expires=" + expires.toUTCString() ]; document.cookie = pieces.join("; "); }; TracWysiwyg.stopEvent = function(event) { if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; } }; TracWysiwyg.setStyle = function(element, object) { var style = element.style; for (var name in object) { style[name] = object[name]; } }; if (document.defaultView) { TracWysiwyg.getStyle = function(element, name) { var value = element.style[name]; if (!value) { var style = element.ownerDocument.defaultView.getComputedStyle(element, null) value = style ? style[name] : null; } return value; }; } else { TracWysiwyg.getStyle = function(element, name) { return element.style[name] || element.currentStyle[name]; }; } TracWysiwyg.elementPosition = function(element) { function vector(left, top) { var value = [ left, top ]; value.left = left; value.top = top; return value; } var position = TracWysiwyg.getStyle(element, "position"); var left = 0, top = 0; for (var node = element; node; node = node.offsetParent) { left += node.offsetLeft || 0; top += node.offsetTop || 0; } if (position != "absolute") { return vector(left, top); } var offset = TracWysiwyg.elementPosition(element.offsetParent); return vector(left - offset.left, top - offset.top); }; TracWysiwyg.getTextAreaHeight = function(textarea) { var height = textarea.offsetHeight; if (height == 0) { height = parseInt(textarea.rows) * parseInt(TracWysiwyg.getStyle(textarea, 'line-height'), 10); } return height; }; TracWysiwyg.getSelfOrAncestor = function(element, name) { var target = element; var d = element.ownerDocument; if (name instanceof RegExp) { while (target && target != d) { switch (target.nodeType) { case 1: // element if (name.test(target.tagName.toLowerCase())) { return target; } break; case 11: // fragment return null; } target = target.parentNode; } } else { name = name.toLowerCase(); while (target && target != d) { switch (target.nodeType) { case 1: // element if (target.tagName.toLowerCase() == name) { return target; } break; case 11: // fragment return null; } target = target.parentNode; } } return null; }; TracWysiwyg.serializeToHref = function(attrs) { var texts = []; for (var name in attrs) { if (/^data(?:-|$)/.exec(name)) { texts.push(encodeURIComponent(name) + "=" + encodeURIComponent(attrs[name])); } } return "#" + texts.join("&"); }; TracWysiwyg.unserializeFromHref = function(href, name) { var attrs = {}; if (href.indexOf("#") !== -1) { var pieces = href.replace(/^[^#]*#/, '').split(/&/g); var length = pieces.length; for (var i = 0; i < length; i++) { var pair = pieces[i].split(/=/g, 2); attrs[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } } return name ? attrs[name] : attrs; }; TracWysiwyg.getTextContent = (function() { var anonymous = document.createElement("div"); if (typeof anonymous.textContent != "undefined") { return function(element) { return element.textContent }; } else if (typeof anonymous.innerText != "undefined") { return function(element) { return element.innerText }; } else { return function(element) { return null }; } })(); TracWysiwyg.initialize = function() { if ("replace".replace(/[a-e]/g, function(m) { return "*" }) != "r*pl***") { return; } if (typeof document.designMode == "undefined") { return; } TracWysiwyg.tracPaths = TracWysiwyg.getTracPaths(); if (!TracWysiwyg.tracPaths) { return; } var textareas = document.getElementsByTagName("textarea"); for (var i = 0; i < textareas.length; i++) { var textarea = textareas[i]; if (/\bwikitext\b/.test(textarea.className || "")) { TracWysiwyg.newInstance(textarea); } } }; trac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/htdocs/toolbar.png0000644000175000017500000001136010672463456022020 0ustar wmbwmbPNG  IHDRoT pHYs  IDATxytTUTe'T8$"F`[FisPEpa4=:8=l3b;i[D#l-!IJBR*{珪o4ݹS{Ww~}ORJ0 gsiZ[ZM&7oӲ'P1glTU"ydbt:]CJN;SؐJ!)/+׮Ͼ E`MM xF'bŮ0u6n^?Jmmm/ddfN2<##8H6WB aՕRv  BHUzdSfJ)AH "A*T!P$(SPH/Kq;EAAߺ':NNEgTVTos-G>v)S|)Waz=&O@oMbt;`ӉbiogQtV+SN!ɖDjni:97 TwPQ^?':n5S>[٧xt̿6EC aws%8yS-y\.mx;456q{X-8m4rnbwŇ8u4_="##P"%t$sl6j]"aΓR" h ^M*<=J(TjҒSlHÀ߯J5o>J˚IΌn2zre|v6hM&#I6RdK⦜1gzqx ~Ή_qԙУQadM"99+>ucǎmq]u LNI&>>^#Ix\-=abw}'.r݉b=V+eT@)W:.yo_>ԴT-j8q"RJjkjinn!--ظa !!ظXΕ#'&Mv01 Ξ9˜sXzOrӧEdfevt2mZ6wͿ+fde"M*TwFZW71qDV>EAme22Jn cB )_Z~.8W6K.ɭI![:o:<nK)xXUu ro-9_G 9ꨯC*g{Ǎ/=E󰾡]IBTU%mr'~>!&^O{[-^D :y(|>,&>!>6BZ[Z :ZۈN>O1њZ7<ޡv5KݐM_ȑhokg$mrUUVc99t:bd1̦r2Ȍ|{{ aaFffi)g}RXڹsl: sis%_fMIIg,Ƚ'O|ŲrRq69yżn>?zXbccIIMk]Q~xiΞ>KEE%wsFsgOp{=ȢŋPCOVleR uuDFZB /r]?+|}qqDƒܷ?*RRӜ=SBEEwοs(S<DTUź@J5'p|y<Z[H%K}]=Vi3ñ7Hjkf :k&$Lr U^wE||f AS~̬ &' ^egs#ؒp:]_S \Ӓ9CKbjkkCέC3y &P$9|rͻ7Աw^gG1Mt$M C~<&9971iR\ 0cW'|RU ˗/[͛9<٬Xhym6ZZZ:u*=%nLnذA&h%pgl?,..fMO[xip8x|ꩧGNc씫ñj<GFC6 #aw|;z;vcq\yaÆ6{ Kx-xẍR\.|#m{t:-Z4^:ͬ_EQXv7 چYF?Z݆{9~ӟOS@__A<6mڤEv~{pɚC"""FC^p333X7qa H%ugů+xLj}O êfwrlmlazhK ukG,ԠNܹ^.|`TBR<Tقu25x<[NU @03=7 > HAm<_PUθ}>d(?׸y 3!|x^F#>ٌ!""UUQN(ft:]x^B( @UUt:b0xIHHS7|zt:z=>_S*믿Nrrrד˗/B;UUUgrƍl7˖-[x駵jjv bٵk(~[obŊª*ݻY|9FL\\\nmmeϞ=j@ +!0 Z;F,YfqFVZb۩{˖a?XS)0pw}EBB/2K. iݾeZ|DDiSCAE|X1K/%ݿ7lxW|FFz_)%V #.6^q[۹pw~: 7p<]EQIx؄h@7 @^o@ 1L: `7oIENDB`trac-wysiwyg-0.12.0.3+r10725/0.10/tracwysiwyg/htdocs/editor.css0000644000175000017500000000024611211421434021625 0ustar wmbwmbpre.wiki { overflow: visible !important; word-wrap: break-word !important; white-space: -moz-pre-wrap !important; white-space: pre-wrap !important; } trac-wysiwyg-0.12.0.3+r10725/0.10/setup.cfg0000644000175000017500000000004310672463456015605 0ustar wmbwmb[egg_info] tag_svn_revision = true trac-wysiwyg-0.12.0.3+r10725/0.10/setup.py0000644000175000017500000000113411463324376015474 0ustar wmbwmb#!/usr/bin/env python # -*- coding: utf-8 -*- from setuptools import setup, find_packages setup( name = 'TracWysiwyg', version = '0.10.0.3', description = 'TracWiki WYSIWYG Editor', license = 'BSD', url = 'http://trac-hacks.org/wiki/TracWysiwygPlugin', author = 'Jun Omae', author_email = 'omae@opengroove.com', packages = find_packages(exclude=['*.tests*']), package_data = { 'tracwysiwyg' : [ 'htdocs/*.js', 'htdocs/*.css', 'htdocs/*.png' ], }, entry_points = { 'trac.plugins': [ 'tracwysiwyg = tracwysiwyg', ], } ) trac-wysiwyg-0.12.0.3+r10725/0.10/tests/0000755000175000017500000000000011677636642015136 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.10/tests/testcase.js0000644000175000017500000017204711642344654017311 0ustar wmbwmbaddEvent(window, "load", function() { TracWysiwyg.tracPaths = { base: ".", stylesheets: [] }; var instance = new TracWysiwyg(document.getElementById("textarea")); var contentDocument = instance.contentDocument; var d = document; var wysiwygHtml = d.getElementById("wysiwyg-html"); var showWysiwygHtml = d.getElementById("show-wysiwyg-html"); setTimeout(function() { if (showWysiwygHtml.checked) { var body = contentDocument.body; var browserIE = body.attachEvent ? true : false; var elements = body.getElementsByTagName("br"); var count = 0; var html = body.innerHTML.replace(/<[Bb][Rr] *[^>\/]*/g, function(value) { var element = elements[count++]; var attributes = element.attributes; var length = attributes.length; if (length == 0) return value; var texts = [ value ]; for (var i = 0; i < length; i++) { var attr = attributes[i]; if (!browserIE || !!element[attr.name]) { texts.push(' ', attr.name, '="', attr.value, '"'); } } return texts.join(""); }); if (wysiwygHtml.value != html) { wysiwygHtml.value = html; } } setTimeout(arguments.callee, 500); }, 500); function generate(dom, wikitext, withoutDomToWikitext, withoutWikitextToFragment) { dom = dom.cloneNode(true); var anonymous = dom.ownerDocument.createElement("div"); anonymous.appendChild(dom); if (!withoutWikitextToFragment) { var fragment = instance.wikitextToFragment(wikitext, contentDocument); var generated = contentDocument.createElement("div"); generated.appendChild(fragment); var generatedHtml = generated.innerHTML; if (!generated.addEventListener || window.opera) { generatedHtml = generatedHtml.replace(/\n\r/g, "\uffff").replace(/\uffff\n?/g, "\n"); } this.assertEqual(anonymous.innerHTML, generatedHtml, "wikitextToFragment"); } if (!withoutDomToWikitext) { this.assertEqual(wikitext, instance.domToWikitext(anonymous), "domToWikitext"); } } function generateFragment(dom, wikitext) { generate.call(this, dom, wikitext, true); } function generateWikitext(dom, wikitext) { generate.call(this, dom, wikitext, false, true); } function run() { var unit = new TracWysiwyg.TestUnit(); var fragment = unit.fragment; var element = unit.element; var a = function(link, label) { var attrs = { href: "#data-tracwysiwyg-link=" + encodeURIComponent(link), title: link, "data-tracwysiwyg-link": link, onclick: "return false;" }; return element("a", attrs, label || link); }; unit.add("treeWalk", function() { var list; function iterator(node) { var value; if (node) { switch (node.nodeType) { case 1: value = node.tagName.toLowerCase(); break; case 3: value = "#text"; break; } } else { value = "(null)"; } list.push(value); } function doTreeWalk(expected, dom) { list = []; instance.treeWalk(dom, iterator); this.assertEqual(expected, list.join(" ")); list = []; instance._treeWalkEmulation(dom, iterator); this.assertEqual(expected, list.join(" ")); } doTreeWalk.call(this, "p #text (null)", element("div", element("p", "paragraph"))); doTreeWalk.call(this, "#text (null)", element("div", element("p", "paragraph")).firstChild); doTreeWalk.call(this, "(null)", element("div", element("p")).firstChild); var dom = element("div"); dom.innerHTML = [ '

Tables

', '

', 'Simple tables can be created like this:', '

', '
||Cell 1||Cell 2||Cell 3||',
                '||Cell 4||Cell 5||Cell 6||',
                '

', 'Display:', '

', '', '
Cell 1Cell 2Cell 3', '
Cell 4Cell 5Cell 6', '
', '

', 'Note that more complex tables can be created using', 'reStructuredText.', '

' ].join(""); var expected = [ 'h2', '#text', 'p', '#text', 'pre', '#text', 'p', '#text', 'table', 'tbody', 'tr', 'td', '#text', 'td', '#text', 'td', '#text', 'tr', 'td', '#text', 'td', '#text', 'td', '#text', 'p', '#text', 'a', '#text', '#text', '(null)'].join(" "); doTreeWalk.call(this, expected, dom); }); unit.add("isLastChildInBlockNode", function() { var dom = fragment( element("p", element("br")), element("p", "foobar", element("br"), "foobar"), element("p", element("b", "foobar", element("br"))), element("p", element("b", "foobar"), element("br")), element("br")); var count = 0; function assert(expected, node) { this.assertEqual(expected, instance.isLastChildInBlockNode(node), "#" + (count++)); } assert.call(this, true, dom.childNodes[0].childNodes[0]); assert.call(this, false, dom.childNodes[1].childNodes[0]); assert.call(this, false, dom.childNodes[1].childNodes[1]); assert.call(this, true, dom.childNodes[1].childNodes[2]); assert.call(this, false, dom.childNodes[2].childNodes[0].childNodes[0]); assert.call(this, true, dom.childNodes[2].childNodes[0].childNodes[1]); assert.call(this, false, dom.childNodes[3].childNodes[0].childNodes[0]); assert.call(this, true, dom.childNodes[3].childNodes[1]); assert.call(this, true, dom.childNodes[4]); }); unit.add("code block", function() { var dom = fragment( element("p", element("tt", "abc")), element("pre", { "class": "wiki" }, "{{{code-block")); var wikitext = [ "`abc`", "", "{{{", "{{{code-block", "}}}" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("code block nest", function() { var dom = fragment( element("pre", { "class": "wiki" }, "#!python\n= level 1\n{{{\n= level 2\n}}}\n= level 1")); var wikitext = [ "{{{", "#!python", "= level 1", "{{{", "= level 2", "}}}", "= level 1", "}}}" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("paragraph", function() { var dom = fragment( element("p", "Paragraph continued..."), element("p", "Second paragraph continued...")); generateFragment.call(this, dom, [ "Paragraph", "continued...", "", "Second paragraph", "continued...", "" ].join("\n")); generate.call(this, dom, [ "Paragraph continued...", "", "Second paragraph continued..." ].join("\n")); }); unit.add("hr", function() { var dom = fragment( element("p", "Paragraph"), element("hr"), element("ul", element("li", "item 1"), element("ol", element("li", "item 1.1"))), element("hr")); generateFragment.call(this, dom, [ "Paragraph", "----", " * item 1", " 1. item 1.1", "----" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "----", " * item 1", " 1. item 1.1", "", "----" ].join("\n")); }); unit.add("bold italic", function() { var dom = element("p", element("b", element("i", "bold italic"))); var wikitext = "'''''bold italic'''''"; generate.call(this, dom, wikitext); }); unit.add("bold", function() { var wikitext = [ "The quick '''brown''' fox.", "", "The quick '''brown''' fox." ].join("\n"); generateWikitext.call(this, fragment( element("p", "The quick ", element("b", "brown"), " fox."), element("p", "The quick ", element("strong", "brown"), " fox.")), wikitext); generateFragment.call(this, fragment( element("p", "The quick ", element("b", "brown"), " fox."), element("p", "The quick ", element("b", "brown"), " fox.")), wikitext); }); unit.add("italic", function() { var wikitext = [ "The quick ''brown'' fox.", "", "The quick ''brown'' fox." ].join("\n"); generateWikitext.call(this, fragment( element("p", "The quick ", element("i", "brown"), " fox."), element("p", "The quick ", element("em", "brown"), " fox.")), wikitext); generateFragment.call(this, fragment( element("p", "The quick ", element("i", "brown"), " fox."), element("p", "The quick ", element("i", "brown"), " fox.")), wikitext); }); unit.add("underline", function() { var dom = element("p", element("u", "underline")); var wikitext = "__underline__"; generate.call(this, dom, wikitext); }); unit.add("strike-through", function() { var dom = element("p", element("del", "strike-through")); var wikitext = "~~strike-through~~"; generate.call(this, dom, wikitext); }); unit.add("superscript", function() { var dom = element("p", element("sup", "superscript")); var wikitext = "^superscript^"; generate.call(this, dom, wikitext); }); unit.add("subscript", function() { var dom = element("p", element("sub", "subscript")); var wikitext = ",,subscript,,"; generate.call(this, dom, wikitext); }); unit.add("monospace", function() { var dom = element("p", element("tt", "monospace"), ", ", element("tt", "mono`s`pace"), ", ", element("tt", "mono{{{s}}}pace")); var wikitext = "`monospace`, {{{mono`s`pace}}}, `mono{{{s}}}pace`"; generate.call(this, dom, wikitext); }); unit.add("italic -> bold", function() { var dom = element("p", "normal", element("i", "italic"), element("b", "bold"), "normal"); var wikitext = "normal''italic'''''bold'''normal"; generate.call(this, dom, wikitext); }); unit.add("bold -> italic", function() { var dom = element("p", "normal", element("b", "bold"), element("i", "italic"), "normal"); var wikitext = "normal'''bold'''''italic''normal"; generate.call(this, dom, wikitext); }); unit.add("[ italic [ xyz ] bold ]", function() { var dom = element("p", "normal", element("i", "italic", element("b", "xyz")), element("b", "bold"), "normal"); var wikitext = "normal''italic'''xyz''bold'''normal"; generate.call(this, dom, wikitext); }); unit.add("overlapped markups", function() { var dom = element("p", "normal", element("b", "bold", element("i", "italic", element("u", "underline", element("del", "strike-through", element("sup", "superscript", element("sub", "subscript"))))), element("u", element("del", element("sup", element("sub", "i")))), element("del", element("sup", element("sub", "u"))), element("sup", element("sub", "strike")), element("sub", "sup"), "sub"), "."); var wikitext = "normal'''bold''italic__underline~~strike-through^superscript,,subscript''i__u~~strike^sup,,sub'''."; generateFragment.call(this, dom, wikitext); }); unit.add("repeated markups", function() { generateWikitext.call(this, element("p", "ab", element("b", "cd"), element("b", "ef"), "gh"), "ab'''cdef'''gh"); generateWikitext.call(this, element("p", "ab", element("i", "cd"), element("i", "ef"), "gh"), "ab''cdef''gh"); generateWikitext.call(this, element("p", "ab", element("u", "cd"), element("u", "ef"), "gh"), "ab__cdef__gh"); generateWikitext.call(this, element("p", "ab", element("sup", "cd"), element("sup", "ef"), "gh"), "ab^cdef^gh"); generateWikitext.call(this, element("p", "ab", element("sub", "cd"), element("sub", "ef"), "gh"), "ab,,cdef,,gh"); generateWikitext.call(this, element("p", "ab", element("tt", "cd"), element("tt", "ef"), "gh"), "ab`cd``ef`gh"); generateWikitext.call(this, element("p", "ab", element("i", element("b", "cd")), element("b", element("i", "ef")), "gh"), "ab'''''cdef'''''gh"); }); unit.add("markups without text", function() { generateWikitext.call(this, element("p", "abc", element("b", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("i", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("u", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("sup", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("sub", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("tt", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("b", element("i", "")), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("i", element("b", "")), "def"), "abcdef"); }); unit.add("! bold italic", function() { var dom = element("p", element("b", element("i", "bold''''' italic")), "."); var wikitext = "'''''bold!''''' italic'''''."; generate.call(this, dom, wikitext); }); unit.add("! bold", function() { var dom = element("p", element("b", "bold''' bold"), "."); var wikitext = "'''bold!''' bold'''."; generate.call(this, dom, wikitext); }); unit.add("! italic", function() { var dom = element("p", element("i", "italic'' italic"), "."); var wikitext = "''italic!'' italic''."; generate.call(this, dom, wikitext); }); unit.add("! underline", function() { var dom = element("p", element("u", "underline__ underline"), "."); var wikitext = "__underline!__ underline__."; generate.call(this, dom, wikitext); }); unit.add("! strike-through", function() { var dom = element("p", element("del", "strike~~through"), "."); var wikitext = "~~strike!~~through~~."; generate.call(this, dom, wikitext); }); unit.add("! superscript", function() { var dom = element("p", element("sup", "superscript^ superscript"), "."); var wikitext = "^superscript!^ superscript^."; generate.call(this, dom, wikitext); }); unit.add("! subscript", function() { var dom = element("p", element("sub", "subscript,, subscript"), "."); var wikitext = ",,subscript!,, subscript,,."; generate.call(this, dom, wikitext); }); unit.add("! monospace", function() { var dom = element("p", "{{{monospace}}} or `monospace`"); var wikitext = "!{{{monospace}}} or !`monospace`"; generate.call(this, dom, wikitext); }); unit.add("#ticket", function() { var dom = element("p", a("ticket:1234", "#1234"), " #2345 ඀"); var wikitext = "#1234 !#2345 ඀"; generate.call(this, dom, wikitext); }); unit.add("{report}", function() { var dom = element("p", "{987}", a("report:123", "{123}")); var wikitext = "!{987}{123}"; generate.call(this, dom, wikitext); }); unit.add("[changeset]", function() { var dom = element("p", a("changeset:123", "[123]"), ", ", a("changeset:234", "r234"), ", ", a("changeset:345/trunk", "[345/trunk]"), ", [123], r234, [345/trunk], ar123"); generate.call(this, dom, "[123], r234, [345/trunk], ![123], !r234, ![345/trunk], ar123"); }); unit.add("[log]", function() { var dom = element("p", "log - ", a("log:@1:3", "r1:3"), ", r1:3, ", a("log:@1:3", "[1:3]"), ", [1:3], ", a("log:@1:3", "log:@1:3"), ", log:@1:3, ", a("log:trunk@1:3", "log:trunk@1:3"), ", log:trunk@1:3"); generate.call(this, dom, "log - r1:3, !r1:3, [1:3], ![1:3], log:@1:3, !log:@1:3, log:trunk@1:3, !log:trunk@1:3"); }); unit.add("wiki:TracLinks", function() { var dom = element("p", a("link:WikiName", "link:WikiName"), " ", a('link:"Foo Bar"', 'link:"Foo Bar"'), " ", a('link:"Foo Bar#baz"', 'link:"Foo Bar#baz"'), " ", a("link:'Foo Bar'", "link:'Foo Bar'"), " ", a("link:'Foo Bar#baz'", "link:'Foo Bar#baz'"), " ", a("svn+ssh://example.com/trunk", "svn+ssh://example.com/trunk"), " ", a("svn+ssh://example.com/trunk", "repository"), " ", a("rfc-2396.compatible://link", "rfc-2396.compatible://link"), " ", a("rfc-2396.compatible://link", "RFC 2396"), " ", a("foo:bar", "foo:bar"), " begin", a("foo:bar", "foo:bar"), " ", a("foo:bar", "foo:bar"), "end begin", a("wiki:WikiStart", "WikiStart"), "end link:'Foo Bar#baz'"); generateFragment.call(this, dom, [ "link:WikiName", 'link:"Foo Bar" link:"Foo Bar#baz"', "link:'Foo Bar' link:'Foo Bar#baz'", "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]", "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]", "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end", "!link:'Foo Bar#baz'" ].join(" ")); generate.call(this, dom, [ "link:WikiName", 'link:"Foo Bar" link:"Foo Bar#baz"', "link:'Foo Bar' link:'Foo Bar#baz'", "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]", "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]", "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end", "!link:'Foo Bar#baz'" ].join(" ")); }); unit.add("[wiki:TracLinks label]", function() { var dom = element("p", a("link:WikiName", "WikiName"), " ", a("link:WikiName", "wiki name"), " ", a("wiki:WikiName", "wiki]name"), " ", a("wiki:WikiName", "wiki name"), " ", a('link:"Foo Bar"', "Foo Bar"), " ", a('link:"Foo Bar#baz"', "Foo Bar#baz"), " ", a('link:"Foo Bar"', "bar foo"), " ", a('link:"Foo Bar#baz"', 'foo "foobar" bar'), " ", a("link:'Foo Bar'", "Foo Bar"), " ", a("link:'Foo Bar#baz'", "Foo Bar#baz"), " ", a("link:'Foo Bar'", "foo bar"), " ", a("link:'Foo Bar#baz'", "foo 'foobar' bar"), " [link:'Foo Bar#baz'] [link:'Foo Bar#baz' label]"); generateFragment.call(this, dom, [ "[link:WikiName]", "[link:WikiName 'wiki name']", '[wiki:WikiName "wiki]name"]', "[WikiName 'wiki name']", '[link:"Foo Bar"] [link:"Foo Bar#baz"]', '[link:"Foo Bar" "bar foo"] [link:"Foo Bar#baz" foo "foobar" bar]', "[link:'Foo Bar'] [link:'Foo Bar#baz']", "[link:'Foo Bar' 'foo bar'] [link:'Foo Bar#baz' foo 'foobar' bar]", "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" ")); generate.call(this, dom, [ "[link:WikiName]", "[link:WikiName wiki name]", '[wiki:WikiName "wiki]name"]', "[wiki:WikiName wiki name]", '[link:"Foo Bar" Foo Bar] [link:"Foo Bar#baz" Foo Bar#baz]', '[link:"Foo Bar" bar foo] [link:"Foo Bar#baz" foo "foobar" bar]', "[link:'Foo Bar' Foo Bar] [link:'Foo Bar#baz' Foo Bar#baz]", "[link:'Foo Bar' foo bar] [link:'Foo Bar#baz' foo 'foobar' bar]", "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" ")); }); unit.add("[/relative label]", function() { var dom = element("p", a("../trac", "Trac"), " ", a("/newticket?component=tracwysiwygplugin", "here"), " ", a("//hostname", "host"), " ", a("//hostname/images", "images"), " ", a("#anchor", "anchor")); var wikitext = [ "[../trac Trac]", "[/newticket?component=tracwysiwygplugin here]", "[//hostname host]", "[//hostname/images images]", "[#anchor anchor]" ].join(" "); generate.call(this, dom, wikitext); }); unit.add("[[macro]]", function() { var dom = element("p", "Line break ", element("br"), " another line", element("br"), "last line [[bR]] ![[Br]] [[Macro]] ![[Macro]]"); generateFragment.call(this, dom, "Line break [[BR]] another line[[br]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]]"); generate.call(this, dom, "Line break [[BR]] another line[[BR]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]]"); }); unit.add("WikiPageName", function() { var dom = fragment( element("p", a("wiki:CamelCase", "CamelCase"), " CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor"), element("p", a("wiki:WikiStart", "WikiStart"), " Wiki", a("wiki:Start", "Start"), " ", a("wiki:Wiki", "Wiki"), "Start Wiki", a("wiki:Start", "Start"), "Wiki")); generate.call(this, dom, [ "CamelCase !CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor", "", "WikiStart Wiki[wiki:Start] [wiki:Wiki]Start Wiki[wiki:Start]Wiki" ].join("\n")); }); unit.add('["internal free link"]', function() { var dom = element("p", "link - ", a('wiki:"internal free link"', "internal free link"), ' - ["free link"]'); generate.call(this, dom, 'link - [wiki:"internal free link" internal free link] - !["free link"]'); }); unit.add("traclink + underline", function() { var dom = element("p", element("u", a("ticket:123", "#123")), " ", a("ticket:123", element("u", "#123")), " ", element("u", a("report:123", "{123}")), " ", a("report:123", element("u", "{123}")), " ", element("u", a("changeset:123", "[123]")), " ", a("changeset:123", element("u", "[123]")), " ", element("u", a("changeset:123", "r123")), " ", a("changeset:123", element("u", "r123")), " ", element("u", a("log:@123:234", "[123:234]")), " ", a("log:@123:234", element("u", "[123:234]")), " ", element("u", a("wiki:WikiStart", "wiki:WikiStart")), " ", a("wiki:WikiStart", element("u", "wiki:WikiStart")), " ", element("u", a("wiki:WikiStart", "WikiStart")), " ", a("wiki:WikiStart", element("u", "WikiStart"))); generateWikitext.call(this, dom, [ '__#123__', '__#123__', '__{123}__', '__{123}__', '__[123]__', '__[123]__', '__[changeset:123 r123]__', '__[changeset:123 r123]__', '__[123:234]__', '__[123:234]__', '__[wiki:WikiStart wiki:WikiStart]__', '__[wiki:WikiStart wiki:WikiStart]__', '__[wiki:WikiStart]__', '__[wiki:WikiStart]__' ].join(" ")); }); unit.add("token + br", function() { var dom = fragment( element("p", "head ", a("http://localhost/", "http://localhost/"), element("br"), "tail"), element("p", "head http://localhost/", element("br"), "tail"), element("p", "head ", element("tt", "teletype"), element("br"), "tail"), element("p", "head ", a("wiki:TracLinks", "TracLinks"), element("br"), "tail"), element("p", "head ", a("http://localhost/", "http://localhost/"), " ", a("wiki:TracLinks", "wiki:TracLinks"), element("br"), "tail"), element("p", "head http://localhost/ wiki:TracLinks", element("br"), "tail")); generateWikitext.call(this, dom, [ "head http://localhost/ [[BR]]tail", "", "head !http://localhost/ [[BR]]tail", "", "head `teletype`[[BR]]tail", "", "head TracLinks[[BR]]tail", "", "head http://localhost/ wiki:TracLinks [[BR]]tail", "", "head !http://localhost/ !wiki:TracLinks [[BR]]tail" ].join("\n")); }); if (window.getSelection) { unit.add("block + br", function() { function br() { return element("br"); } var wikitext = [ "text, br", "", "text'', br[[BR]]''", "", "|| 1,1[[BR]] || || 1,3 ||", "|| || 2,2[[BR]][[BR]] ||", "", " * list, br[[BR]]", " * list, br", " * ", "", "text, br[[BR]]" ].join("\n") generateWikitext.call(this, fragment( element("p", "text, br", br()), element("p", "text", element("i", ", br", br()), br()), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br(), br()), element("td", br()), element("td", "1,3", br())), element("tr", element("td", br()), element("td", "2,2", br(), br(), br())))), element("ul", element("li", "list, br", br(), br()), element("li", "list, br", br()), element("li")), element("p", "text, br", br(), br())), wikitext); generateFragment.call(this, fragment( element("p", "text, br"), element("p", "text", element("i", ", br", br()), br()), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br(), br()), element("td", br()), element("td", "1,3")), element("tr", element("td", br()), element("td", "2,2", br(), br(), br())))), element("ul", element("li", "list, br", br(), br()), element("li", "list, br"), element("li", br())), element("p", "text, br", br(), br())), wikitext); }); } else { unit.add("block + br", function() { function br() { return element("br"); } var wikitext = [ "text, br", "", "text'', br[[BR]]''", "", "|| 1,1[[BR]] || || 1,3 ||", "|| || 2,2[[BR]][[BR]] ||", "", " * list, br[[BR]]", " * list, br", " * ", "", "text, br[[BR]]" ].join("\n") generate.call(this, fragment( element("p", "text, br"), element("p", "text", element("i", ", br", br())), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br()), element("td"), element("td", "1,3")), element("tr", element("td"), element("td", "2,2", br(), br())))), element("ul", element("li", "list, br", br()), element("li", "list, br"), element("li")), element("p", "text, br", br())), wikitext); }); } unit.add("citation", function() { var dom = fragment( element("blockquote", { "class": "citation" }, element("p", "This is the quoted text continued"), element("blockquote", { "class": "citation" }, element("p", "a nested quote"), element("blockquote", { "class": "citation" }, element("p", "a nested-nested quote")))), element("p", "A comment on the above"), element("blockquote", { "class": "citation" }, element("blockquote", { "class": "citation" }, element("p", "start 2nd level")), element("p", "first level"))); generateFragment.call(this, dom, [ "> This is the quoted text", "> continued", "> > a nested quote", "> > > a nested-nested quote", "A comment on the above", "> > start 2nd level", ">first level" ].join("\n")); generate.call(this, dom, [ "> This is the quoted text continued", "> > a nested quote", "> > > a nested-nested quote", "", "A comment on the above", "", "> > start 2nd level", "> first level" ].join("\n")); }); unit.add("header", function() { var dom = fragment( element("h1", "Heading 1"), element("h2", { id: "anchor-2" }, "Heading 2"), element("h3", element("u", "Heading"), " ", element("i", "3")), element("h4", { id: "アンカー-4" }, "Heading 4 with ", a("wiki:WikiStart", "link")), element("h5", "Heading 5"), element("h6", { id: "anchor-6" }, "Heading 6")); generate.call(this, dom, [ "= Heading 1 =", "== Heading 2 == #anchor-2", "=== __Heading__ ''3'' ===", "==== Heading 4 with [wiki:WikiStart link] ==== #アンカー-4", "===== Heading 5 =====", "====== Heading 6 ====== #anchor-6" ].join("\n")); }); unit.add("list", function() { var dom = fragment( element("p", "Paragraph"), element("ul", element("li", "foo bar boo baz"), element("ul", element("li", "Subitem Subitem line 2")), element("li", "item 2 item 2 line 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " * foo bar", " boo baz", " * Subitem", " Subitem line 2", " * item 2", " item 2 line 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " * foo bar boo baz", " * Subitem Subitem line 2", " * item 2 item 2 line 2", "", "Paragraph" ].join("\n")); }); unit.add("list 2", function() { var dom = fragment( element("ul", element("li", "foo bar boo baz"), element("ul", element("li", "Subitem 1"), element("ul", element("li", "nested item 1"), element("li", "nested item 2 nested item 2 continued")), element("li", "Subitem 2 subitem 2 continued"), element("li", "Subitem 3 subitem 3 continued")), element("li", "item 2 item 2 line 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ " * foo bar", " boo baz", " * Subitem 1", " - nested item 1", " - nested item 2", " nested item 2 continued", " * Subitem 2", " subitem 2 continued", " * Subitem 3", " subitem 3 continued", " * item 2", " item 2 line 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ " * foo bar boo baz", " * Subitem 1", " * nested item 1", " * nested item 2 nested item 2 continued", " * Subitem 2 subitem 2 continued", " * Subitem 3 subitem 3 continued", " * item 2 item 2 line 2", "", "Paragraph" ].join("\n")); }); unit.add("ordered list", function() { var dom = fragment( element("p", "Paragraph"), element("ol", element("li", "item 1"), element("ol", { "class": "arabiczero" }, element("li", "item 1.1"), element("li", "item 1.2"), element("ol", { "class": "loweralpha" }, element("li", "item 1.2.a"), element("li", "item 1.2.b")), element("li", "item 1.3"), element("ol", { "class": "loweralpha" }, element("li", "item 1.3.a"), element("li", "item 1.3.b")), element("li", "item 1.4"), element("ol", { "class": "upperalpha" }, element("li", "item 1.4.A"), element("li", "item 1.4.B"), element("li", "item 1.4.C")), element("li", "item 1.5"), element("ol", { "class": "upperalpha" }, element("li", "item 1.5.A")), element("li", "item 1.6"), element("ol", { "class": "lowerroman" }, element("li", "item 1.6.i"), element("li", "item 1.6.ii")), element("li", "item 1.7"), element("ol", { "class": "upperroman" }, element("li", "item 1.7.I"), element("li", "item 1.7.II")))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " 1. item 1", " 0. item 1.1", " 2. item 1.2", " a. item 1.2.a", " z. item 1.2.b", " a. item 1.3", " b. item 1.3.a", " y. item 1.3.b", " Z. item 1.4", " A. item 1.4.A", " z. item 1.4.B", " z. item 1.4.C", " ii. item 1.5", " C. item 1.5.A", " XVI. item 1.6", " i. item 1.6.i", " x. item 1.6.ii", " 0. item 1.7", " I. item 1.7.I", " III. item 1.7.II", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " 1. item 1", " 0. item 1.1", " 0. item 1.2", " a. item 1.2.a", " a. item 1.2.b", " 0. item 1.3", " a. item 1.3.a", " a. item 1.3.b", " 0. item 1.4", " A. item 1.4.A", " A. item 1.4.B", " A. item 1.4.C", " 0. item 1.5", " A. item 1.5.A", " 0. item 1.6", " i. item 1.6.i", " i. item 1.6.ii", " 0. item 1.7", " I. item 1.7.I", " I. item 1.7.II", "", "Paragraph" ].join("\n")); }); unit.add("list + ordered list", function() { var dom = fragment( element("ul", element("li", "Item 1"), element("ul", element("li", "Item 1.1")), element("li", "Item 2")), element("ol", element("li", "Item 1"), element("ol", { "class": "loweralpha" }, element("li", "Item 1.a"), element("li", "Item 1.b"), element("ol", { "class": "lowerroman" }, element("li", "Item 1.b.i"), element("li", "Item 1.b.ii"))), element("li", "Item 2")), element("p", "And numbered lists can also be given an explicit number:"), element("ol", { start: 3 }, element("li", "Item 3"))); generateFragment.call(this, dom, [ " * Item 1", " * Item 1.1", " * Item 2", " 1. Item 1", " a. Item 1.a", " a. Item 1.b", " i. Item 1.b.i", " i. Item 1.b.ii", " 1. Item 2", "And numbered lists can also be given an explicit number:", " 3. Item 3" ].join("\n")); generate.call(this, dom, [ " * Item 1", " * Item 1.1", " * Item 2", "", " 1. Item 1", " a. Item 1.a", " a. Item 1.b", " i. Item 1.b.i", " i. Item 1.b.ii", " 1. Item 2", "", "And numbered lists can also be given an explicit number:", "", " 3. Item 3" ].join("\n")); }); unit.add("list + code block", function() { var dom = fragment( element("p", "Paragraph"), element("ul", element("li", "item 1", element("pre", { "class": "wiki" }, "code")), element("ul", element("li", "item 1.1", element("pre", { "class": "wiki" }, "code"), "cont.", element("pre", { "class": "wiki" }, "code"))), element("li", "item 2", element("pre", { "class": "wiki" }, "code"))), element("ol", element("li", "item 1"))); generateFragment.call(this, dom, [ "Paragraph", " * item 1", "{{{", "code", "}}}", " * item 1.1", "{{{", "code", "}}}", " cont.", "{{{", "code", "}}}", " * item 2", "{{{", "code", "}}}", " 1. item 1" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " * item 1", "{{{", "code", "}}}", " * item 1.1", "{{{", "code", "}}}", " cont.", "{{{", "code", "}}}", " * item 2", "{{{", "code", "}}}", "", " 1. item 1" ].join("\n")); }); unit.add("list + citation", function() { var dom = fragment( element('ol', element('li', 'item 1')), element('blockquote', { 'class': 'citation' }, element("p", "citation 1")), element('ul', element('li', 'item 2'), element("ol", element('li', 'item 2.1'), element('li', 'item 2.2'))), element('blockquote', { 'class': 'citation' }, element("p", "citation 2 citation 3")), element('ol', element('li', 'item 3'))); generateFragment.call(this, dom, [ ' 1. item 1', '> citation 1', ' * item 2', ' 1. item 2.1', ' 1. item 2.2', '> citation 2', '> citation 3', ' 1. item 3' ].join("\n")); generateWikitext.call(this, dom, [ ' 1. item 1', '', '> citation 1', '', ' * item 2', ' 1. item 2.1', ' 1. item 2.2', '', '> citation 2 citation 3', '', ' 1. item 3' ].join("\n")); }); unit.add("definition", function() { var dom = element("dl", element("dt", "python"), element("dd", "www.python.org :: cont."), element("dt", element("b", "trac")), element("dd", element("b", "trac"), ".edgewall.org cont.", " ", element("tt", "trac-hacks::"), " trac-hacks.org")); generateFragment.call(this, dom, [ " python:: www.python.org :: cont.", " '''trac''':: '''trac'''.edgewall.org", " cont.", " `trac-hacks::` trac-hacks.org" ].join("\n")); generate.call(this, dom, [ " python:: www.python.org :: cont.", " '''trac''':: '''trac'''.edgewall.org cont. `trac-hacks::` trac-hacks.org" ].join("\n")); }); unit.add("blockquote", function() { var dom = fragment( element("p", "Paragraph"), element("blockquote", element("p", "blockquote 1 cont. 1"), element("blockquote", element("p", "blockquote 1.1"), element("blockquote", element("p", "blockquote 1.1.1 cont. 1.1.1")), element("p", "blockquote 1.2")), element("p", "blockquote 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " blockquote 1", " cont. 1", " blockquote 1.1", " blockquote 1.1.1", " cont. 1.1.1", " blockquote 1.2", " blockquote 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " blockquote 1 cont. 1", " blockquote 1.1", " blockquote 1.1.1 cont. 1.1.1", " blockquote 1.2", " blockquote 2", "", "Paragraph" ].join("\n")); }); unit.add("table", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2")), element("tr", element("td", "2.1")), element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3"), " ", element("tt", "-"))))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||1.1||1.2||", "||2.1", "||3.1||__3.2__||`3` `-`", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| 1.1 || 1.2 ||", "|| 2.1 ||", "|| 3.1 || __3.2__ || `3` `-` ||", "", "Paragraph" ].join("\n")); }); unit.add("table + rule", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1st")))), element("p", element("b", "bold")), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "2nd")))), element("p", "'''normal")); generateFragment.call(this, dom, [ "||1st||", "'''bold'''", "||2nd||", "!'''normal" ].join("\n")); generate.call(this, dom, [ "|| 1st ||", "", "'''bold'''", "", "|| 2nd ||", "", "!'''normal" ].join("\n")); }); unit.add("blockquote + table", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "pre.1"), element("td", "pre.2")))), element("blockquote", element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2")), element("tr", element("td", "2.1")))), element("blockquote", element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "deep"))))), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3.3")))))), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "post.1"), element("td", "post.2")))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||pre.1||pre.2||", " ||1.1||1.2||", " ||2.1", " ||deep||", " ||3.1||__3.2__||`3.3`", "||post.1||post.2||", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| pre.1 || pre.2 ||", "", " || 1.1 || 1.2 ||", " || 2.1 ||", " || deep ||", " || 3.1 || __3.2__ || `3.3` ||", "", "|| post.1 || post.2 ||", "", "Paragraph" ].join("\n")); }); unit.add("table [ paragraph, ul ]", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", element("p", "1.1")), element("td", element("ul", element("li", "item 1"), element("li", "item 2")))), element("tr", element("td", element("p", "2.1"), element("ul", element("li", "item 3"), element("li", "item 4"))))))); generateWikitext.call(this, dom, [ "|| 1.1 || * item 1[[BR]] * item 2 ||", "|| 2.1[[BR]][[BR]] * item 3[[BR]] * item 4 ||" ].join("\n")); }); unit.add("table with incomplete markups", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", element("b", element("i", "'"))), element("td", element("b", "bold"))) ) ) ); generateFragment.call(this, dom, "|| '''''' || '''bold''' ||"); }); unit.add("table from word", function() { var dom = element("div"); dom.innerHTML = [ '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '
', '

a

', '

b

', '
', '', '

b

', '
', '

c

', '
', '', '

d

', '
', '' ].join("\n"); generateWikitext.call(this, dom, [ "|| a[[BR]][[BR]]b || b ||", "|| c || d ||" ].join("\n")); }); unit.add("domToWikitext for code block", function() { var br = function() { return element("br") }; var dom = fragment( element("h1", "Heading", br(), "1"), element("h2", "Heading", br(), "2"), element("h3", "Heading", br(), "3"), element("h4", "Heading", br(), "4"), element("h5", "Heading", br(), "5"), element("h6", "Heading", br(), "6"), element("p", "var TracWysiwyg = function(textarea) {", br(), "...", br(), "}"), element("blockquote", { "class": "citation" }, element("p", "citation", br(), "continued")), element("blockquote", element("p", "quote", br(), "continued")), element("ul", element("li", "item 1", br(), "continued"), element("ol", element("li", "item", br(), "1.1"))), element("dl", element("dt", "def to_s(", br(), ")"), element("dd", "dt", br(), "dd")), element("table", element("tbody", element("tr", element("td", "cell", br(), "1"), element("th", "cell", br(), "2"))))); var wikitext = instance.domToWikitext(dom, { formatCodeBlock: true }); this.assertEqual([ "= Heading 1 =", "== Heading 2 ==", "=== Heading 3 ===", "==== Heading 4 ====", "===== Heading 5 =====", "====== Heading 6 ======", "var TracWysiwyg = function(textarea) {", "...", "}", "", "> citation", "> continued", "", " quote", " continued", "", " * item 1", " continued", " 1. item", " 1.1", "", " def to_s( ):: dt", " dd", "", "|| cell[[BR]]1 || cell[[BR]]2 ||" ].join("\n"), wikitext); }); unit.add("selectRange", function() { var d = instance.contentDocument; function _element() { var args = [ d ]; args.push.apply(args, arguments); return element.apply(this, args); } function _text() { var args = [ d ]; args.push.apply(args, arguments); return text.apply(this, args); } function assertRangeText(expected, start, startOffset, end, endOffset) { instance.selectRange(start, startOffset, end, endOffset); if (expected instanceof RegExp) { unit.assertMatch(expected, instance.getSelectionText()); } else { unit.assertEqual(expected, instance.getSelectionText()); } } var body = d.body; while (body.childNodes.length > 0) { body.removeChild(body.lastChild); } body.appendChild(fragment(d, _element("p", "The", " quick", " brown", _element("b", " fox", " jumps", " over"), " the", " lazy", " dog."), _element("p", "Brick ", "quiz ", "whangs ", "jumpy ", "veldt ", "fox."))); var paragraph1 = body.childNodes[0]; var paragraph2 = body.childNodes[1]; var bold = paragraph1.childNodes[3]; assertRangeText("The", paragraph1.childNodes[0], 0, paragraph1.childNodes[0], 3); assertRangeText("he", paragraph1.childNodes[0], 1, paragraph1.childNodes[0], 3); assertRangeText("e quick brow", paragraph1.childNodes[0], 2, paragraph1.childNodes[2], 5); assertRangeText("ick brown", paragraph1.childNodes[1], 3, paragraph1.childNodes[2], 6); assertRangeText("ick brown fox j", paragraph1.childNodes[1], 3, bold.childNodes[1], 2); assertRangeText("ver the laz", bold.childNodes[2], 2, paragraph1.childNodes[5], 4); assertRangeText(" the lazy", paragraph1.childNodes[4], 0, paragraph1.childNodes[5], 5); assertRangeText("lazy dog.", paragraph1.childNodes[5], 1, paragraph1.childNodes[6], 5); assertRangeText(/^fox jumps over the lazy dog\.[\r\n]*Brick quiz whangs$/, bold.childNodes[0], 1, paragraph2.childNodes[2], 6); assertRangeText(" fox jumps over", paragraph1, 3, paragraph1, 4); assertRangeText(" dog.", paragraph1, 6, paragraph1, 7); assertRangeText("", paragraph1, 7, paragraph1, 7); assertRangeText("quick brown fox jumps over", paragraph1.childNodes[1], 1, paragraph1, 4); assertRangeText(" fox jumps over t", paragraph1, 3, paragraph1.childNodes[4], 2); }); unit.run(); } var button = document.createElement("button"); button.innerHTML = "run »"; button.style.textDecoration = "underline"; document.body.appendChild(button); addEvent(button, "click", run); button.focus(); }); trac-wysiwyg-0.12.0.3+r10725/0.10/tests/testunit.js0000644000175000017500000001527311642336132017342 0ustar wmbwmbTracWysiwyg.TestUnit = function() { this.cases = {}; this.assertCounts = {}; this.current = null; }; (function() { var prototype = TracWysiwyg.TestUnit.prototype; prototype.inspect = function(value) { var type = typeof value; switch (type) { case "string": return value.replace(/[\u0000-\u001f\\\u007f\ufffe\uffff]/g, function(m) { var code = m.charCodeAt(0); switch (code) { case 9: return "\\t"; case 10: return "\\n"; case 11: return "\\v"; case 12: return "\\f"; case 13: return "\\r"; case 92: return "\\\\"; } return "\\u" + (0x10000 + code).toString(16).substring(1); }); break; case "object": case "function": if (value instanceof RegExp) { return value.toString(); } } return "{%}".replace("%", type) + value.toString(); }; prototype.fragment = function() { var start = 0; var arg = arguments[0]; var d; if (arg.nodeType != 9) { d = document; } else { d = arg; start = 1; } var fragment = d.createDocumentFragment(); var length = arguments.length; for (var i = start; i < length; i++) { fragment.appendChild(arguments[i]); } return fragment; }; prototype.element = function(tag) { var start = 0; var arg = arguments[start++]; var d, tag; if (typeof arg == "string") { d = document; tag = arg; } else { d = arg; tag = arguments[start++]; } var element = d.createElement(tag); for (var i = start; i < arguments.length; i++) { arg = arguments[i]; switch (typeof arg) { case "object": if (typeof arg.nodeType == "undefined") { for (var name in arg) { var value = arg[name]; switch (name) { case "id": element.id = value; break; case "class": case "className": element.className = value; break; default: element.setAttribute(name, value); break; } } continue; } break; case "string": arg = d.createTextNode(arg); break; } element.appendChild(arg); } return element; }; prototype.text = function() { var start = 0; var arg = arguments[start++]; var d, text; if (typeof arg == "string") { d = document; text = arg; } else { d = arg; text = arguments[start++]; } return d.createTextNode(text); }; prototype.$ = function(id) { return typeof id == "string" ? document.getElementById(id) : id; }; prototype.add = function(name, method) { if (name in this.cases) { throw "'" + name + "' is in use."; } this.cases[name] = method; this.assertCounts[name] = 0; }; prototype.assertEqual = function(expected, actual, label) { var count = ++this.assertCounts[this.current]; if (typeof (expected) == typeof (actual) && expected == actual) { return true; } throw (label || "") + "[" + count + "]\n" + this.inspect(expected) + " (" + expected.length + ")\n" + this.inspect(actual) + " (" + actual.length + ")"; }; prototype.assertMatch = function(pattern, string, label) { var count = ++this.assertCounts[this.current]; if (pattern.test(string)) { return true; } throw (label || "") + "[" + count + "]\n" + this.inspect(pattern) + "\n" + this.inspect(string) + " (" + string.length + ")"; }; prototype.run = function() { var self = this var $ = this.$, element = this.element, text = this.text; var d = document; var cases = this.cases; var assertCounts = this.assertCounts; var names = []; for (var name in cases) { names.push(name); assertCounts[name] = 0; } var container = $("testunit"); var count; if (container) { container.parentNode.removeChild(container); } container = element( "table", { id: "testunit" }, element("caption", { id: "testunit.summary" }), element("tbody", { id: "testunit.body" })); d.body.appendChild(container); var body = $("testunit.body"); var summary = $("testunit.summary"); for (count = 0; count < names.length; count++) { body.appendChild( element("tr", element("td", names[count]), element("td", { id: "testcase." + count }, "..."))); } count = 0; var success = 0; var invoke = function() { if (count >= names.length) { self.current = null; return; } var current = names[count]; self.current = current; var cell = $("testcase." + count); cell.className = "current"; try { cases[current].call(self); cell.className = "success"; cell.replaceChild(text("OK"), cell.firstChild); success++; } catch (e) { cell.className = "failure"; var message = e.message || e.toString(); if (e.stack) { message = [ message, e.stack ].join("\n\n"); } cell.replaceChild( element("textarea", { id: "testcase." + count + ".textarea", rows: message.split("\n").length, cols: 80, readonly: "readonly" }), cell.firstChild); $("testcase." + count + ".textarea").value = message; } summary.innerHTML = success + " / " + names.length; count++; setTimeout(invoke, 10); }; invoke(); }; })(); trac-wysiwyg-0.12.0.3+r10725/0.10/tests/index.html0000644000175000017500000000343111463324376017123 0ustar wmbwmb tracwysiwyg test
trac-wysiwyg-0.12.0.3+r10725/0.10/tests/trac.js0000644000175000017500000000101010714562212016373 0ustar wmbwmbfunction addEvent(element, type, listener) { if (element.addEventListener) { element.addEventListener(type, listener, false); return true; } else if (element.attachEvent) { return element.attachEvent("on" + type, listener); } return false; } function getAncestorByTagName(node, tag) { tag = tag.toLowerCase(); do { node = node.parentNode; } while (node.nodeType == 1 && node.tagName.toLowerCase() != tag); return node.nodeType == 1 ? node : null; } trac-wysiwyg-0.12.0.3+r10725/0.10/MANIFEST.in0000644000175000017500000000014210672463456015522 0ustar wmbwmbinclude tracwysiwyg/htdocs/*.js include tracwysiwyg/htdocs/*.css include tracwysiwyg/htdocs/*.png trac-wysiwyg-0.12.0.3+r10725/0.10/bookmarklet.js0000644000175000017500000000471411314717400016626 0ustar wmbwmb/* * javascript:(function(d,u){var s=d.createElement('script');s.charset='utf-8';s.src=u;d.getElementsByTagName('head')[0].appendChild(s)})(document,'http://trac-hacks.org/svn/tracwysiwygplugin/0.10/bookmarklet.js') */ (function() { var w = window; var d = document; var base = 'http://trac-hacks.org/svn/tracwysiwygplugin/0.10/tracwysiwyg/htdocs/'; var head = d.getElementsByTagName('head')[0]; var script = d.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('charset', 'utf-8'); script.src = base + 'wysiwyg.js'; head.appendChild(script); var link = d.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type', 'text/css'); link.setAttribute('href', base + 'wysiwyg.css'); head.appendChild(link); function getTracPaths() { var paths = { stylesheets: [] }; var links = head.getElementsByTagName('link'); var length = links.length; for (var i = 0; i < length; i++) { var link = links[i]; var rel = (link.getAttribute('rel') || '').toLowerCase(); var type = (link.getAttribute('type') || '').toLowerCase(); var href = link.getAttribute('href') || ''; switch (rel) { case 'help': if (!paths.base && /\/wiki\/TracGuide$/.test(href)) { paths.base = href.slice(0, -14); } break; case 'search': if (!paths.search && !type && /\/search$/.test(href)) { paths.search = href; paths.base = href.slice(0, -6); } break; case 'stylesheet': if (/\/css\/trac\.css$/.test(href)) { paths.stylesheets.push(href); } break; } } if (paths.base && paths.stylesheets.length > 0) { if (!paths.search) { paths.search = paths.base + 'search'; } paths.stylesheets.push(base + 'editor.css'); return paths; } return null; } function lazy() { switch (typeof w.TracWysiwyg) { case 'undefined': setTimeout(lazy, 100); return; case 'function': TracWysiwyg.getTracPaths = getTracPaths; TracWysiwyg.initialize(); break; } } lazy(); })(); trac-wysiwyg-0.12.0.3+r10725/0.11/0000755000175000017500000000000011677636642013775 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/0000755000175000017500000000000011677636642016371 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/__init__.py0000644000175000017500000000753011356644040020470 0ustar wmbwmb# -*- coding: utf-8 -*- import re from genshi.builder import tag from genshi.filters.transform import Transformer from trac.core import Component, implements from trac.config import ListOption, _TRUE_VALUES from trac.ticket.web_ui import TicketModule from trac.web.api import IRequestFilter, ITemplateStreamFilter from trac.web.chrome import ITemplateProvider, add_link, add_stylesheet, add_script from trac.web.href import Href __all__ = ['WysiwygModule'] class WysiwygModule(Component): implements(ITemplateProvider, IRequestFilter, ITemplateStreamFilter) wysiwyg_stylesheets = ListOption('tracwysiwyg', 'wysiwyg_stylesheets', doc="""Add stylesheets to the WYSIWYG editor""") # ITemplateProvider#get_htdocs_dirs def get_htdocs_dirs(self): from pkg_resources import resource_filename return [('tracwysiwyg', resource_filename(__name__, 'htdocs'))] # ITemplateProvider#get_templates_dirs def get_templates_dirs(self): return [] # IRequestFilter#pre_process_request def pre_process_request(self, req, handler): return handler # IRequestFilter#post_process_request def post_process_request(self, req, template, data, content_type): add_link(req, 'tracwysiwyg.base', req.href() or '/') stylesheets = ['chrome/common/css/trac.css', 'chrome/tracwysiwyg/editor.css'] stylesheets += self.wysiwyg_stylesheets for stylesheet in stylesheets: add_link(req, 'tracwysiwyg.stylesheet', _expand_filename(req, stylesheet)) add_stylesheet(req, 'tracwysiwyg/wysiwyg.css') add_script(req, 'tracwysiwyg/wysiwyg.js') add_script(req, 'tracwysiwyg/wysiwyg-load.js') return (template, data, content_type) # ITemplateStreamFilter def filter_stream(self, req, method, filename, stream, data): options = {} if filename == 'ticket.html': options['escapeNewlines'] = _preserve_newlines(self.env) if options: text = 'var _tracwysiwyg = %s' % _to_json(options) stream |= Transformer('//head').append(tag.script(text, type='text/javascript')) return stream def _preserve_newlines(env): ticket = TicketModule(env) # Trac 0.11.2 later if hasattr(ticket, 'must_preserve_newlines'): return ticket.must_preserve_newlines preserve_newlines = ticket.preserve_newlines if preserve_newlines == 'default': preserve_newlines = env.get_version(initial=True) >= 21 # 0.11 return preserve_newlines in _TRUE_VALUES def _expand_filename(req, filename): if filename.startswith('chrome/common/') and 'htdocs_location' in req.chrome: href = Href(req.chrome['htdocs_location']) return href(filename[14:]) if filename.startswith('/') or re.match(r'https?://', filename): href = Href(filename) return href() return req.href(filename) _escape_re = re.compile(r'[\010\f\n\r\t"><&\\]') _escape_chars = { '\010': r'\b', '\f' : r'\f', '\n' : r'\n', '\r' : r'\r', '\t' : r'\t', '"' : r'\"', '>' : r'\u003E', '<' : r'\u003C', '&' : r'\u0026', '\\' : r'\\', } def _escape_replace(match): return _escape_chars[match.group(0)] def _to_json(value): if isinstance(value, basestring): return '"%s"' % _escape_re.sub(_escape_replace, value) if value is None: return 'null' if value is False: return 'false' if value is True: return 'true' if isinstance(value, (int, long)): return str(value) if isinstance(value, (list, tuple)): return '[ %s ]' % ', '.join([_to_json(v) for v in value]) if isinstance(value, dict): return '{ %s }' % ', '.join([ '%s: %s' % (_to_json(k), _to_json(v)) for k, v in value.iteritems()]) raise TypeError, 'Unsupported type "%s"' % type(value) trac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/htdocs/0000755000175000017500000000000011677636642017655 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/htdocs/wysiwyg.css0000644000175000017500000001035611306772706022105 0ustar wmbwmbiframe.wysiwyg { border: 1px solid #d7d7d7; clear: both; display: block; } iframe.wysiwyg:focus { border: 1px solid #886; } .editor-toggle { float: right; font-size: 80%; } .wysiwyg-toolbar { border: solid #d7d7d7; border-width: 1px 1px 1px 0; height: 18px; width: 400px; float: left; } .wysiwyg-toolbar ul, .wysiwyg-toolbar li { list-style-type: none; margin: 0px; padding: 0px; } .wysiwyg-toolbar li { float: left; display: block; } .wysiwyg-toolbar li :link, .wysiwyg-toolbar li :visited { background: transparent url(toolbar.png) no-repeat; border: 1px solid #fff; border-left-color: #d7d7d7; cursor: default; display: block; width: 20px; height: 16px; color: #777; } .wysiwyg-toolbar li.selected :link, .wysiwyg-toolbar li.selected :visited { border: 1px solid #7c4; } .wysiwyg-toolbar li a:hover, .wysiwyg-toolbar li.selected a:hover { background-color: transparent; border: 1px solid #fb2; color: #886; } .wysiwyg-toolbar li a#wt-style { width: 62px; white-space: nowrap; overflow-x: hidden; line-height: 1.2; padding-left: 2px; padding-right: 2px; background-image: url(../common/desc.png); background-position: right bottom; } .wysiwyg-toolbar li a#wt-style span { display: none; } .wysiwyg-toolbar li.wysiwyg-menu-style a#wt-style span.wysiwyg-menu-style { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-paragraph a#wt-style span.wysiwyg-menu-paragraph { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading1 a#wt-style span.wysiwyg-menu-heading1 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading2 a#wt-style span.wysiwyg-menu-heading2 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading3 a#wt-style span.wysiwyg-menu-heading3 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading4 a#wt-style span.wysiwyg-menu-heading4 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading5 a#wt-style span.wysiwyg-menu-heading5 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-heading6 a#wt-style span.wysiwyg-menu-heading6 { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-code a#wt-style span.wysiwyg-menu-code { display: inline; } .wysiwyg-toolbar li.wysiwyg-menu-quote a#wt-style span.wysiwyg-menu-quote { display: inline; } .wysiwyg-toolbar li a#wt-em { background-position: 0 0; } .wysiwyg-toolbar li a#wt-strong { background-position: 0 -16px; } .wysiwyg-toolbar li a#wt-underline { background-position: 0 -32px; } .wysiwyg-toolbar li a#wt-monospace { background-position: 0 -160px; } .wysiwyg-toolbar li a#wt-link { background-position: 0 -96px; } .wysiwyg-toolbar li a#wt-unlink { background-position: 0 -112px; } .wysiwyg-toolbar li a#wt-ol { background-position: 0 -176px; } .wysiwyg-toolbar li a#wt-ul { background-position: 0 -192px; } .wysiwyg-toolbar li a#wt-outdent { background-position: 0 -208px; } .wysiwyg-toolbar li a#wt-indent { background-position: 0 -224px; } .wysiwyg-toolbar li a#wt-table { background-position: 0 -240px; } .wysiwyg-toolbar li a#wt-hr { background-position: 0 -128px; } .wysiwyg-toolbar li a#wt-br { background-position: 0 -144px; } .wysiwyg-toolbar li a#wt-remove { background-position: 0 -256px; } .wysiwyg-toolbar li a#wt-decorationmenu, .wysiwyg-toolbar li a#wt-tablemenu { width: 10px; background-image: url(../common/desc.png); background-position: center bottom; } .wysiwyg-menu { border: 1px solid #d7d7d7; padding: 1px 2px; background-color: #fff; -moz-opacity: 0.90; opacity: 0.90; } .wysiwyg-menu p, .wysiwyg-menu h1, .wysiwyg-menu h2, .wysiwyg-menu h3, .wysiwyg-menu h4, .wysiwyg-menu h5, .wysiwyg-menu h6, .wysiwyg-menu pre.wiki, .wysiwyg-menu blockquote.citation { margin: 0px; } .wysiwyg-menu ul, .wysiwyg-menu li { list-style-type: none; margin: 0px; padding: 0px; } .wysiwyg-menu :link, .wysiwyg-menu :visited { display: block; padding: 1px; border: 1px solid #fff; color: #000; } .wysiwyg-menu .selected :link, .wysiwyg-menu .selected :visited { border: 1px solid #7c4; } .wysiwyg-menu a:hover, .wysiwyg-menu .selected a:hover { border: 1px solid #fb2; } .wysiwyg-menu .menu { font-size: 85%; } trac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/htdocs/wysiwyg-load.js0000644000175000017500000000012510761221176022631 0ustar wmbwmbjQuery(document).ready(function($) { setTimeout(TracWysiwyg.initialize, 10); }); trac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/htdocs/wysiwyg.js0000644000175000017500000040462011642344654021732 0ustar wmbwmbvar TracWysiwyg = function(textarea, options) { var self = this; var editorMode = TracWysiwyg.getEditorMode(); this.autolink = true; this.textarea = textarea; this.options = options = options || {}; var wikitextToolbar = textarea.previousSibling; if (wikitextToolbar && (wikitextToolbar.nodeType != 1 || wikitextToolbar.className != "wikitoolbar")) { wikitextToolbar = null; } this.wikitextToolbar = wikitextToolbar; var anonymous = document.createElement("div"); anonymous.innerHTML = ''; var frame = anonymous.firstChild; textarea.parentNode.insertBefore(frame, textarea.nextSibling); this.frame = frame; this.contentWindow = frame.contentWindow; this.contentDocument = this.contentWindow.document; this.initializeEditor(this.contentDocument); this.wysiwygToolbar = this.createWysiwygToolbar(document); this.styleMenu = this.createStyleMenu(document); this.decorationMenu = this.createDecorationMenu(document); this.tableMenu = this.createTableMenu(document); this.menus = [ this.styleMenu, this.decorationMenu, this.tableMenu ]; this.toolbarButtons = this.setupMenuEvents(); this.toggleEditorButtons = null; this.autolinkButton = null; this.savedWysiwygHTML = null; this.setupToggleEditorButtons(); this.setupSyncResizingTextArea(); var styleStatic = { position: "static", left: "-9999px", top: "-9999px" }; var styleAbsolute = { position: "absolute", left: "-9999px", top: "-9999px" }; switch (editorMode) { case "textarea": TracWysiwyg.setStyle(textarea, styleStatic); if (wikitextToolbar) { TracWysiwyg.setStyle(wikitextToolbar, styleStatic); } TracWysiwyg.setStyle(frame, { position: "absolute", left: "-9999px", top: TracWysiwyg.elementPosition(textarea).top + "px" }); TracWysiwyg.setStyle(this.wysiwygToolbar, styleAbsolute); TracWysiwyg.setStyle(this.autolinkButton.parentNode, { display: "none" }); textarea.setAttribute("tabIndex", ""); frame.setAttribute("tabIndex", "-1"); break; case "wysiwyg": TracWysiwyg.setStyle(textarea, { position: "absolute", left: "-9999px", top: TracWysiwyg.elementPosition(textarea).top + "px" }); if (wikitextToolbar) { TracWysiwyg.setStyle(wikitextToolbar, styleAbsolute); } TracWysiwyg.setStyle(frame, styleStatic); TracWysiwyg.setStyle(this.wysiwygToolbar, styleStatic); TracWysiwyg.setStyle(this.autolinkButton.parentNode, { display: "" }); textarea.setAttribute("tabIndex", "-1"); frame.setAttribute("tabIndex", ""); break; } frame.parentNode.insertBefore(this.wysiwygToolbar, frame); var body = document.body; for (var i = 0; i < this.menus.length; i++) { body.insertBefore(this.menus[i], body.firstChild); } var element = this.wikitextToolbar || this.textarea; element.parentNode.insertBefore(this.toggleEditorButtons, element); function lazySetup() { if (self.contentDocument.body) { var exception; try { self.execCommand("useCSS", false); } catch (e) { } try { self.execCommand("styleWithCSS", false); } catch (e) { } if (editorMode == "wysiwyg") { try { self.loadWysiwygDocument() } catch (e) { exception = e } } self.setupEditorEvents(); self.setupFormEvent(); if (exception) { self.textarea.style.position = "static"; if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "static"; } self.frame.style.position = self.wysiwygToolbar.style.position = "absolute"; self.autolinkButton.parentNode.style.display = "none"; alert("Failed to activate the wysiwyg editor."); throw exception; } } else { setTimeout(lazySetup, 100); } } lazySetup(); }; TracWysiwyg.prototype.initializeEditor = function(d) { var l = window.location; var html = []; html.push( '\n', '', '', '', ''); var stylesheets = TracWysiwyg.tracPaths.stylesheets; if (!stylesheets) { // Work around wysiwyg stops with Agilo var base = TracWysiwyg.tracPaths.base.replace(/\/*$/, "/"); stylesheets = [ base + "chrome/common/css/trac.css", base + "chrome/tracwysiwyg/editor.css" ]; } var length = stylesheets.length; for (var i = 0; i < length; i++) { html.push(''); } html.push('', '', '', ''); var first = !window.opera && d.addEventListener ? true : false; if (first) { d.designMode = "On"; } d.open(); d.write(html.join("")); d.close(); if (!first) { d.designMode = "On"; if (d != this.contentWindow.document) { this.contentDocument = this.contentWindow.document; } } }; TracWysiwyg.prototype.toggleAutolink = function() { this.autolink = !this.autolink; this.autolinkButton.checked = this.autolink; }; TracWysiwyg.prototype.listenerToggleAutolink = function(input) { var self = this; return function(event) { self.autolink = input.checked; }; }; TracWysiwyg.prototype.listenerToggleEditor = function(type) { var self = this; switch (type) { case "textarea": return function(event) { if (self.textarea.style.position == "absolute") { self.hideAllMenus(); self.loadTracWikiText(); self.textarea.style.position = "static"; self.textarea.setAttribute("tabIndex", ""); if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "static"; } self.frame.style.position = self.wysiwygToolbar.style.position = "absolute"; self.frame.setAttribute("tabIndex", "-1"); self.autolinkButton.parentNode.style.display = "none"; TracWysiwyg.setEditorMode(type); } self.focusTextarea(); }; case "wysiwyg": return function(event) { if (self.frame.style.position == "absolute") { try { self.loadWysiwygDocument(); } catch (e) { TracWysiwyg.stopEvent(event || window.event); alert("Failed to activate the wysiwyg editor."); throw e; } self.syncResizingTextArea(); self.textarea.style.position = "absolute"; self.textarea.setAttribute("tabIndex", "-1"); if (self.wikitextToolbar) { self.wikitextToolbar.style.position = "absolute"; } self.frame.style.position = self.wysiwygToolbar.style.position = "static"; self.frame.setAttribute("tabIndex", ""); self.autolinkButton.parentNode.style.display = ""; TracWysiwyg.setEditorMode(type); } self.focusWysiwyg(); }; } }; TracWysiwyg.prototype.activeEditor = function() { return this.textarea.style.position == "absolute" ? "wysiwyg" : "textarea"; }; TracWysiwyg.prototype.setupFormEvent = function() { var self = this; function listener(event) { var textarea = self.textarea; try { if (textarea.style.position == "absolute") { var body = self.contentDocument.body; if (self.savedWysiwygHTML !== null && body.innerHTML != self.savedWysiwygHTML) { textarea.value = self.domToWikitext(body, self.options); } } } catch (e) { TracWysiwyg.stopEvent(event || window.event); } } addEvent(this.textarea.form, "submit", listener); }; TracWysiwyg.prototype.createWysiwygToolbar = function(d) { var html = [ '' ]; var div = d.createElement("div"); div.className = "wysiwyg-toolbar"; div.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return div; }; TracWysiwyg.prototype.createStyleMenu = function(d) { var html = [ '

Normal

', '

Header 1

', '

Header 2

', '

Header 3

', '

Header 4

', '
Header 5
', '
Header 6
', '
Code block
', '
Quote
' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.createDecorationMenu = function(d) { var html = [ '' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.createTableMenu = function(d) { var html = [ '' ]; var menu = d.createElement("div"); menu.className = "wysiwyg-menu"; TracWysiwyg.setStyle(menu, { position: "absolute", left: "-1000px", top: "-1000px", zIndex: 1000 }); menu.innerHTML = html.join("").replace(/ href="#">/g, ' href="#" onmousedown="return false" tabindex="-1">'); return menu; }; TracWysiwyg.prototype.setupMenuEvents = function() { function addToolbarEvent(element, self, args) { var method = args.shift(); addEvent(element, "click", function(event) { var w = self.contentWindow; TracWysiwyg.stopEvent(event || w.event); var keepMenus = false, exception; try { keepMenus = method.apply(self, args) } catch (e) { exception = e } if (!keepMenus) { self.hideAllMenus(); } element.blur(); w.focus(); if (exception) { throw exception; } }); } function argsByType(self, name, element) { switch (name) { case "style": return [ self.toggleMenu, self.styleMenu, element ]; case "strong": return [ self.execDecorate, "bold" ]; case "em": return [ self.execDecorate, "italic" ]; case "underline": return [ self.execDecorate, "underline" ]; case "strike": return [ self.execDecorate, "strikethrough" ]; case "sub": return [ self.execDecorate, "subscript" ]; case "sup": return [ self.execDecorate, "superscript" ]; case "monospace": return [ self.execDecorate, "monospace" ]; case "decorationmenu": return [ self.toggleMenu, self.decorationMenu, element ]; case "remove": return [ self.execCommand, "removeformat" ]; case "paragraph": return [ self.formatParagraph ]; case "heading1": return [ self.formatHeaderBlock, "h1" ]; case "heading2": return [ self.formatHeaderBlock, "h2" ]; case "heading3": return [ self.formatHeaderBlock, "h3" ]; case "heading4": return [ self.formatHeaderBlock, "h4" ]; case "heading5": return [ self.formatHeaderBlock, "h5" ]; case "heading6": return [ self.formatHeaderBlock, "h6" ]; case "link": return [ self.createLink ]; case "unlink": return [ self.execCommand, "unlink" ]; case "ol": return [ self.insertOrderedList ]; case "ul": return [ self.insertUnorderedList ]; case "outdent": return [ self.outdent ]; case "indent": return [ self.indent ]; case "table": return [ self.insertTable ]; case "tablemenu": return [ self.toggleMenu, self.tableMenu, element ]; case "insert-row-before": return [ self.insertTableRow, false ]; case "insert-row-after": return [ self.insertTableRow, true ]; case "insert-col-before": return [ self.insertTableColumn, false ]; case "insert-col-after": return [ self.insertTableColumn, true ]; case "delete-row": return [ self.deleteTableRow ]; case "delete-col": return [ self.deleteTableColumn ]; case "code": return [ self.formatCodeBlock ]; case "quote": return [ self.formatQuoteBlock ]; case "hr": return [ self.insertHorizontalRule ]; case "br": return [ self.insertLineBreak ]; } return null; } function setup(container) { var elements = container.getElementsByTagName("a"); var length = elements.length; for (var i = 0; i < length; i++) { var element = elements[i]; var name = element.id.replace(/^wt-/, ""); var args = argsByType(this, name, element); if (args) { addToolbarEvent(element, this, args); buttons[name] = element; } } } var buttons = {}; setup.call(this, this.wysiwygToolbar); for (var i = 0; i < this.menus.length; i++) { setup.call(this, this.menus[i]); } return buttons; }; TracWysiwyg.prototype.toggleMenu = function(menu, element) { if (parseInt(menu.style.left, 10) < 0) { this.hideAllMenus(menu); var position = TracWysiwyg.elementPosition(element); TracWysiwyg.setStyle(menu, { left: position[0] + "px", top: (position[1] + 18) + "px" }); } else { this.hideAllMenus(); } return true; }; TracWysiwyg.prototype.hideAllMenus = function(except) { var menus = this.menus; var length = menus.length; for (var i = 0; i < length; i++) { if (menus[i] != except) { TracWysiwyg.setStyle(menus[i], { left: "-1000px", top: "-1000px" }); } } }; TracWysiwyg.prototype.execDecorate = function(name) { if (this.selectionContainsTagName("pre")) { return; } var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var position = this.getSelectionPosition(); var ancestor = {}; ancestor.start = getSelfOrAncestor(position.start, /^(?:a|tt)$/); ancestor.end = getSelfOrAncestor(position.end, /^(?:a|tt)$/); this.expandSelectionToElement(ancestor); if (name != "monospace") { this.execCommand(name); } else { this.execDecorateMonospace(); } this.selectionChanged(); }; TracWysiwyg.prototype.execDecorateMonospace = function() { var html = this.getSelectionHTML(); var removePattern = /|<\/tt>/gi; if (/^/i.test(html) && /<\/tt>$/i.test(html)) { html = html.replace(removePattern, ""); } else { var id = this.generateDomId(); html = '' + html.replace(removePattern, "") + ""; } this.insertHTML(html); var node = this.contentDocument.getElementById(id); if (node) { this.selectNode(node); } }; TracWysiwyg.prototype.execCommand = function(name, arg) { return this.contentDocument.execCommand(name, false, arg); }; TracWysiwyg.prototype.setupEditorEvents = function() { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var self = this; var d = this.contentDocument; var w = this.contentWindow; var ime = false; function listenerKeydown(event) { var method = null; var args = null; event = event || self.contentWindow.event; var keyCode = event.keyCode; switch (keyCode) { case 0x09: // TAB var range = self.getSelectionRange(); var stop = false; var element = getSelfOrAncestor(range.startContainer, /^(?:li|pre|table)$/); if (element) { switch (element.tagName.toLowerCase()) { case "li": self.execCommand(event.shiftKey ? "outdent" : "indent"); self.selectionChanged(); stop = true; break; case "pre": self.insertHTML("\t"); stop = true; break; case "table": if (getSelfOrAncestor(range.endContainer, "table") == element) { self.moveFocusInTable(!event.shiftKey); self.selectionChanged(); stop = true; } break; } } if (stop) { TracWysiwyg.stopEvent(event); } return; case 0xe5: ime = true; break; } switch ((keyCode & 0x00fffff) | (event.ctrlKey ? 0x40000000 : 0) | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0)) { case 0x40000042: // C-b method = self.execDecorate; args = [ "bold" ]; break; case 0x40000049: // C-i method = self.execDecorate; args = [ "italic" ]; break; case 0x4000004c: // C-l method = self.toggleAutolink; args = []; break; case 0x40000055: // C-u method = self.execDecorate; args = [ "underline" ]; break; case 0x40000059: // C-y method = self.execCommand; args = [ "redo" ]; break; case 0x4000005a: // C-z method = self.execCommand; args = [ "undo" ]; break; } if (method !== null) { TracWysiwyg.stopEvent(event); method.apply(self, args); self.selectionChanged(); } else if (keyCode) { var focus = self.getFocusNode(); if (!getSelfOrAncestor(focus, /^(?:p|li|h[1-6]|t[dh]|d[td]|pre|blockquote)$/)) { self.execCommand("formatblock", "

"); } } } addEvent(d, window.opera ? "keypress" : "keydown", listenerKeydown); function listenerKeypress(event) { event = event || self.contentWindow.event; var modifier = (event.ctrlKey ? 0x40000000 : 0) | (event.shiftKey ? 0x20000000 : 0) | (event.altKey ? 0x10000000 : 0); switch (event.charCode || event.keyCode) { case 0x20: // SPACE self.detectTracLink(event); return; case 0x0d: // ENTER self.detectTracLink(event); switch (modifier) { case 0: if (self.insertParagraphOnEnter) { self.insertParagraphOnEnter(event); } break; case 0x20000000: // Shift if (self.insertLineBreakOnShiftEnter) { self.insertLineBreakOnShiftEnter(event); } break; } return; } } addEvent(d, "keypress", listenerKeypress); function listenerKeyup(event) { var keyCode = event.keyCode; if (ime) { switch (keyCode) { case 0x20: // SPACE self.detectTracLink(event); break; } ime = false; } self.selectionChanged(); } addEvent(d, "keyup", listenerKeyup); function listenerMouseup(event) { self.selectionChanged(); } addEvent(d, "mouseup", listenerMouseup); function listenerClick(event) { self.hideAllMenus(); self.selectionChanged(); } addEvent(d, "click", listenerClick); }; TracWysiwyg.prototype.loadWysiwygDocument = function() { var d = this.contentDocument; var container = d.body; var tmp; while (tmp = container.lastChild) { container.removeChild(tmp); } var fragment = this.wikitextToFragment(this.textarea.value, d, this.options); container.appendChild(fragment); this.savedWysiwygHTML = container.innerHTML; }; TracWysiwyg.prototype.focusWysiwyg = function() { var self = this; var w = this.contentWindow; function lazy() { w.focus(); try { self.execCommand("useCSS", false); } catch (e) { } try { self.execCommand("styleWithCSS", false); } catch (e) { } self.selectionChanged(); } setTimeout(lazy, 10); }; TracWysiwyg.prototype.loadTracWikiText = function() { this.textarea.value = this.domToWikitext(this.contentDocument.body, this.options); this.savedWysiwygHTML = null; }; TracWysiwyg.prototype.focusTextarea = function() { this.textarea.focus(); }; TracWysiwyg.prototype.setupToggleEditorButtons = function() { var div = document.createElement("div"); var mode = TracWysiwyg.editorMode; var html = '' + '' + ' ' + ' ' + '  '; div.className = "editor-toggle"; div.innerHTML = html.replace(/@/g, ++TracWysiwyg.count); this.toggleEditorButtons = div; var buttons = div.getElementsByTagName("input"); for (var i = 0; i < buttons.length; i++) { var button = buttons[i]; switch (button.type) { case "checkbox": var listener = this.listenerToggleAutolink(button); addEvent(button, "click", listener); addEvent(button, "keypress", listener); this.autolinkButton = button; break; case "radio": addEvent(button, "click", this.listenerToggleEditor(button.value)); break; } } }; TracWysiwyg.prototype.setupSyncResizingTextArea = function() { var editrows = document.getElementById("editrows"); if (editrows) { var self = this; function timeout() { self.syncResizingTextArea(); } addEvent(editrows, "change", function() { setTimeout(timeout, 100) }); } }; TracWysiwyg.prototype.syncResizingTextArea = function() { var height = this.textarea.offsetHeight; var frame = this.frame; if (height > 0 && frame.height != height) { frame.height = height; } }; TracWysiwyg.prototype.detectTracLink = function(event) { if (!this.autolink) { return; } var range = this.getSelectionRange(); var node = range.startContainer; if (!node || !range.collapsed) { return; } var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; if (getSelfOrAncestor(node, /^(?:a|tt|pre)$/)) { return; } var offset = range.startOffset; if (node.nodeType != 3) { node = node.childNodes[offset]; while (node && node.nodeType != 3) { node = node.lastChild; } if (!node) { return; } offset = node.nodeValue.length; } else if (offset == 0) { node = node.previousSibling; if (!node || node.nodeType == 1) { return; } offset = node.nodeValue.length; } var startContainer = node; var endContainer = node; var text = [ node.nodeValue.substring(0, offset) ]; for ( ; ; ) { if (/[ \t\r\n\f\v]/.test(text[text.length - 1])) { break; } node = node.previousSibling; if (!node || node.nodeType == 1) { break; } text.push(node.nodeValue); startContainer = node; } text.reverse(); text = text.join(""); if (!text) { return; } var pattern = this.wikiDetectTracLinkPattern; pattern.lastIndex = /[^ \t\r\n\f\v]*$/.exec(text).index; var match, tmp; for (tmp = pattern.exec(text); tmp; tmp = pattern.exec(text)) { match = tmp; } if (!match) { return; } var label = match[0]; var link = this.normalizeTracLink(label); var id = this.generateDomId(); var anchor = this.createAnchor(link, label, { id: id, "data-tracwysiwyg-autolink": "true" }); var anonymous = this.contentDocument.createElement("div"); anonymous.appendChild(anchor); var html = anonymous.innerHTML; node = endContainer; var startOffset = match.index; while (startContainer != node && startOffset >= startContainer.nodeValue.length) { startOffset -= startContainer.nodeValue.length; startContainer = startContainer.nextSibling; } var endOffset = startOffset + label.length; endContainer = startContainer; while (endContainer != node && endOffset >= endContainer.nodeValue.length) { endOffset -= endContainer.nodeValue.length; endContainer = endContainer.nextSibling; } this.selectRange(startContainer, startOffset, endContainer, endOffset); offset = text.length - match.index - label.length; if (offset == 0) { switch (event.keyCode) { case 0x20: // SPACE this.insertHTML(html + "\u00a0"); TracWysiwyg.stopEvent(event); return; case 0x0d: // ENTER if (event.shiftKey) { if (window.opera || !anonymous.addEventListener) { this.insertHTML(html + "
"); if (window.opera) { anchor = this.contentDocument.getElementById(id); node = anchor.parentNode; offset = node.childNodes.length; this.selectRange(node, offset, node, offset); } TracWysiwyg.stopEvent(event); return; } } this.insertHTML(html); anchor = this.contentDocument.getElementById(id); node = event.shiftKey ? anchor.parentNode : anchor; offset = node.childNodes.length; this.selectRange(node, offset, node, offset); return; } } this.insertHTML(html); anchor = this.contentDocument.getElementById(id); node = anchor.nextSibling; if (!node) { node = anchor.parentNode; offset = node.childNodes.length; } this.selectRange(node, offset, node, offset); }; TracWysiwyg.prototype.formatParagraph = function() { if (this.selectionContainsTagName("table")) { return; } this.execCommand("formatblock", "

"); this.selectionChanged(); }; TracWysiwyg.prototype.formatHeaderBlock = function(name) { if (this.selectionContainsTagName("table")) { return; } this.execCommand("formatblock", "<" + name + ">"); this.selectionChanged(); }; TracWysiwyg.prototype.insertOrderedList = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("insertorderedlist"); this.selectionChanged(); }; TracWysiwyg.prototype.insertUnorderedList = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("insertunorderedlist"); this.selectionChanged(); }; TracWysiwyg.prototype.outdent = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("outdent"); }; TracWysiwyg.prototype.indent = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } this.execCommand("indent"); }; TracWysiwyg.prototype.insertTable = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var id = this.generateDomId(); this.insertHTML(this.tableHTML(id, 2, 3)); var element = this.contentDocument.getElementById(id) if (element) { this.selectNodeContents(element); } this.selectionChanged(); }; TracWysiwyg.prototype._tableHTML = function(row, col) { var tr = "" + ((1 << col) - 1).toString(2).replace(/1/g, "") + ""; var html = [ '', '', ((1 << row) - 1).toString(2).replace(/1/g, tr), '', '
' ]; return html.join(""); }; TracWysiwyg.prototype._getFocusForTable = function() { var hash = { node: null, cell: null, row: null, table: null }; hash.node = this.getFocusNode(); hash.cell = hash.node ? TracWysiwyg.getSelfOrAncestor(hash.node, /^t[dh]$/) : null; hash.row = hash.cell ? TracWysiwyg.getSelfOrAncestor(hash.cell, "tr") : null; hash.table = hash.row ? TracWysiwyg.getSelfOrAncestor(hash.row, "table") : null; return hash; }; TracWysiwyg.prototype.insertTableRow = function(after) { var focus = this._getFocusForTable(); if (focus.table && focus.row) { var d = this.contentDocument; var cells = focus.row.getElementsByTagName("td"); var row = focus.table.insertRow(focus.row.rowIndex + (after ? 1 : 0)); for (var j = 0; j < cells.length; j++) { this.insertTableCell(row, 0); } } }; TracWysiwyg.prototype.insertTableColumn = function(after) { var focus = this._getFocusForTable(); if (focus.table && focus.cell) { var d = this.contentDocument; var rows = focus.table.rows; var length = rows.length; var cellIndex = focus.cell.cellIndex + (after ? 1 : 0); for (var i = 0; i < length; i++) { var row = rows[i]; this.insertTableCell(row, Math.min(cellIndex, row.cells.length)); } } }; TracWysiwyg.prototype.deleteTableRow = function() { var focus = this._getFocusForTable(); if (focus.table && focus.row) { focus.table.deleteRow(focus.row.rowIndex); } }; TracWysiwyg.prototype.deleteTableColumn = function() { var focus = this._getFocusForTable(); if (focus.table && focus.cell) { var rows = focus.table.rows; var length = rows.length; var cellIndex = focus.cell.cellIndex; for (var i = 0; i < length; i++) { var row = rows[i]; if (cellIndex < row.cells.length) { row.deleteCell(cellIndex); } } } }; TracWysiwyg.prototype.moveFocusInTable = function(forward) { var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var focus = this.getFocusNode(); var element = getSelfOrAncestor(focus, /^(?:t[dhr]|table)$/); var target, table, rows, cells; switch (element.tagName.toLowerCase()) { case "td": case "th": focus = element; var row = getSelfOrAncestor(element, "tr"); cells = row.cells; if (forward) { if (focus.cellIndex + 1 < cells.length) { target = cells[focus.cellIndex + 1]; } else { table = getSelfOrAncestor(row, /^(?:tbody|table)$/); rows = table.rows; target = row.rowIndex + 1 < rows.length ? rows[row.rowIndex + 1].cells[0] : null; } } else { if (focus.cellIndex > 0) { target = cells[focus.cellIndex - 1]; } else { table = getSelfOrAncestor(row, /^(?:tbody|table)$/); rows = table.rows; if (row.rowIndex > 0) { cells = rows[row.rowIndex - 1].cells; target = cells[cells.length - 1]; } else { target = null; } } } break; case "tr": cells = element.cells; target = cells[forward ? 0 : cells.length - 1]; break; case "tbody": case "table": rows = element.rows; cells = rows[forward ? 0 : rows.length - 1].cells; target = cells[forward ? 0 : cells.length - 1]; break; } if (target) { this.selectNodeContents(target); } else if (table) { table = getSelfOrAncestor(table, "table"); var parent = table.parentNode; var elements = parent.childNodes; var length = elements.length; for (var offset = 0; offset < length; offset++) { if (table == elements[offset]) { if (forward) { offset++; } this.selectRange(parent, offset, parent, offset); } } } }; TracWysiwyg.prototype.formatCodeBlock = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var text = this.getSelectionText(); if (!text) { var node = this.getFocusNode(); while (node.nodeType == 3) { node = node.parentNode; } text = TracWysiwyg.getTextContent(node); this.selectNode(node); } var fragment = this.getSelectionFragment(); text = this.domToWikitext(fragment, { formatCodeBlock: true }).replace(/\s+$/, ""); var d = this.contentDocument; var anonymous = d.createElement("div"); var pre = d.createElement("pre"); pre.className = "wiki"; anonymous.appendChild(pre); if (text) { pre.appendChild(d.createTextNode(text)); } this.insertHTML(anonymous.innerHTML); this.selectionChanged(); }; TracWysiwyg.prototype.formatQuoteBlock = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } var d = this.contentDocument; var anonymous = d.createElement("div"); var container = d.createElement("blockquote"); container.className = "citation"; var fragment = this.getSelectionFragment(); var childNodes = fragment.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { var child = childNodes[i]; var text = null; switch (child.nodeType) { case 1: if (child.tagName.toLowerCase() != "blockquote" || child.className != "citation") { text = TracWysiwyg.getTextContent(child); } break; case 3: text = child.nodeValue; break; default: continue; } if (text !== null) { if (!text) { continue; } var tmp = d.createElement("p"); tmp.appendChild(d.createTextNode(text)); child = tmp; } container.insertBefore(child, container.firstChild); } if (container.childNodes.length == 0) { container.appendChild(d.createElement("p")); } anonymous.appendChild(container); this.insertHTML(anonymous.innerHTML); this.selectionChanged(); }; TracWysiwyg.prototype.insertHorizontalRule = function() { if (this.selectionContainsTagName("table") || this.selectionContainsTagName("pre")) { return; } if (!this.execCommand("inserthorizontalrule")) { this.insertHTML("


"); } this.selectionChanged(); }; TracWysiwyg.prototype.createLink = function() { if (this.selectionContainsTagName("pre")) { return; } var focus = this.getFocusNode(); var anchor = TracWysiwyg.getSelfOrAncestor(focus, "a"); var expand = anchor || TracWysiwyg.getSelfOrAncestor(focus, "tt"); var currLink; if (anchor) { var attrs; var autolink = anchor.getAttribute("data-tracwysiwyg-autolink"); if (autolink === null) { attrs = TracWysiwyg.unserializeFromHref(anchor.href); autolink = attrs["data-tracwysiwyg-autolink"]; } if (autolink == "true") { var pattern = this.wikiDetectTracLinkPattern; pattern.lastIndex = 0; var label = TracWysiwyg.getTextContent(anchor); var match = pattern.exec(label); if (match && match.index == 0 && match[0].length == label.length) { currLink = this.normalizeTracLink(label); } } if (!currLink) { currLink = anchor.getAttribute("data-tracwysiwyg-link") || attrs["data-tracwysiwyg-link"] || anchor.href; } } else { currLink = ""; } if (expand) { this.selectNodeContents(expand); } var text = this.getSelectionText() || ""; var newLink = (prompt(text ? "Enter TracLink:" : "Insert TracLink:", currLink) || "").replace(/^\s+|\s+$/g, ""); if (newLink && newLink != currLink) { text = text || newLink; newLink = this.normalizeTracLink(newLink); var id = this.generateDomId(); var d = this.contentDocument; var anonymous = d.createElement("div"); anchor = this.createAnchor(newLink, text, { id: id }); anonymous.appendChild(anchor); this.insertHTML(anonymous.innerHTML); anchor = d.getElementById(id); if (anchor) { this.selectNodeContents(anchor); } } this.selectionChanged(); }; TracWysiwyg.prototype.createAnchor = function(link, label, attrs) { var d = this.contentDocument; var anchor = d.createElement("a"); var href = {}; for (var name in attrs) { var value = attrs[name]; href[name] = value; anchor.setAttribute(name, value); } href["data-tracwysiwyg-link"] = link; anchor.href = TracWysiwyg.serializeToHref(href); anchor.title = link; anchor.setAttribute("data-tracwysiwyg-link", link); anchor.setAttribute("onclick", "return false;"); anchor.appendChild(d.createTextNode(label)); return anchor; }; TracWysiwyg.prototype.collectChildNodes = function(dest, source) { var childNodes = source.childNodes; for (var i = childNodes.length - 1; i >= 0; i--) { dest.insertBefore(childNodes[i], dest.firstChild); } }; TracWysiwyg.prototype.generateDomId = function() { var d = this.contentDocument; for ( ; ; ) { var id = "tmp-" + (new Date().valueOf().toString(36)); if (!d.getElementById(id)) { return id; } } }; TracWysiwyg.prototype.selectionChanged = function() { var status = { strong: false, em: false, underline: false, strike: false, sub: false, sup: false, monospace: false, paragraph: false, heading1: false, heading2: false, heading3: false, heading4: false, heading5: false, heading6: false, link: false, ol: false, ul: false, outdent: false, indent: false, table: false, code: false, quote: false, hr: false, br: false }; var tagNameToKey = { b: "strong", i: "em", u: "underline", del: "strike", tt: "monospace", p: "paragraph", h1: "heading1", h2: "heading2", h3: "heading3", h4: "heading4", h5: "heading5", h6: "heading6", a: "link", pre: "code", blockquote: "quote" }; var position = this.getSelectionPosition(); var node; if (position.start) { node = position.start == position.end ? position.start.firstChild : position.start.nextSibling; node = node || position.start; } else { node = null; } while (node) { if (node.nodeType == 1) { var name = node.tagName.toLowerCase(); if (name in tagNameToKey) { name = tagNameToKey[name]; } status[name] = true; } node = node.parentNode; } var toolbarButtons = this.toolbarButtons; for (var name in status) { var button = toolbarButtons[name]; if (button) { var parent = button.parentNode; parent.className = (parent.className || "").replace(/ *\bselected\b|$/, status[name] ? " selected" : ""); } } var styles = [ "quote", "paragraph", "code", "heading1", "heading2", "heading3", "heading4", "heading5", "heading6" ]; var styleButton = toolbarButtons["style"]; var styleButtonClass = "wysiwyg-menu-style"; for (var i = 0; i < styles.length; i++) { var name = styles[i]; if (status[name]) { styleButtonClass = "wysiwyg-menu-" + name; break; } } styleButton.parentNode.className = styleButtonClass; }; (function() { var _linkScheme = "[\\w.+-]+"; // cf. WikiSystem.XML_NAME, http://www.w3.org/TR/REC-xml/#id var _xmlName = "[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD](?:[-:_.A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]*[-_A-Za-z0-9\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD])?" var _quotedString = "'[^']+'|" + '"[^"]+"'; var _changesetId = "(?:\\d+|[a-fA-F\\d]{6,})"; var _ticketLink = "#\\d+"; var _reportLink = "\\{\\d+\\}"; var _changesetPath = "/[^\\]]*"; var _changesetLinkBracket = "\\[" + _changesetId + "(?:" + _changesetPath + ")?\\]"; var _changesetLinkRev = "r" + _changesetId + "\\b(?!:" + _changesetId + ")"; var _logLinkBracket = "\\[" + _changesetId + "[-:]" + _changesetId + "(?:" + _changesetPath + ")?\\]"; var _logLinkRev = "r" + _changesetId + "[-:]" + _changesetId + "\\b"; var _tracLink = _linkScheme + ":(?:" + _quotedString + "|[a-zA-Z0-9/?!#@](?:(?:\\|(?=[^| \\t\\r\\f\\v])|[^|<> \\t\\r\\f\\v])*[a-zA-Z0-9/=])?)"; var _wikiPageName = "[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+(?:#[\\w:][-\\w\\d.:]*)?" + "(?=:(?:$|[ \\t\\r\\f\\v])|[^:a-zA-Z]|[ \\t\\r\\f\\v]|$)"; var wikiInlineRules = []; wikiInlineRules.push("!?'''''"); // 1. bolditalic wikiInlineRules.push("!?'''"); // 2. bold wikiInlineRules.push("!?''"); // 3. italic wikiInlineRules.push("!?__"); // 4. underline wikiInlineRules.push("!?~~"); // 5. strike wikiInlineRules.push("!?,,"); // 6. subscript wikiInlineRules.push("!?\\^"); // 7. superscript wikiInlineRules.push("!?\\{\\{\\{.*?\\}\\}\\}"); // 8. code block wikiInlineRules.push("!?`.*?`"); // 9. inline wikiInlineRules.push("[!&]?" + _ticketLink); // 10. ticket wikiInlineRules.push("!?" + _reportLink); // 11. report // 12. changeset wikiInlineRules.push("!?" + _changesetLinkBracket + "|(?:\\b|!)" + _changesetLinkRev); // 13. log wikiInlineRules.push("!?" + _logLinkBracket + "|(?:\\b|!)" + _logLinkRev); wikiInlineRules.push("!?" + _tracLink); // 14. wiki:TracLinks wikiInlineRules.push("!?\\[(?:" // 15. [wiki:TracLinks label] or [/relative label] + "[/.#][^ \\t\\r\\f\\v[\\]]*|" + _linkScheme + ":(?:" + _quotedString + "|[^\\] \\t\\r\\f\\v]*)|" + _wikiPageName + "[ \\t\\r\\f\\v]+(?:" + _quotedString + "|[^\\]]+)" + ")(?:[ \\t\\r\\f\\v]+(?:" + _quotedString + "|[^\\]]+))?\\]"); // 16. [[macro]] wikiInlineRules.push("!?\\[\\[[\\w/+-]+(?:\\]\\]|\\(.*?\\)\\]\\])"); // 17. WikiPageName wikiInlineRules.push("(?:\\b|!)" + _wikiPageName); // 18. ["internal free link"] wikiInlineRules.push("!?\\[(?:" + _quotedString + ")\\]"); var wikiRules = []; wikiRules.push.apply(wikiRules, wikiInlineRules); wikiRules.push("^(?: *>)+[ \\t\\r\\f\\v]*"); // -1. citation // -2. header wikiRules.push("^[ \\t\\r\\f\\v]*={1,6}[ \\t\\r\\f\\v]+.*?[ \\t\\r\\f\\v]+={1,6}(?:[ \\t\\r\\f\\v]+#" + _xmlName + ")?[ \\t\\r\\f\\v]*$"); // -3. list wikiRules.push("^ +(?:[-*]|[0-9]+\\.|[a-zA-Z]\\.|[ivxIVX]{1,5}\\.) "); // -4. definition wikiRules.push("^[ \\t\\r\\f\\v]+(?:`[^`]*`|\\{\\{\\{.*?\\}\\}\\}|[^`{:]|:[^:])+::(?:[ \\t\\r\\f\\v]+|$)"); wikiRules.push("^[ \\t\\r\\f\\v]+(?=[^ \\t\\r\\f\\v])"); // -5. leading space wikiRules.push("\\|\\|[ \\t\\r\\f\\v]*$"); // -6. closing table row wikiRules.push("\\|\\|"); // -7. cell var wikiSyntaxRules = []; wikiSyntaxRules.push(_ticketLink); wikiSyntaxRules.push(_reportLink); wikiSyntaxRules.push(_changesetLinkBracket); wikiSyntaxRules.push(_changesetLinkRev); wikiSyntaxRules.push(_logLinkBracket); wikiSyntaxRules.push(_logLinkRev); var wikiDetectTracLinkRules = []; wikiDetectTracLinkRules.push(_ticketLink); wikiDetectTracLinkRules.push(_reportLink); wikiDetectTracLinkRules.push(_changesetLinkBracket); wikiDetectTracLinkRules.push("\\b" + _changesetLinkRev); wikiDetectTracLinkRules.push(_logLinkBracket); wikiDetectTracLinkRules.push("\\b" + _logLinkRev); wikiDetectTracLinkRules.push(_tracLink); wikiDetectTracLinkRules.push("\\b" + _wikiPageName); var wikiInlineRulesPattern = new RegExp("(?:" + wikiInlineRules.join("|") + ")", "g"); var wikiRulesPattern = new RegExp("(?:(" + wikiRules.join(")|(") + "))", "g"); var wikiSyntaxPattern = new RegExp("^(?:" + wikiSyntaxRules.join("|") + ")$"); var wikiSyntaxLogPattern = new RegExp("^[\\[r]" + _changesetId + "[-:]"); var wikiDetectTracLinkPattern = new RegExp("(?:" + wikiDetectTracLinkRules.join("|") + ")", "g"); TracWysiwyg.prototype._linkScheme = _linkScheme; TracWysiwyg.prototype._quotedString = _quotedString; TracWysiwyg.prototype._changesetId = _changesetId; TracWysiwyg.prototype._tracLink = _tracLink; TracWysiwyg.prototype._wikiPageName = _wikiPageName; TracWysiwyg.prototype.wikiInlineRules = wikiInlineRules; TracWysiwyg.prototype.wikiRules = wikiRules; TracWysiwyg.prototype.xmlNamePattern = new RegExp("^" + _xmlName + "$"); TracWysiwyg.prototype.wikiInlineRulesPattern = wikiInlineRulesPattern; TracWysiwyg.prototype.wikiRulesPattern = wikiRulesPattern; TracWysiwyg.prototype.wikiSyntaxPattern = wikiSyntaxPattern; TracWysiwyg.prototype.wikiSyntaxLogPattern = wikiSyntaxLogPattern; TracWysiwyg.prototype.wikiDetectTracLinkPattern = wikiDetectTracLinkPattern; })(); TracWysiwyg.prototype.normalizeTracLink = function(link) { link = this.convertWikiSyntax(link); if (/^[\/.#]/.test(link)) { link = encode(link); } if (!/^[\w.+-]+:/.test(link)) { link = "wiki:" + link; } if (/^wiki:[^\"\']/.test(link) && /\s/.test(link)) { if (link.indexOf('"') === -1) { link = 'wiki:"' + link + '"'; } else if (link.indexOf("'") === -1) { link = "wiki:'" + link + "'"; } else { link = 'wiki:"' + link.replace(/"/g, "%22") + '"'; } } return link; }; TracWysiwyg.prototype.convertWikiSyntax = function(link) { var match = this.wikiSyntaxPattern.exec(link); if (match) { switch (match[0].charCodeAt(0)) { case 0x7b: // "{" link = "report:" + link.slice(1, -1); break; case 0x5b: // "[" link = (this.wikiSyntaxLogPattern.test(link) ? "log:@" : "changeset:") + link.slice(1, -1); break; case 0x23: // # link = "ticket:" + link.substring(1); break; case 0x72: // r link = (this.wikiSyntaxLogPattern.test(link) ? "log:@" : "changeset:") + link.substring(1); break; } } return link; }; TracWysiwyg.prototype.isInlineNode = function(node) { if (node) { switch (node.nodeType) { case 1: return (node.tagName.toLowerCase() in this.wikiInlineTags); case 3: return true; } } return false; }; (function() { var blocks = { p: true, blockquote: true, div: true, li: true, ul: true, ol: true, dl: true, dt: true, dd: true, h1: true, h2: true, h3: true, h4: true, h5: true, h6: true, table: true, thead: true, tbody: true, tr: true, td: true, th: true }; function generator(prop, blocks) { return function (node) { if (!node) { return false; } for ( ; ; ) { if (node[prop]) { return false; } node = node.parentNode; if (!node) { return true; } if (node.nodeType == 1 && node.tagName.toLowerCase() in blocks) { return true; } } return false; }; } TracWysiwyg.prototype.isLastChildInBlockNode = generator("nextSibling", blocks); TracWysiwyg.prototype.isFirstChildInBlockNode = generator("previousSibling", blocks); })(); TracWysiwyg.prototype.wikitextToFragment = function(wikitext, contentDocument, options) { options = options || {}; var escapeNewlines = !!options.escapeNewlines; var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var _linkScheme = this._linkScheme; var _quotedString = this._quotedString; var wikiInlineRules = this.wikiInlineRules; var wikiRulesPattern = new RegExp(this.wikiRulesPattern.source, "g"); var self = this; var fragment = contentDocument.createDocumentFragment(); var holder = fragment; var lines = wikitext.split("\n"); var codeText = null; var currentHeader = null; var quoteDepth = []; var listDepth = []; var decorationStatus; var decorationStack; var inCodeBlock, inParagraph, inDefList, inTable, inTableRow; inCodeBlock = inParagraph = inDefList = inTable = inTableRow = false; function handleCodeBlock(line) { if (/^ *\{\{\{ *$/.test(line)) { inCodeBlock++; if (inCodeBlock == 1) { closeParagraph(); codeText = []; } else { codeText.push(line); } } else if (/^ *\}\}\} *$/.test(line)) { inCodeBlock--; if (inCodeBlock == 0) { var pre = contentDocument.createElement("pre"); pre.className = "wiki"; pre.appendChild(contentDocument.createTextNode(codeText.join( pre.addEventListener && !window.opera ? "\n" : "\n\r"))); holder.appendChild(pre); codeText = []; } else { codeText.push(line); } } else { codeText.push(line); } } function handleCitation(value) { var quote = /^(?: *>)+/.exec(value)[0]; var depth = quote.replace(/ +/g, "").length; if (depth > quoteDepth.length) { closeToFragment("blockquote"); while (depth > quoteDepth.length) { openQuote((new RegExp("^(?: *>){" + (quoteDepth.length + 1) + "}")).exec(quote)[0].length, true); } } else if (depth == quoteDepth.length) { // nothing to do } else { closeParagraph(); while (depth < quoteDepth.length) { closeQuote(); } } } function openQuote(length, citation) { var target = holder; if (target != fragment) { target = getSelfOrAncestor(target, "blockquote"); } var element = contentDocument.createElement("blockquote"); if (citation) { element.className = "citation"; } (target || fragment).appendChild(element); holder = element; quoteDepth.push(length); } function closeQuote() { var target = getSelfOrAncestor(holder, "blockquote"); holder = target.parentNode; quoteDepth.pop(); } function handleHeader(line) { var match = /^\s*(=+)[ \t\r\f\v]+.*?[ \t\r\f\v]+(=+)(?:[ \t\r\f\v]+#([^ \t\r\f\v]+)[ \t\r\f\v]*)?$/.exec(line); if (!match || match[1].length != match[2].length) { return null; } closeToFragment(); var tag = "h" + match[1].length; var element = contentDocument.createElement(tag); if (match[3]) { element.id = match[3]; } fragment.appendChild(element); holder = element; return tag; } function closeHeader() { if (currentHeader) { var target = getSelfOrAncestor(holder, currentHeader); holder = target.parentNode; currentHeader = null; } } function handleInline(name) { if (name == "bolditalic") { if (decorationStatus.italic) { handleInline("italic"); handleInline("bold"); } else { handleInline("bold"); handleInline("italic"); } return; } var d = contentDocument; if (decorationStatus[name]) { var tagNames = []; for (var index = decorationStack.length - 1; index >= 0; index--) { var tagName = holder.tagName; holder = holder.parentNode; if (decorationStack[index] == name) { break; } tagNames.push(tagName); } decorationStack.splice(index, 1); decorationStatus[name] = false; while (tagNames.length > 0) { var element = d.createElement(tagNames.pop()); holder.appendChild(element); holder = element; } return; } var tagName; switch (name) { case "bold": tagName = "b"; break; case "italic": tagName = "i"; break; case "underline": tagName = "u"; break; case "strike": tagName = "del"; break; case "subscript": tagName = "sub"; break; case "superscript": tagName = "sup"; break; } if (holder == fragment) { openParagraph(); } element = d.createElement(tagName); holder.appendChild(element); holder = element; decorationStatus[name] = true; decorationStack.push(name); } function handleInlineCode(value, length) { var d = contentDocument; var element = d.createElement("tt"); value = value.slice(length, -length); if (value.length > 0) { element.appendChild(d.createTextNode(value)); holder.appendChild(element); } } function createAnchor(link, label) { var anchor = self.createAnchor(link, label); holder.appendChild(anchor); } function handleTracLinks(value) { var match = handleTracLinks.pattern.exec(value); if (match) { var link = match[1]; if (!/^(?:[\w.+-]+:|[\/.#].*)/.test(link)) { link = "wiki:" + link; } var text = (match[2] || match[1].replace(/^[\w.+-]+:/, "")).replace(/^(["'])(.*)\1$/g, "$2"); createAnchor(link, text); } else { holder.appendChild(contentDocument.createTextNode(value)); } } handleTracLinks.pattern = new RegExp("\\[" + "((?:" + _linkScheme + ":)?(?:" + _quotedString + "|[^\\]\\s]+))" + "(?:\\s+(.*))?\\]"); function handleTracWikiLink(value) { createAnchor(value, value); } function handleWikiPageName(name, label) { createAnchor("wiki:" + name, label || name); } function handleTracOtherLinks(value) { createAnchor(self.convertWikiSyntax(value), value); } function handleTracTicketLink(value) { if (!/^&/.test(value)) { handleTracOtherLinks(value); return true; } return false; } function handleList(value) { var match = /^( +)(?:([-*])|((?:([0-9]+)|([a-z])|([A-Z])|[ivxIVX]{1,5})))/.exec(value); var tag, className, depth, start; if (!match) { holder.appendChild(contentDocument.createTextNode(value)); return; } depth = match[1].length; if (match[2]) { tag = "ul"; } else if (match[3]) { tag = "ol"; switch (match[3]) { case "0": className = "arabiczero"; break; case "1": break; case "i": className = "lowerroman"; break; case "I": className = "upperroman"; break; default: if (match[4]) { start = parseInt(match[4], 10); } else if (match[5]) { className = "loweralpha"; } else if (match[6]) { className = "upperalpha"; } break; } } var last = listDepth.length - 1; if (depth > (last >= 0 ? listDepth[last] : 0)) { closeToFragment("li"); openList(tag, className, start, depth); } else { var container, list; if (listDepth.length > 1 && depth < listDepth[last]) { do { if (depth >= listDepth[last]) { break; } closeList(); last = listDepth.length - 1; } while (listDepth.length > 1); container = holder; } else { list = getSelfOrAncestor(holder, "li"); self.appendBogusLineBreak(list); container = list.parentNode; } if (tag != container.tagName.toLowerCase()) { holder = container.parentNode; listDepth.pop(); openList(tag, className, start, depth); } else { var tmp = contentDocument.createElement("li"); container.appendChild(tmp); holder = tmp; listDepth[last] = depth; } } } function openList(tag, className, start, depth) { var d = contentDocument; var h = holder; var container = d.createElement(tag); if (className) { container.className = className; } if (start) { container.setAttribute("start", start); } var list = d.createElement("li"); container.appendChild(list); var target; if (h == fragment) { target = fragment; } else { target = getSelfOrAncestor(h, "li"); target = target ? target.parentNode : h; } target.appendChild(container); holder = list; listDepth.push(depth); } function closeList() { var h = holder; var target = getSelfOrAncestor(h, "li"); if (target) { self.appendBogusLineBreak(target); holder = target.parentNode.parentNode; } else { holder = h.parentNode; } listDepth.pop(); } function handleDefinition(value) { var d = contentDocument; var h = holder; var dl = null; if (inDefList) { dl = getSelfOrAncestor(h, "dl"); } else { closeParagraph(); dl = d.createElement("dl"); fragment.appendChild(dl); inDefList = true; } var match = /^ +(.*?)\s*::/.exec(value); var dt = d.createElement("dt"); var oneliner = self.wikitextToOnelinerFragment(match[1], d, self.options); dt.appendChild(oneliner); dl.appendChild(dt); var dd = d.createElement("dd"); dl.appendChild(dd); holder = dd; } function closeDefList() { var element = getSelfOrAncestor(holder, "dl"); if (element) { holder = element.parentNode; } inDefList = false; } function handleIndent(value) { var depth = value.length; var last = quoteDepth.length - 1; if (depth > (last >= 0 ? quoteDepth[last] : 0)) { closeParagraph(); closeTable(); openQuote(depth, false); } else { while (quoteDepth.length > 0) { if (depth >= quoteDepth[last]) { break; } closeToFragment("blockquote"); closeQuote(); last = quoteDepth.length - 1; } quoteDepth[last] = depth; } } function openParagraph() { if (!inParagraph) { var element = contentDocument.createElement("p"); holder.appendChild(element); holder = element; inParagraph = true; } } function closeParagraph() { if (inParagraph) { var target = holder; if (target != fragment) { target = getSelfOrAncestor(target, "p"); self.appendBogusLineBreak(target); } holder = target.parentNode; inParagraph = false; } } function handleTableCell(action) { var d = contentDocument; var h, table, tbody; if (!inTable) { closeToFragment("blockquote"); h = holder; table = d.createElement("table"); table.className = "wiki"; tbody = d.createElement("tbody"); table.appendChild(tbody); h.appendChild(table); inTable = true; inTableRow = false; } else { h = holder; tbody = getSelfOrAncestor(h, "tbody"); } if (inTableRow) { var cell = getSelfOrAncestor(h, "td"); if (cell) { self.appendBogusLineBreak(cell); } } var row; switch (action) { case 1: row = d.createElement("tr"); tbody.appendChild(row); inTableRow = true; break; case 0: row = getSelfOrAncestor(h, "tr"); break; case -1: if (inTableRow) { var target = getSelfOrAncestor(h, "tr"); holder = target.parentNode; inTableRow = false; } return; } var cell = d.createElement("td"); row.appendChild(cell); holder = cell; decorationStatus = {}; } function closeTable() { if (inTable) { var target = getSelfOrAncestor(holder, "table"); holder = target.parentNode; inTable = inTableRow = false; } } function closeToFragment(stopTag) { var element = holder; var _fragment = fragment; stopTag = stopTag ? stopTag.toLowerCase() : null; while (element != _fragment) { var tag = element.tagName.toLowerCase(); if (tag == stopTag) { holder = element; return; } var method; switch (tag) { case "p": method = closeParagraph; break; case "li": case "ul": case "ol": method = closeList; break; case "dd": method = closeDefList; break; case "blockquote": method = closeQuote; break; case "td": case "tr": case "tbody": case "table": method = closeTable; break; default: break; } if (method) { method(); element = holder; } else { element = element.parentNode; } } holder = _fragment; } function getMatchNumber(match) { var length = match.length; for (var i = 1; i < length; i++) { if (match[i]) { var inlines = wikiInlineRules.length return i <= inlines ? i : inlines - i; } } return null; } for (var indexLines = 0; indexLines < lines.length; indexLines++) { var line = lines[indexLines].replace(/\r$/, ""); if (inCodeBlock || /^ *\{\{\{ *$/.test(line)) { handleCodeBlock(line); continue; } if (/^----/.test(line)) { closeToFragment(); fragment.appendChild(contentDocument.createElement("hr")); continue; } if (line.length == 0) { closeToFragment(); continue; } line = line.replace(/\t/g, " "); line = line.replace(/\u00a0/g, " "); wikiRulesPattern.lastIndex = 0; var prevIndex = wikiRulesPattern.lastIndex; decorationStatus = {}; decorationStack = []; for ( ; ; ) { var match = wikiRulesPattern.exec(line); var matchNumber = null; var text = null; if (match) { matchNumber = getMatchNumber(match); if (prevIndex < match.index) { text = line.substring(prevIndex, match.index); } } else { text = line.substring(prevIndex); } if ((prevIndex == 0 && text || match && match.index == 0 && matchNumber > 0) && (!inParagraph || quoteDepth.length > 0) && (!inDefList || !/^ /.test(line))) { closeToFragment(); } if (text || match && matchNumber > 0) { if (inParagraph && (prevIndex == 0 || quoteDepth.length > 0)) { if (escapeNewlines) { if (quoteDepth.length == 0) { holder.appendChild(contentDocument.createElement("br")); } } else { text = text ? (" " + text) : " "; } } if (!inTable && quoteDepth.length > 0 || holder == fragment) { if (!inParagraph) { openParagraph(); } } if (text) { holder.appendChild(contentDocument.createTextNode(text)); } } if (!match) { break; } prevIndex = wikiRulesPattern.lastIndex; var matchText = match[0]; if (!/^!/.test(matchText)) { // start '!' switch (matchNumber) { case 1: // bolditalic handleInline("bolditalic"); continue; case 2: // bold handleInline("bold"); continue; case 3: // italic handleInline("italic"); continue; case 4: // underline handleInline("underline"); continue; case 5: // strike handleInline("strike"); continue; case 6: // subscript handleInline("subscript"); continue; case 7: // superscript handleInline("superscript"); continue; case 8: // code block handleInlineCode(matchText, 3); continue; case 9: // inline handleInlineCode(matchText, 1); continue; case 10: // ticket if (handleTracTicketLink(matchText)) { continue; } break; case 11: // report case 12: // changeset case 13: // log handleTracOtherLinks(matchText); continue; case 14: // wiki:TracLinks handleTracWikiLink(matchText); continue; case 15: // [wiki:TracLinks label] handleTracLinks(matchText); continue; case 16: // [[macro]] break; case 17: // WikiPageName handleWikiPageName(matchText); continue; case 18: // ["internal free link"] handleWikiPageName(matchText.slice(1, -1), matchText.slice(2, -2)); continue; case -1: // citation if (escapeNewlines && inParagraph) { holder.appendChild(contentDocument.createElement("br")); } handleCitation(matchText); if (escapeNewlines) { openParagraph(); } continue; case -2: // header currentHeader = handleHeader(matchText); if (currentHeader) { line = line.replace(/[ \t\r\f\v]+=+(?:[ \t\r\f\v]+#[^ \t\r\f\v]+)?[ \t\r\f\v]*$/, ""); wikiRulesPattern.lastIndex = prevIndex = line.match(/^\s*=+[ \t\r\f\v]*/)[0].length; continue; } break; case -3: // list handleList(matchText) continue; case -4: // definition handleDefinition(matchText); continue; case -5: // leading space if (listDepth.length == 0 && !inDefList) { handleIndent(matchText); continue; } if (!this.isInlineNode(holder.lastChild)) { continue; } matchText = matchText.replace(/^\s+/, " "); break; case -6: // closing table row if (inTable) { handleTableCell(-1); continue; } break; case -7: // cell if (quoteDepth.length > 0 && match.index == 0) { closeToFragment(); } for ( ; ; ) { // lookahead next double pipes var m = wikiRulesPattern.exec(line); switch (m ? getMatchNumber(m) : 0) { case 0: case -6: case -7: var end = m ? m.index : line.length; if (prevIndex < end) { line = line.substring(0, prevIndex) + line.substring(prevIndex, end).replace(/^[ \t\r\n\f\v]+|[ \t\r\n\f\v]+$/g, "") + line.substring(end); } break; default: continue; } break; } wikiRulesPattern.lastIndex = prevIndex; handleTableCell(inTableRow ? 0 : 1); continue; } } if (matchText) { if (listDepth.length == 0 && !currentHeader && !inDefList && !inTable) { openParagraph(); } var tmp; if (matchNumber == 16) { tmp = /^!?\[\[br\]\]$/i.test(matchText) ? (matchText.charCodeAt(0) == 0x21 ? contentDocument.createTextNode(matchText.substring(1)) : contentDocument.createElement("br")) : contentDocument.createTextNode(matchText); } else { tmp = contentDocument.createTextNode(/^!/.test(matchText) ? matchText.substring(1) : matchText); } holder.appendChild(tmp); } } if (currentHeader) { closeHeader(); } if (inTable) { handleTableCell(-1); } } closeToFragment(); return fragment; }; TracWysiwyg.prototype.wikitextToOnelinerFragment = function(wikitext, contentDocument, options) { var source = this.wikitextToFragment(wikitext, contentDocument, options); var fragment = contentDocument.createDocumentFragment(); this.collectChildNodes(fragment, source.firstChild); return fragment; }; TracWysiwyg.prototype.wikiOpenTokens = { "h1": "= ", "h2": "== ", "h3": "=== ", "h4": "==== ", "h5": "===== ", "h6": "====== ", "b": "'''", "strong": "'''", "i": "''", "em": "''", "u": "__", "del": "~~", "strike": "~~", "sub": ",,", "sup": "^", "hr": "----\n", "dl": true, "dt": " ", "dd": " ", "table": true, "tbody": true }; TracWysiwyg.prototype.wikiCloseTokens = { "#text": true, "a": true, "tt": true, "h1": " =", "h2": " ==", "h3": " ===", "h4": " ====", "h5": " =====", "h6": " ======", "b": "'''", "strong": "'''", "i": "''", "em": "''", "u": "__", "del": "~~", "strike": "~~", "sub": ",,", "sup": "^", "br": true, "hr": true, "dl": "\n", "dt": "::", "dd": "\n", "tbody": true, "tr": "||\n", "td": true, "th": true }; TracWysiwyg.prototype.wikiBlockTags = { "h1": true, "h2": true, "h3": true, "h4": true, "h5": true, "h6": true, "table": true, "dl": true, "hr": true }; TracWysiwyg.prototype.wikiInlineTags = { "a": true, "tt": true, "b": true, "strong": true, "i": true, "em": true, "u": true, "del": true, "strike": true, "sub": true, "sup": true, "br": true, "span": true }; TracWysiwyg.prototype.domToWikitext = function(root, options) { options = options || {}; var formatCodeBlock = !!options.formatCodeBlock; var escapeNewlines = !!options.escapeNewlines; var self = this; var getTextContent = TracWysiwyg.getTextContent; var getSelfOrAncestor = TracWysiwyg.getSelfOrAncestor; var wikiOpenTokens = this.wikiOpenTokens; var wikiCloseTokens = this.wikiCloseTokens; var wikiInlineTags = this.wikiInlineTags; var wikiBlockTags = this.wikiBlockTags; var xmlNamePattern = this.xmlNamePattern; var wikiInlineRulesPattern = this.wikiInlineRulesPattern; var wikiSyntaxPattern = this.wikiSyntaxPattern; var tracLinkPattern = new RegExp("^" + this._tracLink + "$"); var wikiPageNamePattern = new RegExp("^" + this._wikiPageName + "$"); var decorationTokenPattern = /^(?:'''|''|__|\^|,,)$/; var texts = []; var stack = []; var last = root; var listDepth = 0; var quoteDepth = 0; var quoteCitation = false; var inCodeBlock = false; var skipNode = null; function escapeText(s) { var match = /^!?\[\[(.+)\]\]$/.exec(s); if (match) { return match[1].toLowerCase() != "br" ? s : "!" + s; } if (/^&#\d+/.test(s)) { return s; } return "!" + s; } function isTailEscape() { var t = texts; var length = t.length; return length > 0 ? /!$/.test(t[length - 1]) : false; } function tokenFromSpan(node) { if (node.className == "underline") { return wikiOpenTokens["u"]; } var style = node.style; if (style.fontWeight == "bold") { return wikiOpenTokens["b"]; } if (style.fontStyle == "italic") { return wikiOpenTokens["i"]; } switch (style.textDecoration) { case "underline": return wikiOpenTokens["u"]; case "line-through": return wikiOpenTokens["del"]; } switch (style.verticalAlign) { case "sub": return wikiOpenTokens["sub"]; case "sup": return wikiOpenTokens["sup"]; } return undefined; } function nodeDecorations(node) { var _wikiOpenTokens = wikiOpenTokens; var _decorationTokenPattern = decorationTokenPattern; var hash = {}; for ( ; ; ) { var childNodes = node.childNodes; if (!childNodes || childNodes.length != 1) { break; } var child = childNodes[0]; if (child.nodeType != 1) { break; } var token = _wikiOpenTokens[child.tagName.toLowerCase()]; if (_decorationTokenPattern.test(token)) { hash[token] = true; } node = child; } return hash; } function pushTextWithDecorations(text, node, traclink) { var _texts = texts; var _decorationTokenPattern = decorationTokenPattern; var decorationsHash = nodeDecorations(node); var decorations = []; var cancelDecorations = []; while (_texts.length > 0) { var token = _texts[_texts.length - 1]; if (_decorationTokenPattern.test(token)) { if (decorationsHash[token]) { delete decorationsHash[token]; cancelDecorations.push(_texts.pop()); continue; } if ((token == "'''" || token == "''") && _texts.length > 1) { var moreToken = _texts[_texts.length - 2]; if (_decorationTokenPattern.test(moreToken) && token + moreToken == "'''''" && decorationsHash[moreToken]) { delete decorationsHash[moreToken]; cancelDecorations.push(moreToken); _texts[_texts.length - 2] = _texts[_texts.length - 1]; _texts.pop(); } } } break; } for (var token in decorationsHash) { decorations.push(token); } decorations.sort(); if (decorations.length > 0) { _texts.push.apply(_texts, decorations); } if (traclink) { if (_texts.length > 0 && /[\w.+-]$/.test(_texts[_texts.length - 1])) { _texts.push(traclink); } else { text = new String(text); text["tracwysiwyg-traclink"] = traclink; _texts.push(text); } } else { _texts.push(text); } if (decorations.length > 0) { decorations.reverse(); _texts.push.apply(_texts, decorations); } if (cancelDecorations.length > 0) { cancelDecorations.reverse(); _texts.push.apply(_texts, cancelDecorations); } } function pushToken(token) { var _texts = texts; var _decorationTokenPattern = decorationTokenPattern; var length = _texts.length; if (length == 0 || !_decorationTokenPattern.test(token)) { _texts.push(token); return; } var last = _texts[length - 1]; if (!_decorationTokenPattern.test(last)) { _texts.push(token); return; } if (last == token) { _texts.pop(); return; } if (length < 2 || last + token != "'''''") { _texts.push(token); return; } if (_texts[length - 2] == token) { _texts[length - 2] = _texts[length - 1]; _texts.pop(); } else { _texts.push(token); } } function tracLinkText(link, label) { if (!/\]/.test(label) && !/^[\"\']/.test(label)) { return "[" + link + " " + label + "]"; } if (!/\"/.test(label)) { return "[" + link + ' "' + label + '"]'; } if (!/\'/.test(label)) { return "[" + link + " '" + label + "']"; } return "[" + link + ' "' + label.replace(/"+/g, "") + '"]'; } function pushAnchor(node) { var link = node.getAttribute("data-tracwysiwyg-link"); var autolink = node.getAttribute("data-tracwysiwyg-autolink"); var attrs; if (link === null) { attrs = TracWysiwyg.unserializeFromHref(node.href); link = attrs["data-tracwysiwyg-link"]; autolink = attrs["data-tracwysiwyg-autolink"]; } link = (link || node.href).replace(/^\s+|\s+$/g, ""); var label = getTextContent(node).replace(/^\s+|\s+$/g, ""); if (!label) { return; } var text = null; var traclink = null; if (autolink == "true") { if (wikiPageNamePattern.test(label)) { text = label; link = "wiki:" + label; traclink = "[wiki:" + label + "]"; } else if (wikiSyntaxPattern.test(label)) { text = label; link = self.convertWikiSyntax(label); } else if (tracLinkPattern.test(label)) { text = link = label; } } else { if (link == label && tracLinkPattern.test(label)) { text = label; } } if (!text) { var match = /^([\w.+-]+):(@?(.*))$/.exec(link); if (match) { if (label == match[2]) { if (match[1] == "wiki" && wikiPageNamePattern.test(match[2])) { text = match[2]; traclink = "[wiki:" + text + "]"; } else { text = "[" + link + "]"; } } else { var usingLabel = false; switch (match[1]) { case "changeset": usingLabel = label == "[" + match[2] + "]" || /^\d+$/.test(match[2]) && label == "r" + match[2]; break; case "log": usingLabel = label == "[" + match[3] + "]" || label == "r" + match[3]; break; case "report": usingLabel = label == "{" + match[2] + "}"; break; case "ticket": usingLabel = label == "#" + match[2]; break; } if (usingLabel) { text = label; } } } } if (isTailEscape()) { texts.push(" "); } if (text === null) { text = tracLinkText(link, label); } if (!traclink && /^[\w.+-]/.test(text)) { traclink = tracLinkText(link, label); } pushTextWithDecorations(text, node, traclink); } function string(source, times) { var value = (1 << times) - 1; if (value <= 0) { return ""; } else { return value.toString(2).replace(/1/g, source); } } function open(name, node) { if (skipNode !== null) { return; } var _texts = texts; var token = wikiOpenTokens[name]; if (token !== undefined) { if (name in wikiBlockTags && self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } if (token !== true) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } } else { switch (name) { case "#text": var value = node.nodeValue; if (value) { if (!inCodeBlock) { if (value && !self.isInlineNode(node.previousSibling || node.parentNode)) { value = value.replace(/^[ \t\r\n\f\v]+/g, ""); } if (value && !self.isInlineNode(node.nextSibling || node.parentNode)) { value = value.replace(/[ \t\r\n\f\v]+$/g, ""); } value = value.replace(/\r?\n/g, " "); if (!formatCodeBlock) { value = value.replace(wikiInlineRulesPattern, escapeText); } } if (value) { var length = _texts.length; var prev = length > 0 ? _texts[length - 1] : null; if (prev && prev["tracwysiwyg-traclink"] && tracLinkPattern.test(prev + value.substring(0, 1))) { _texts[length - 1] = prev["tracwysiwyg-traclink"]; } _texts.push(value); } } break; case "p": if (quoteDepth > 0) { _texts.push(string(quoteCitation ? "> " : " ", quoteDepth)); } else if (!/[^ \t\r\n\f\v]/.test(getTextContent(node))) { skipNode = node; } break; case "a": skipNode = node; pushAnchor(node); break; case "li": _texts.push(" " + string(" ", listDepth - 1)); var container = node.parentNode; if ((container.tagName || "").toLowerCase() == "ol") { var start = container.getAttribute("start") || ""; if (start != "1" && /^(?:[0-9]+|[a-zA-Z]|[ivxIVX]{1,5})$/.test(start)) { _texts.push(start, ". "); } else { switch (container.className) { case "arabiczero": _texts.push("0. "); break; case "lowerroman": _texts.push("i. "); break; case "upperroman": _texts.push("I. "); break; case "loweralpha": _texts.push("a. "); break; case "upperalpha": _texts.push("A. "); break; default: _texts.push("1. "); break; } } } else { _texts.push("* "); } break; case "ul": case "ol": if (listDepth == 0) { if (self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } } else if (listDepth > 0) { if (node.parentNode.tagName.toLowerCase() == "li") { _texts.push("\n"); } } listDepth++; break; case "br": if (!self.isBogusLineBreak(node)) { var value = null; if (inCodeBlock) { value = "\n"; } else if (formatCodeBlock) { switch (((node.parentNode || {}).tagName || "").toLowerCase()) { case "li": value = "\n " + string(" ", listDepth); break; case "p": case "blockquote": value = "\n"; if (quoteDepth > 0) { value += string(quoteCitation ? "> " : " ", quoteDepth); } break; case "dd": value = "\n "; break; case "dt": case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": value = " "; break; default: value = "\n"; break; } } else { if (escapeNewlines && getSelfOrAncestor(node, /^(?:p|blockquote)$/)) { value = quoteDepth > 0 ? "\n" + string(quoteCitation ? "> " : " ", quoteDepth) : "\n"; } if (!value) { value = "[[BR]]"; var length = _texts.length; if (length > 0) { var lastText = _texts[length - 1]; var tmp = lastText + "[[BR]]"; var _pattern = wikiInlineRulesPattern; _pattern.lastIndex = 0; var lastMatch, match; while (match = _pattern.exec(tmp)) { lastMatch = match; } if (lastMatch && lastMatch.index < lastText.length && lastMatch.index + lastMatch[0].length > lastText.length) { value = " [[BR]]"; } } } } _texts.push(value); } break; case "pre": _texts.push( /^(?:li|dd)$/i.test(node.parentNode.tagName) || self.isInlineNode(node.previousSibling) ? "\n{{{\n" : "{{{\n"); inCodeBlock = true; break; case "blockquote": if (self.isInlineNode(node.previousSibling)) { _texts.push("\n"); } quoteDepth++; if (quoteDepth == 1) { quoteCitation = (node.className == "citation"); } break; case "td": case "th": skipNode = node; _texts.push("||"); var text = self.domToWikitext(node, self.options).replace(/ *\n/g, "[[BR]]").replace(/^ +| +$/g, ""); _texts.push(text ? " " + text + " " : " "); break; case "tr": if (quoteDepth > 0) { _texts.push(string(quoteCitation ? ">" : " ", quoteDepth)); } break; case "tt": skipNode = node; var value = getTextContent(node); var text; if (value) { if (isTailEscape()) { _texts.push(" "); } if (!/`/.test(value)) { text = "`" + value + "`"; } else if (!/\{\{\{|\}\}\}/.test(value)) { text = "{{{" + value + "}}}"; } else { text = value.replace(/[^`]+|`+/g, function(m) { return m.charCodeAt(0) != 0x60 ? "`" + m + "`" : "{{{" + m + "}}}"; }); } pushTextWithDecorations(text, node); } break; case "span": var token = tokenFromSpan(node); if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } break; case "script": case "style": skipNode = node; break; } } } function close(name, node) { if (skipNode !== null) { if (skipNode == node) { skipNode = null; } return; } var _texts = texts; var token = wikiCloseTokens[name]; if (token === true) { // nothing to do } else if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } pushToken(token); } else { switch (name) { case "p": _texts.push(quoteDepth == 0 ? "\n\n" : "\n"); break; case "li": if (node.getElementsByTagName("li").length == 0) { _texts.push("\n"); } break; case "ul": case "ol": listDepth--; if (listDepth == 0) { _texts.push("\n"); } break; case "pre": var text; var parentNode = node.parentNode; if (parentNode && /^(?:li|dd)$/i.test(parentNode.tagName)) { var nextSibling = node.nextSibling; if (!nextSibling) { text = "\n}}}"; } else if (nextSibling.nodeType != 1) { text = "\n}}}\n"; } else if (nextSibling.tagName.toLowerCase() == "pre") { text = "\n}}}"; } else { text = "\n}}}\n"; } if (text.slice(-1) == "\n") { text += listDepth > 0 ? " " + string(" ", listDepth) : " "; } } else { text = "\n}}}\n"; } _texts.push(text); inCodeBlock = false; break; case "blockquote": quoteDepth--; if (quoteDepth == 0) { _texts.push("\n"); } break; case "span": var token = tokenFromSpan(node); if (token !== undefined) { if (name in wikiInlineTags && isTailEscape()) { _texts.push(" "); } _texts.push(token); } break; case "table": if (quoteDepth == 0) { _texts.push("\n"); } break; } } if (/^h[1-6]$/.test(name)) { if (xmlNamePattern.test(node.id || "")) { _texts.push(" #", node.id); } _texts.push("\n"); } } function iterator(node) { var name = null; switch (node && node.nodeType) { case 1: // element name = node.tagName.toLowerCase(); break; case 3: // text name = "#text"; break; } if (node && last == node.parentNode) { // down // nothing to do } else if (node && last == node.previousSibling) { // forward close(stack.pop(), last); } else { // up, forward var tmp = last; var nodeParent = node ? node.parentNode : root; for ( ; ; ) { var parent = tmp.parentNode; if (parent == node) { break; } close(stack.pop(), tmp); if (parent == nodeParent || !parent) { if (!node) { return; } break; } tmp = parent; } } open(name, node); stack.push(name); last = node; } this.treeWalk(root, iterator); return texts.join("").replace(/^(?: *\n)+|(?: *\n)+$/g, ""); }; if (window.getSelection) { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { var wikiInlineTags = this.wikiInlineTags; var last = element.lastChild; for ( ; ; ) { if (!last) { break; } if (last.nodeType != 1) { return; } var name = last.tagName.toLowerCase(); if (name == "br") { break; } if (!(name in wikiInlineTags)) { return; } last = last.lastChild || last.previousSibling; } var br = this.contentDocument.createElement("br"); element.appendChild(br); }; TracWysiwyg.prototype.isBogusLineBreak = TracWysiwyg.prototype.isLastChildInBlockNode; TracWysiwyg.prototype.insertParagraphOnEnter = function(event) { var range = this.getSelectionRange(); var node = range.endContainer; var header = null; if (node && node.nodeType == 3 && range.endOffset == node.nodeValue.length) { var nextSibling = node.nextSibling; if (!nextSibling || nextSibling.tagName.toLowerCase() == "br") { while (node) { if (node.nodeType == 1 && /^h[1-6]$/i.exec(node.tagName)) { header = node; break; } node = node.parentNode; } if (header) { var parent = header.parentNode; var childNodes = parent.childNodes; var length = childNodes.length; for (var offset = 0; offset < length; offset++) { if (childNodes[offset] == header) { offset++; break; } } this.selectRange(parent, offset, parent, offset); this.insertHTML('


'); TracWysiwyg.stopEvent(event); } } } }; TracWysiwyg.prototype.tableHTML = function(id, row, col) { var html = this._tableHTML(row, col); return html.replace(/<\/td>/g, '
').replace(//, ''); }; TracWysiwyg.prototype.insertTableCell = function(row, index) { var cell = row.insertCell(index); this.appendBogusLineBreak(cell); return cell; }; TracWysiwyg.prototype.getFocusNode = function() { return this.contentWindow.getSelection().focusNode; }; if (window.opera) { TracWysiwyg.prototype.insertLineBreak = function() { this.execCommand("inserthtml", "
"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; } else if (window.getSelection().setBaseAndExtent) { // Safari 2+ TracWysiwyg.prototype.insertLineBreak = function() { this.execCommand("insertlinebreak"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = function(event) { this.insertLineBreak(); TracWysiwyg.stopEvent(event); }; } else { // Firefox 2+ TracWysiwyg.prototype.insertLineBreak = function() { var d = this.contentDocument; var event = d.createEvent("KeyboardEvent"); event.initKeyEvent("keypress", true, true, null, false, false, true, false, 0x000d, 0); d.body.dispatchEvent(event); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; } if (window.getSelection().removeAllRanges) { TracWysiwyg.prototype.selectNode = function(node) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.selectNode(node); selection.addRange(range); }; TracWysiwyg.prototype.selectNodeContents = function(node) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.selectNodeContents(node); selection.addRange(range); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var selection = this.contentWindow.getSelection(); selection.removeAllRanges(); var range = this.contentDocument.createRange(); range.setStart(start, startOffset); range.setEnd(end, endOffset); selection.addRange(range); }; TracWysiwyg.prototype.getNativeSelectionRange = function() { var selection = this.contentWindow.getSelection(); return selection.rangeCount > 0 ? selection.getRangeAt(0) : null; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { if (arg.start || arg.end) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange() || this.contentDocument.createRange(); selection.removeAllRanges(); if (arg.start) { range.setStartBefore(arg.start); } if (arg.end) { range.setEndAfter(arg.end); } selection.addRange(range); } }; TracWysiwyg.prototype.insertHTML = function(html) { this.execCommand("inserthtml", html); }; } else { // Safari 2 TracWysiwyg.prototype.selectNode = function(node) { var selection = this.contentWindow.getSelection(); var range = this.contentDocument.createRange(); range.selectNode(node); selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); range.detach(); }; TracWysiwyg.prototype.selectNodeContents = function(node) { this.selectRange(node, 0, node, node.childNodes.length); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var selection = this.contentWindow.getSelection(); selection.setBaseAndExtent(start, startOffset, end, endOffset); }; TracWysiwyg.prototype.getNativeSelectionRange = function() { var selection = this.contentWindow.getSelection(); if (selection.anchorNode) { var range = this.contentDocument.createRange(); range.setStart(selection.baseNode, selection.baseOffset); range.setEnd(selection.extentNode, selection.extentOffset); if (range.collapsed && !selection.isCollapsed) { range.setStart(selection.extentNode, selection.extentOffset); range.setEnd(selection.baseNode, selection.baseOffset); } return range; } return null; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { if (arg.start || arg.end) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange(); if (arg.start) { range.setStartBefore(arg.start); } if (arg.end) { range.setEndAfter(arg.end); } selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); range.detach(); } }; TracWysiwyg.prototype.insertHTML = function(html) { var range = this.getNativeSelectionRange(); if (range) { var d = this.contentDocument; var tmp = d.createRange(); tmp.setStart(d.body, 0); tmp.setEnd(d.body, 0); var fragment = tmp.createContextualFragment(html); range.deleteContents(); range.insertNode(fragment); range.detach(); tmp.detach(); } }; } TracWysiwyg.prototype.getSelectionRange = TracWysiwyg.prototype.getNativeSelectionRange; TracWysiwyg.prototype.getSelectionText = function() { var range = this.getNativeSelectionRange(); return range ? range.toString() : null; }; TracWysiwyg.prototype.getSelectionHTML = function() { var fragment = this.getSelectionFragment(); var anonymous = this.contentDocument.createElement("div"); anonymous.appendChild(fragment); return anonymous.innerHTML; }; TracWysiwyg.prototype.getSelectionFragment = function() { var range = this.getNativeSelectionRange(); return range ? range.cloneContents() : this.contentDocument.createDocumentFragment(); }; TracWysiwyg.prototype.getSelectionPosition = function() { var range = this.getNativeSelectionRange(); var position = { start: null, end: null }; if (range) { position.start = range.startContainer; position.end = range.endContainer; } return position; }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { var selection = this.contentWindow.getSelection(); var range = this.getNativeSelectionRange(); if (!range) { return false; } var ancestor = range.commonAncestorContainer; if (!ancestor) { return false; } if (TracWysiwyg.getSelfOrAncestor(ancestor, name)) { return true; } if (ancestor.nodeType != 1) { return false; } var elements = ancestor.getElementsByTagName(name); var length = elements.length; for (var i = 0; i < length; i++) { if (selection.containsNode(elements[i], true)) { return true; } } return false; }; } else if (document.selection) { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { }; TracWysiwyg.prototype.isBogusLineBreak = function(node) { return false }; TracWysiwyg.prototype.insertParagraphOnEnter = null; TracWysiwyg.prototype.insertLineBreak = function() { this.insertHTML("
"); }; TracWysiwyg.prototype.insertLineBreakOnShiftEnter = null; TracWysiwyg.prototype.tableHTML = function(id, row, col) { var html = this._tableHTML(row, col); return html.replace(//, ''); }; TracWysiwyg.prototype.insertTableCell = function(row, index) { return row.insertCell(index); }; TracWysiwyg.prototype.getFocusNode = function() { this.contentWindow.focus(); var d = this.contentDocument; var range = d.selection.createRange(); var node = range.item ? range.item(0) : range.parentElement(); return node.ownerDocument == d ? node : null; }; TracWysiwyg.prototype.selectNode = function(node) { var d = this.contentDocument; var body = d.body; var range; d.selection.empty(); try { range = body.createControlRange(); range.addElement(node); } catch (e) { range = body.createTextRange(); range.moveToElementText(node); } range.select(); }; TracWysiwyg.prototype.selectNodeContents = function(node) { var d = this.contentDocument; d.selection.empty(); var range = d.body.createTextRange(); range.moveToElementText(node); range.select(); }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { var d = this.contentDocument; var body = d.body; d.selection.empty(); var range = endPoint(start, startOffset); if (start != end || startOffset != endOffset) { range.setEndPoint("EndToEnd", endPoint(end, endOffset)); } range.select(); function endPoint(node, offset) { var range; if (node.nodeType == 1) { var childNodes = node.childNodes; if (offset >= childNodes.length) { range = body.createTextRange(); range.moveToElementText(node); range.collapse(false); return range; } node = childNodes[offset]; if (node.nodeType == 1) { range = body.createTextRange(); range.moveToElementText(node); range.collapse(true); switch (node.tagName.toLowerCase()) { case "table": range.move("character", -1); break; } return range; } return endPoint(node, 0); } if (node.nodeType != 3) { throw "selectRange: nodeType != @".replace(/@/, node.nodeType); } range = body.createTextRange(); var element = node.previousSibling; while (element) { var nodeType = element.nodeType; if (nodeType == 1) { range.moveToElementText(element); range.collapse(false); break; } if (nodeType == 3) { offset += element.nodeValue.length; } element = element.previousSibling; } if (!element) { range.moveToElementText(node.parentNode); range.collapse(true); } if (offset != 0) { range.move("character", offset); } return range; } }; TracWysiwyg.prototype.getSelectionRange = function() { var body = this.contentDocument.body; var pseudo = {}; var start = this.getNativeSelectionRange(); if (start.item) { var element = start.item(0); var parent = element.parentNode; var childNodes = parent.childNodes; var length = childNodes.length; for (var i = 0; i < length; i++) { if (childNodes[i] == element) { pseudo.startOffset = i; pseudo.endOffset = i + 1; break; } } pseudo.collapsed = false; pseudo.startContainer = pseudo.endContainer = parent; return pseudo; } var end = start.duplicate(); pseudo.collapsed = start.compareEndPoints("StartToEnd", end) == 0; start.collapse(true); end.collapse(false); function nextElement(range) { var parent = range.parentElement(); var childNodes = parent.childNodes; var length = childNodes.length; for (var i = 0; i < length; i++) { var node = childNodes[i]; if (node.nodeType == 1) { var tmp = body.createTextRange(); tmp.moveToElementText(node); if (range.compareEndPoints("EndToStart", tmp) <= 0) { return node; } } } return null; } function nodeOffset(range, parent, element, index, length) { var tmp = body.createTextRange(); tmp.moveToElementText(element || parent); tmp.collapse(!!element); tmp.move("character", -index); if (!element) { length++; } for ( ; length >= 0; length--) { if (tmp.compareEndPoints("EndToStart", range) == 0) { return length; } tmp.move("character", -1); } return null; } function setContainerOffset(range, containerKey, offsetKey) { var parent = range.parentElement(); var element = nextElement(range); var index = 0; var node = element ? element.previousSibling : parent.lastChild; var offset, length; while (node && node.nodeType == 3) { length = node.nodeValue.length; offset = nodeOffset(range, parent, element, index, length); if (offset !== null) { pseudo[containerKey] = node; pseudo[offsetKey] = offset; return; } index += length; node = node.previousSibling; } var childNodes = parent.childNodes; length = childNodes.length; if (length > 0) { pseudo[containerKey] = parent; pseudo[offsetKey] = containerKey == "startContainer" ? 0 : length - 1; return; } element = parent; parent = element.parentNode; childNodes = parent.childNodes; length = childNodes.length; for (offset = 0; offset < length; offset++) { if (element == childNodes[offset]) { pseudo[containerKey] = parent; pseudo[offsetKey] = offset; return; } } } setContainerOffset(start, "startContainer", "startOffset"); setContainerOffset(end, "endContainer", "endOffset"); return pseudo; }; TracWysiwyg.prototype.getNativeSelectionRange = function() { this.contentWindow.focus(); return this.contentDocument.selection.createRange(); }; TracWysiwyg.prototype.getSelectionText = function() { var range = this.getNativeSelectionRange(); if (range) { return range.item ? range.item(0).innerText : range.text; } return null; }; TracWysiwyg.prototype.getSelectionHTML = function() { var range = this.getNativeSelectionRange(); if (range) { return range.item ? range.item(0).innerHTML : range.htmlText; } return null; }; TracWysiwyg.prototype.getSelectionFragment = function() { var d = this.contentDocument; var fragment = d.createDocumentFragment(); var anonymous = d.createElement("div"); anonymous.innerHTML = this.getSelectionHTML(); this.collectChildNodes(fragment, anonymous); return fragment; }; TracWysiwyg.prototype.getSelectionPosition = function() { this.contentWindow.focus(); var d = this.contentDocument; var range = d.selection.createRange(); var startNode = null; var endNode = null; if (range.item) { if (range.item(0).ownerDocument == d) { startNode = range.item(0); endNode = range.item(range.length - 1); } } else { if (range.parentElement().ownerDocument == d) { var startRange = range.duplicate(); startRange.collapse(true); startNode = startRange.parentElement(); var endRange = range.duplicate(); endRange.collapse(false); endNode = endRange.parentElement(); } } return { start: startNode, end: endNode }; }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { this.contentWindow.focus(); var d = this.contentDocument; var body = d.body; var range = d.selection.createRange(); var tmp; if (arg.start) { tmp = body.createTextRange(); tmp.moveToElementText(arg.start); range.setEndPoint("StartToStart", tmp); } if (arg.end) { tmp = body.createTextRange(); tmp.moveToElementText(arg.end); range.setEndPoint("EndToEnd", tmp); } if (tmp) { range.select(); } }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { this.contentWindow.focus(); var d = this.contentDocument; var selection = d.selection; var range = selection.createRange(); var parent = range.item ? range.item(0) : range.parentElement(); if (!parent) { return false; } if (TracWysiwyg.getSelfOrAncestor(parent, name)) { return true; } var elements = parent.getElementsByTagName(name); var length = elements.length; for (var i = 0; i < length; i++) { var testRange = selection.createRange(); testRange.moveToElementText(elements[i]); if (range.compareEndPoints("StartToEnd", testRange) <= 0 && range.compareEndPoints("EndToStart", testRange) >= 0) { return true; } } return false; }; TracWysiwyg.prototype.insertHTML = function(html) { this.contentWindow.focus(); var selection = this.contentDocument.selection; var range = selection.createRange(); range.pasteHTML(html.replace(/\t/g, " ")); range.collapse(false); range.select(); range = this.contentDocument.selection.createRange(); }; } else { TracWysiwyg.prototype.appendBogusLineBreak = function(element) { }; TracWysiwyg.prototype.insertParagraphOnEnter = null; TracWysiwyg.prototype.insertLineBreak = function() { }; TracWysiwyg.prototype.insertTableCell = function(row, index) { return null }; TracWysiwyg.prototype.getFocusNode = function() { return null }; TracWysiwyg.prototype.selectNode = function(node) { }; TracWysiwyg.prototype.selectNodeContents = function(node) { return null }; TracWysiwyg.prototype.selectRange = function(start, startOffset, end, endOffset) { }; TracWysiwyg.prototype.getSelectionRange = function() { return null }; TracWysiwyg.prototype.getNativeSelectionRange = function() { return null }; TracWysiwyg.prototype.getSelectionText = function() { return null }; TracWysiwyg.prototype.getSelectionHTML = function() { return null }; TracWysiwyg.prototype.getSelectionFragment = function() { return null }; TracWysiwyg.prototype.getSelectionPosition = function() { return null }; TracWysiwyg.prototype.expandSelectionToElement = function(arg) { }; TracWysiwyg.prototype.selectionContainsTagName = function(name) { return false }; TracWysiwyg.prototype.insertHTML = function(html) { }; } TracWysiwyg.prototype._treeWalkEmulation = function(root, iterator) { if (!root.firstChild) { iterator(null); return; } var element = root; var tmp; while (element) { if (tmp = element.firstChild) { element = tmp; } else if (tmp = element.nextSibling) { element = tmp; } else { for ( ; ; ) { element = element.parentNode; if (element == root || !element) { iterator(null); return; } if (tmp = element.nextSibling) { element = tmp; break; } } } iterator(element); } }; if (document.createTreeWalker) { TracWysiwyg.prototype.treeWalk = function(root, iterator) { var walker = root.ownerDocument.createTreeWalker( root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, true); while (walker.nextNode()) { iterator(walker.currentNode); } iterator(null); }; } else { TracWysiwyg.prototype.treeWalk = TracWysiwyg.prototype._treeWalkEmulation; } TracWysiwyg.instances = []; TracWysiwyg.count = 0; TracWysiwyg.tracPaths = null; TracWysiwyg.newInstance = function(textarea, options) { var instance = new TracWysiwyg(textarea, options); TracWysiwyg.instances.push(instance); return instance; }; TracWysiwyg.findInstance = function(textarea) { var instances = TracWysiwyg.instances; var length = instances.length; for (var i = 0; i < length; i++) { var instance = instances[i]; if (instance.textarea == textarea) { return instance; } } return null; }; TracWysiwyg.getTracPaths = function() { var stylesheets = []; var paths = { stylesheets: stylesheets }; var d = document; var head = d.getElementsByTagName("head")[0]; var links = head.getElementsByTagName("link"); var length = links.length; for (var i = 0; i < length; i++) { var link = links[i]; var href = link.getAttribute("href") || ""; var type = link.getAttribute("type") || ""; switch ((link.getAttribute("rel") || "").toLowerCase()) { case "tracwysiwyg.base": paths.base = href; break; case "tracwysiwyg.stylesheet": stylesheets.push(href); break; } } if (paths.base && stylesheets.length > 0) { return paths; } return null; }; TracWysiwyg.getOptions = function() { var options = {}; if (typeof window._tracwysiwyg != "undefined") { options = _tracwysiwyg; } return options; }; TracWysiwyg.getEditorMode = function() { if (TracWysiwyg.editorMode) { return TracWysiwyg.editorMode; } var mode = null; var cookies = (document.cookie || "").split(";"); var length = cookies.length; for (var i = 0; i < length; i++) { var match = /^\s*tracwysiwyg=(\S*)/.exec(cookies[i]); if (match) { switch (match[1]) { case "wysiwyg": mode = match[1]; break; default: // "textarea" mode = null; break; } break; } } TracWysiwyg.editorMode = mode || "textarea"; return TracWysiwyg.editorMode; }; TracWysiwyg.setEditorMode = function(mode) { switch (mode) { case "wysiwyg": break; default: // "textarea" mode = "textarea"; break; } TracWysiwyg.editorMode = mode; var now = new Date(); if (!/\/$/.test(TracWysiwyg.tracPaths.base)) { expires = new Date(now.getTime() - 86400000); pieces = [ "tracwysiwyg=", "path=" + TracWysiwyg.tracPaths.base + "/", "expires=" + expires.toUTCString() ]; document.cookie = pieces.join("; "); } var expires = new Date(now.getTime() + 365 * 86400 * 1000); var pieces = [ "tracwysiwyg=" + mode, "path=" + TracWysiwyg.tracPaths.base, "expires=" + expires.toUTCString() ]; document.cookie = pieces.join("; "); }; TracWysiwyg.stopEvent = function(event) { if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; } }; TracWysiwyg.setStyle = function(element, object) { var style = element.style; for (var name in object) { style[name] = object[name]; } }; if (document.defaultView) { TracWysiwyg.getStyle = function(element, name) { var value = element.style[name]; if (!value) { var style = element.ownerDocument.defaultView.getComputedStyle(element, null) value = style ? style[name] : null; } return value; }; } else { TracWysiwyg.getStyle = function(element, name) { return element.style[name] || element.currentStyle[name]; }; } TracWysiwyg.elementPosition = function(element) { function vector(left, top) { var value = [ left, top ]; value.left = left; value.top = top; return value; } var position = TracWysiwyg.getStyle(element, "position"); var left = 0, top = 0; for (var node = element; node; node = node.offsetParent) { left += node.offsetLeft || 0; top += node.offsetTop || 0; } if (position != "absolute") { return vector(left, top); } var offset = TracWysiwyg.elementPosition(element.offsetParent); return vector(left - offset.left, top - offset.top); }; TracWysiwyg.getTextAreaHeight = function(textarea) { var height = textarea.offsetHeight; if (height == 0) { height = parseInt(textarea.rows) * parseInt(TracWysiwyg.getStyle(textarea, 'line-height'), 10); } return height; }; TracWysiwyg.getSelfOrAncestor = function(element, name) { var target = element; var d = element.ownerDocument; if (name instanceof RegExp) { while (target && target != d) { switch (target.nodeType) { case 1: // element if (name.test(target.tagName.toLowerCase())) { return target; } break; case 11: // fragment return null; } target = target.parentNode; } } else { name = name.toLowerCase(); while (target && target != d) { switch (target.nodeType) { case 1: // element if (target.tagName.toLowerCase() == name) { return target; } break; case 11: // fragment return null; } target = target.parentNode; } } return null; }; TracWysiwyg.serializeToHref = function(attrs) { var texts = []; for (var name in attrs) { if (/^data(?:-|$)/.exec(name)) { texts.push(encodeURIComponent(name) + "=" + encodeURIComponent(attrs[name])); } } return "#" + texts.join("&"); }; TracWysiwyg.unserializeFromHref = function(href, name) { var attrs = {}; if (href.indexOf("#") !== -1) { var pieces = href.replace(/^[^#]*#/, '').split(/&/g); var length = pieces.length; for (var i = 0; i < length; i++) { var pair = pieces[i].split(/=/g, 2); attrs[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } } return name ? attrs[name] : attrs; }; TracWysiwyg.getTextContent = (function() { var anonymous = document.createElement("div"); if (typeof anonymous.textContent != "undefined") { return function(element) { return element.textContent }; } else if (typeof anonymous.innerText != "undefined") { return function(element) { return element.innerText }; } else { return function(element) { return null }; } })(); TracWysiwyg.initialize = function() { if ("replace".replace(/[a-e]/g, function(m) { return "*" }) != "r*pl***") { return; } if (typeof document.designMode == "undefined") { return; } TracWysiwyg.tracPaths = TracWysiwyg.getTracPaths(); if (!TracWysiwyg.tracPaths) { return; } var options = TracWysiwyg.getOptions(); var textareas = document.getElementsByTagName("textarea"); for (var i = 0; i < textareas.length; i++) { var textarea = textareas[i]; if (/\bwikitext\b/.test(textarea.className || "")) { TracWysiwyg.newInstance(textarea, options); } } }; trac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/htdocs/toolbar.png0000644000175000017500000001136010672463456022021 0ustar wmbwmbPNG  IHDRoT pHYs  IDATxytTUTe'T8$"F`[FisPEpa4=:8=l3b;i[D#l-!IJBR*{珪o4ݹS{Ww~}ORJ0 gsiZ[ZM&7oӲ'P1glTU"ydbt:]CJN;SؐJ!)/+׮Ͼ E`MM xF'bŮ0u6n^?Jmmm/ddfN2<##8H6WB aՕRv  BHUzdSfJ)AH "A*T!P$(SPH/Kq;EAAߺ':NNEgTVTos-G>v)S|)Waz=&O@oMbt;`ӉbiogQtV+SN!ɖDjni:97 TwPQ^?':n5S>[٧xt̿6EC aws%8yS-y\.mx;456q{X-8m4rnbwŇ8u4_="##P"%t$sl6j]"aΓR" h ^M*<=J(TjҒSlHÀ߯J5o>J˚IΌn2zre|v6hM&#I6RdK⦜1gzqx ~Ή_qԙУQadM"99+>ucǎmq]u LNI&>>^#Ix\-=abw}'.r݉b=V+eT@)W:.yo_>ԴT-j8q"RJjkjinn!--ظa !!ظXΕ#'&Mv01 Ξ9˜sXzOrӧEdfevt2mZ6wͿ+fde"M*TwFZW71qDV>EAme22Jn cB )_Z~.8W6K.ɭI![:o:<nK)xXUu ro-9_G 9ꨯC*g{Ǎ/=E󰾡]IBTU%mr'~>!&^O{[-^D :y(|>,&>!>6BZ[Z :ZۈN>O1њZ7<ޡv5KݐM_ȑhokg$mrUUVc99t:bd1̦r2Ȍ|{{ aaFffi)g}RXڹsl: sis%_fMIIg,Ƚ'O|ŲrRq69yżn>?zXbccIIMk]Q~xiΞ>KEE%wsFsgOp{=ȢŋPCOVleR uuDFZB /r]?+|}qqDƒܷ?*RRӜ=SBEEwοs(S<DTUź@J5'p|y<Z[H%K}]=Vi3ñ7Hjkf :k&$Lr U^wE||f AS~̬ &' ^egs#ؒp:]_S \Ӓ9CKbjkkCέC3y &P$9|rͻ7Աw^gG1Mt$M C~<&9971iR\ 0cW'|RU ˗/[͛9<٬Xhym6ZZZ:u*=%nLnذA&h%pgl?,..fMO[xip8x|ꩧGNc씫ñj<GFC6 #aw|;z;vcq\yaÆ6{ Kx-xẍR\.|#m{t:-Z4^:ͬ_EQXv7 چYF?Z݆{9~ӟOS@__A<6mڤEv~{pɚC"""FC^p333X7qa H%ugů+xLj}O êfwrlmlazhK ukG,ԠNܹ^.|`TBR<Tقu25x<[NU @03=7 > HAm<_PUθ}>d(?׸y 3!|x^F#>ٌ!""UUQN(ft:]x^B( @UUt:b0xIHHS7|zt:z=>_S*믿Nrrrד˗/B;UUUgrƍl7˖-[x駵jjv bٵk(~[obŊª*ݻY|9FL\\\nmmeϞ=j@ +!0 Z;F,YfqFVZb۩{˖a?XS)0pw}EBB/2K. iݾeZ|DDiSCAE|X1K/%ݿ7lxW|FFz_)%V #.6^q[۹pw~: 7p<]EQIx؄h@7 @^o@ 1L: `7oIENDB`trac-wysiwyg-0.12.0.3+r10725/0.11/tracwysiwyg/htdocs/editor.css0000644000175000017500000000024611211421434021626 0ustar wmbwmbpre.wiki { overflow: visible !important; word-wrap: break-word !important; white-space: -moz-pre-wrap !important; white-space: pre-wrap !important; } trac-wysiwyg-0.12.0.3+r10725/0.11/setup.cfg0000644000175000017500000000004310672463456015606 0ustar wmbwmb[egg_info] tag_svn_revision = true trac-wysiwyg-0.12.0.3+r10725/0.11/setup.py0000644000175000017500000000113411463324376015475 0ustar wmbwmb#!/usr/bin/env python # -*- coding: utf-8 -*- from setuptools import setup, find_packages setup( name = 'TracWysiwyg', version = '0.11.0.3', description = 'TracWiki WYSIWYG Editor', license = 'BSD', url = 'http://trac-hacks.org/wiki/TracWysiwygPlugin', author = 'Jun Omae', author_email = 'omae@opengroove.com', packages = find_packages(exclude=['*.tests*']), package_data = { 'tracwysiwyg' : [ 'htdocs/*.js', 'htdocs/*.css', 'htdocs/*.png' ], }, entry_points = { 'trac.plugins': [ 'tracwysiwyg = tracwysiwyg', ], } ) trac-wysiwyg-0.12.0.3+r10725/0.11/tests/0000755000175000017500000000000011677636642015137 5ustar wmbwmbtrac-wysiwyg-0.12.0.3+r10725/0.11/tests/testcase.js0000644000175000017500000017701611642344654017313 0ustar wmbwmbaddEvent(window, "load", function() { TracWysiwyg.tracPaths = { base: ".", stylesheets: [] }; var options = TracWysiwyg.getOptions(); var instance = new TracWysiwyg(document.getElementById("textarea"), options); var contentDocument = instance.contentDocument; var d = document; var wysiwygHtml = d.getElementById("wysiwyg-html"); var showWysiwygHtml = d.getElementById("show-wysiwyg-html"); setTimeout(function() { if (showWysiwygHtml.checked) { var body = contentDocument.body; var browserIE = body.attachEvent ? true : false; var elements = body.getElementsByTagName("br"); var count = 0; var html = body.innerHTML.replace(/<[Bb][Rr] *[^>\/]*/g, function(value) { var element = elements[count++]; var attributes = element.attributes; var length = attributes.length; if (length == 0) return value; var texts = [ value ]; for (var i = 0; i < length; i++) { var attr = attributes[i]; if (!browserIE || !!element[attr.name]) { texts.push(' ', attr.name, '="', attr.value, '"'); } } return texts.join(""); }); if (wysiwygHtml.value != html) { wysiwygHtml.value = html; } } setTimeout(arguments.callee, 500); }, 500); function generate(dom, wikitext, options, withoutDomToWikitext, withoutWikitextToFragment) { dom = dom.cloneNode(true); var anonymous = dom.ownerDocument.createElement("div"); anonymous.appendChild(dom); if (!withoutWikitextToFragment) { var fragment = instance.wikitextToFragment(wikitext, contentDocument, options); var generated = contentDocument.createElement("div"); generated.appendChild(fragment); var generatedHtml = generated.innerHTML; if (!generated.addEventListener || window.opera) { generatedHtml = generatedHtml.replace(/\n\r/g, "\uffff").replace(/\uffff\n?/g, "\n"); } this.assertEqual(anonymous.innerHTML, generatedHtml, "wikitextToFragment"); } if (!withoutDomToWikitext) { this.assertEqual(wikitext, instance.domToWikitext(anonymous, options), "domToWikitext"); } } function generateFragment(dom, wikitext, options) { generate.call(this, dom, wikitext, options, true, false); } function generateWikitext(dom, wikitext, options) { generate.call(this, dom, wikitext, options, false, true); } function run() { var unit = new TracWysiwyg.TestUnit(); var fragment = unit.fragment; var element = unit.element; var br = function() { return element("br") }; var a = function(link, label) { var attrs = { href: "#data-tracwysiwyg-link=" + encodeURIComponent(link), title: link, "data-tracwysiwyg-link": link, onclick: "return false;" }; return element("a", attrs, label || link); }; unit.add("treeWalk", function() { var list; function iterator(node) { var value; if (node) { switch (node.nodeType) { case 1: value = node.tagName.toLowerCase(); break; case 3: value = "#text"; break; } } else { value = "(null)"; } list.push(value); } function doTreeWalk(expected, dom) { list = []; instance.treeWalk(dom, iterator); this.assertEqual(expected, list.join(" ")); list = []; instance._treeWalkEmulation(dom, iterator); this.assertEqual(expected, list.join(" ")); } doTreeWalk.call(this, "p #text (null)", element("div", element("p", "paragraph"))); doTreeWalk.call(this, "#text (null)", element("div", element("p", "paragraph")).firstChild); doTreeWalk.call(this, "(null)", element("div", element("p")).firstChild); var dom = element("div"); dom.innerHTML = [ '

Tables

', '

', 'Simple tables can be created like this:', '

', '
||Cell 1||Cell 2||Cell 3||',
                '||Cell 4||Cell 5||Cell 6||',
                '

', 'Display:', '

', '', '
Cell 1Cell 2Cell 3', '
Cell 4Cell 5Cell 6', '
', '

', 'Note that more complex tables can be created using', 'reStructuredText.', '

' ].join(""); var expected = [ 'h2', '#text', 'p', '#text', 'pre', '#text', 'p', '#text', 'table', 'tbody', 'tr', 'td', '#text', 'td', '#text', 'td', '#text', 'tr', 'td', '#text', 'td', '#text', 'td', '#text', 'p', '#text', 'a', '#text', '#text', '(null)'].join(" "); doTreeWalk.call(this, expected, dom); }); unit.add("isLastChildInBlockNode", function() { var dom = fragment( element("p", element("br")), element("p", "foobar", element("br"), "foobar"), element("p", element("b", "foobar", element("br"))), element("p", element("b", "foobar"), element("br")), element("br")); var count = 0; function assert(expected, node) { this.assertEqual(expected, instance.isLastChildInBlockNode(node), "#" + (count++)); } assert.call(this, true, dom.childNodes[0].childNodes[0]); assert.call(this, false, dom.childNodes[1].childNodes[0]); assert.call(this, false, dom.childNodes[1].childNodes[1]); assert.call(this, true, dom.childNodes[1].childNodes[2]); assert.call(this, false, dom.childNodes[2].childNodes[0].childNodes[0]); assert.call(this, true, dom.childNodes[2].childNodes[0].childNodes[1]); assert.call(this, false, dom.childNodes[3].childNodes[0].childNodes[0]); assert.call(this, true, dom.childNodes[3].childNodes[1]); assert.call(this, true, dom.childNodes[4]); }); unit.add("code block", function() { var dom = fragment( element("p", element("tt", "abc")), element("pre", { "class": "wiki" }, "{{{code-block")); var wikitext = [ "`abc`", "", "{{{", "{{{code-block", "}}}" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("code block nest", function() { var dom = fragment( element("pre", { "class": "wiki" }, "#!python\n= level 1\n{{{\n= level 2\n}}}\n= level 1")); var wikitext = [ "{{{", "#!python", "= level 1", "{{{", "= level 2", "}}}", "= level 1", "}}}" ].join("\n"); generate.call(this, dom, wikitext); }); unit.add("paragraph", function() { var dom = fragment( element("p", "Paragraph continued..."), element("p", "Second paragraph continued...")); generateFragment.call(this, dom, [ "Paragraph", "continued...", "", "Second paragraph", "continued...", "" ].join("\n")); generate.call(this, dom, [ "Paragraph continued...", "", "Second paragraph continued..." ].join("\n")); }); unit.add("hr", function() { var dom = fragment( element("p", "Paragraph"), element("hr"), element("ul", element("li", "item 1"), element("ol", element("li", "item 1.1"))), element("hr")); generateFragment.call(this, dom, [ "Paragraph", "----", " * item 1", " 1. item 1.1", "----" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "----", " * item 1", " 1. item 1.1", "", "----" ].join("\n")); }); unit.add("bold italic", function() { var dom = element("p", element("b", element("i", "bold italic"))); var wikitext = "'''''bold italic'''''"; generate.call(this, dom, wikitext); }); unit.add("bold", function() { var wikitext = [ "The quick '''brown''' fox.", "", "The quick '''brown''' fox." ].join("\n"); generateWikitext.call(this, fragment( element("p", "The quick ", element("b", "brown"), " fox."), element("p", "The quick ", element("strong", "brown"), " fox.")), wikitext); generateFragment.call(this, fragment( element("p", "The quick ", element("b", "brown"), " fox."), element("p", "The quick ", element("b", "brown"), " fox.")), wikitext); }); unit.add("italic", function() { var wikitext = [ "The quick ''brown'' fox.", "", "The quick ''brown'' fox." ].join("\n"); generateWikitext.call(this, fragment( element("p", "The quick ", element("i", "brown"), " fox."), element("p", "The quick ", element("em", "brown"), " fox.")), wikitext); generateFragment.call(this, fragment( element("p", "The quick ", element("i", "brown"), " fox."), element("p", "The quick ", element("i", "brown"), " fox.")), wikitext); }); unit.add("underline", function() { var dom = element("p", element("u", "underline")); var wikitext = "__underline__"; generate.call(this, dom, wikitext); }); unit.add("strike-through", function() { var dom = element("p", element("del", "strike-through")); var wikitext = "~~strike-through~~"; generate.call(this, dom, wikitext); }); unit.add("superscript", function() { var dom = element("p", element("sup", "superscript")); var wikitext = "^superscript^"; generate.call(this, dom, wikitext); }); unit.add("subscript", function() { var dom = element("p", element("sub", "subscript")); var wikitext = ",,subscript,,"; generate.call(this, dom, wikitext); }); unit.add("monospace", function() { var dom = element("p", element("tt", "monospace"), ", ", element("tt", "mono`s`pace"), ", ", element("tt", "mono{{{s}}}pace")); var wikitext = "`monospace`, {{{mono`s`pace}}}, `mono{{{s}}}pace`"; generate.call(this, dom, wikitext); }); unit.add("italic -> bold", function() { var dom = element("p", "normal", element("i", "italic"), element("b", "bold"), "normal"); var wikitext = "normal''italic'''''bold'''normal"; generate.call(this, dom, wikitext); }); unit.add("bold -> italic", function() { var dom = element("p", "normal", element("b", "bold"), element("i", "italic"), "normal"); var wikitext = "normal'''bold'''''italic''normal"; generate.call(this, dom, wikitext); }); unit.add("[ italic [ xyz ] bold ]", function() { var dom = element("p", "normal", element("i", "italic", element("b", "xyz")), element("b", "bold"), "normal"); var wikitext = "normal''italic'''xyz''bold'''normal"; generate.call(this, dom, wikitext); }); unit.add("overlapped markups", function() { var dom = element("p", "normal", element("b", "bold", element("i", "italic", element("u", "underline", element("del", "strike-through", element("sup", "superscript", element("sub", "subscript"))))), element("u", element("del", element("sup", element("sub", "i")))), element("del", element("sup", element("sub", "u"))), element("sup", element("sub", "strike")), element("sub", "sup"), "sub"), "."); var wikitext = "normal'''bold''italic__underline~~strike-through^superscript,,subscript''i__u~~strike^sup,,sub'''."; generateFragment.call(this, dom, wikitext); }); unit.add("repeated markups", function() { generateWikitext.call(this, element("p", "ab", element("b", "cd"), element("b", "ef"), "gh"), "ab'''cdef'''gh"); generateWikitext.call(this, element("p", "ab", element("i", "cd"), element("i", "ef"), "gh"), "ab''cdef''gh"); generateWikitext.call(this, element("p", "ab", element("u", "cd"), element("u", "ef"), "gh"), "ab__cdef__gh"); generateWikitext.call(this, element("p", "ab", element("sup", "cd"), element("sup", "ef"), "gh"), "ab^cdef^gh"); generateWikitext.call(this, element("p", "ab", element("sub", "cd"), element("sub", "ef"), "gh"), "ab,,cdef,,gh"); generateWikitext.call(this, element("p", "ab", element("tt", "cd"), element("tt", "ef"), "gh"), "ab`cd``ef`gh"); generateWikitext.call(this, element("p", "ab", element("i", element("b", "cd")), element("b", element("i", "ef")), "gh"), "ab'''''cdef'''''gh"); }); unit.add("markups without text", function() { generateWikitext.call(this, element("p", "abc", element("b", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("i", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("u", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("sup", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("sub", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("tt", ""), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("b", element("i", "")), "def"), "abcdef"); generateWikitext.call(this, element("p", "abc", element("i", element("b", "")), "def"), "abcdef"); }); unit.add("! bold italic", function() { var dom = element("p", element("b", element("i", "bold''''' italic")), "."); var wikitext = "'''''bold!''''' italic'''''."; generate.call(this, dom, wikitext); }); unit.add("! bold", function() { var dom = element("p", element("b", "bold''' bold"), "."); var wikitext = "'''bold!''' bold'''."; generate.call(this, dom, wikitext); }); unit.add("! italic", function() { var dom = element("p", element("i", "italic'' italic"), "."); var wikitext = "''italic!'' italic''."; generate.call(this, dom, wikitext); }); unit.add("! underline", function() { var dom = element("p", element("u", "underline__ underline"), "."); var wikitext = "__underline!__ underline__."; generate.call(this, dom, wikitext); }); unit.add("! strike-through", function() { var dom = element("p", element("del", "strike~~through"), "."); var wikitext = "~~strike!~~through~~."; generate.call(this, dom, wikitext); }); unit.add("! superscript", function() { var dom = element("p", element("sup", "superscript^ superscript"), "."); var wikitext = "^superscript!^ superscript^."; generate.call(this, dom, wikitext); }); unit.add("! subscript", function() { var dom = element("p", element("sub", "subscript,, subscript"), "."); var wikitext = ",,subscript!,, subscript,,."; generate.call(this, dom, wikitext); }); unit.add("! monospace", function() { var dom = element("p", "{{{monospace}}} or `monospace`"); var wikitext = "!{{{monospace}}} or !`monospace`"; generate.call(this, dom, wikitext); }); unit.add("#ticket", function() { var dom = element("p", a("ticket:1234", "#1234"), " #2345 ඀"); var wikitext = "#1234 !#2345 ඀"; generate.call(this, dom, wikitext); }); unit.add("{report}", function() { var dom = element("p", "{987}", a("report:123", "{123}")); var wikitext = "!{987}{123}"; generate.call(this, dom, wikitext); }); unit.add("[changeset]", function() { var dom = element("p", a("changeset:123", "[123]"), ", ", a("changeset:234", "r234"), ", ", a("changeset:345/trunk", "[345/trunk]"), ", [123], r234, [345/trunk], ar123"); generate.call(this, dom, "[123], r234, [345/trunk], ![123], !r234, ![345/trunk], ar123"); }); unit.add("[log]", function() { var dom = element("p", "log - ", a("log:@1:3", "r1:3"), ", r1:3, ", a("log:@1:3", "[1:3]"), ", [1:3], ", a("log:@1:3", "log:@1:3"), ", log:@1:3, ", a("log:trunk@1:3", "log:trunk@1:3"), ", log:trunk@1:3"); generate.call(this, dom, "log - r1:3, !r1:3, [1:3], ![1:3], log:@1:3, !log:@1:3, log:trunk@1:3, !log:trunk@1:3"); }); unit.add("wiki:TracLinks", function() { var dom = element("p", a("link:WikiName", "link:WikiName"), " ", a('link:"Foo Bar"', 'link:"Foo Bar"'), " ", a('link:"Foo Bar#baz"', 'link:"Foo Bar#baz"'), " ", a("link:'Foo Bar'", "link:'Foo Bar'"), " ", a("link:'Foo Bar#baz'", "link:'Foo Bar#baz'"), " ", a("svn+ssh://example.com/trunk", "svn+ssh://example.com/trunk"), " ", a("svn+ssh://example.com/trunk", "repository"), " ", a("rfc-2396.compatible://link", "rfc-2396.compatible://link"), " ", a("rfc-2396.compatible://link", "RFC 2396"), " ", a("foo:bar", "foo:bar"), " begin", a("foo:bar", "foo:bar"), " ", a("foo:bar", "foo:bar"), "end begin", a("wiki:WikiStart", "WikiStart"), "end link:'Foo Bar#baz'"); generateFragment.call(this, dom, [ "link:WikiName", 'link:"Foo Bar" link:"Foo Bar#baz"', "link:'Foo Bar' link:'Foo Bar#baz'", "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]", "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]", "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end", "!link:'Foo Bar#baz'" ].join(" ")); generate.call(this, dom, [ "link:WikiName", 'link:"Foo Bar" link:"Foo Bar#baz"', "link:'Foo Bar' link:'Foo Bar#baz'", "svn+ssh://example.com/trunk [svn+ssh://example.com/trunk repository]", "rfc-2396.compatible://link [rfc-2396.compatible://link RFC 2396]", "foo:bar begin[foo:bar foo:bar] [foo:bar foo:bar]end begin[wiki:WikiStart]end", "!link:'Foo Bar#baz'" ].join(" ")); }); unit.add("[wiki:TracLinks label]", function() { var dom = element("p", a("link:WikiName", "WikiName"), " ", a("link:WikiName", "wiki name"), " ", a("wiki:WikiName", "wiki]name"), " ", a("wiki:WikiName", "wiki name"), " ", a('link:"Foo Bar"', "Foo Bar"), " ", a('link:"Foo Bar#baz"', "Foo Bar#baz"), " ", a('link:"Foo Bar"', "bar foo"), " ", a('link:"Foo Bar#baz"', 'foo "foobar" bar'), " ", a("link:'Foo Bar'", "Foo Bar"), " ", a("link:'Foo Bar#baz'", "Foo Bar#baz"), " ", a("link:'Foo Bar'", "foo bar"), " ", a("link:'Foo Bar#baz'", "foo 'foobar' bar"), " [link:'Foo Bar#baz'] [link:'Foo Bar#baz' label]"); generateFragment.call(this, dom, [ "[link:WikiName]", "[link:WikiName 'wiki name']", '[wiki:WikiName "wiki]name"]', "[WikiName 'wiki name']", '[link:"Foo Bar"] [link:"Foo Bar#baz"]', '[link:"Foo Bar" "bar foo"] [link:"Foo Bar#baz" foo "foobar" bar]', "[link:'Foo Bar'] [link:'Foo Bar#baz']", "[link:'Foo Bar' 'foo bar'] [link:'Foo Bar#baz' foo 'foobar' bar]", "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" ")); generate.call(this, dom, [ "[link:WikiName]", "[link:WikiName wiki name]", '[wiki:WikiName "wiki]name"]', "[wiki:WikiName wiki name]", '[link:"Foo Bar" Foo Bar] [link:"Foo Bar#baz" Foo Bar#baz]', '[link:"Foo Bar" bar foo] [link:"Foo Bar#baz" foo "foobar" bar]', "[link:'Foo Bar' Foo Bar] [link:'Foo Bar#baz' Foo Bar#baz]", "[link:'Foo Bar' foo bar] [link:'Foo Bar#baz' foo 'foobar' bar]", "![link:'Foo Bar#baz'] ![link:'Foo Bar#baz' label]" ].join(" ")); }); unit.add("[/relative label]", function() { var dom = element("p", a("../trac", "Trac"), " ", a("/newticket?component=tracwysiwygplugin", "here"), " ", a("//hostname", "host"), " ", a("//hostname/images", "images"), " ", a("#anchor", "anchor")); var wikitext = [ "[../trac Trac]", "[/newticket?component=tracwysiwygplugin here]", "[//hostname host]", "[//hostname/images images]", "[#anchor anchor]" ].join(" "); generate.call(this, dom, wikitext); }); unit.add("[[macro]]", function() { var dom = element("p", "Line break ", element("br"), " another line", element("br"), "last line [[bR]] ![[Br]] [[Macro]] ![[Macro]]"); generateFragment.call(this, dom, "Line break [[BR]] another line[[br]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]]"); generate.call(this, dom, "Line break [[BR]] another line[[BR]]last line ![[bR]] !![[Br]] [[Macro]] ![[Macro]]"); }); unit.add("WikiPageName", function() { var dom = fragment( element("p", a("wiki:CamelCase", "CamelCase"), " CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor"), element("p", a("wiki:WikiStart", "WikiStart"), " Wiki", a("wiki:Start", "Start"), " ", a("wiki:Wiki", "Wiki"), "Start Wiki", a("wiki:Start", "Start"), "Wiki")); generate.call(this, dom, [ "CamelCase !CamelCase FooBarA FOo FoobarA OneÅngström Oneångström setTextColor", "", "WikiStart Wiki[wiki:Start] [wiki:Wiki]Start Wiki[wiki:Start]Wiki" ].join("\n")); }); unit.add('["internal free link"]', function() { var dom = element("p", "link - ", a('wiki:"internal free link"', "internal free link"), ' - ["free link"]'); generate.call(this, dom, 'link - [wiki:"internal free link" internal free link] - !["free link"]'); }); unit.add("traclink + underline", function() { var dom = element("p", element("u", a("ticket:123", "#123")), " ", a("ticket:123", element("u", "#123")), " ", element("u", a("report:123", "{123}")), " ", a("report:123", element("u", "{123}")), " ", element("u", a("changeset:123", "[123]")), " ", a("changeset:123", element("u", "[123]")), " ", element("u", a("changeset:123", "r123")), " ", a("changeset:123", element("u", "r123")), " ", element("u", a("log:@123:234", "[123:234]")), " ", a("log:@123:234", element("u", "[123:234]")), " ", element("u", a("wiki:WikiStart", "wiki:WikiStart")), " ", a("wiki:WikiStart", element("u", "wiki:WikiStart")), " ", element("u", a("wiki:WikiStart", "WikiStart")), " ", a("wiki:WikiStart", element("u", "WikiStart"))); generateWikitext.call(this, dom, [ '__#123__', '__#123__', '__{123}__', '__{123}__', '__[123]__', '__[123]__', '__[changeset:123 r123]__', '__[changeset:123 r123]__', '__[123:234]__', '__[123:234]__', '__[wiki:WikiStart wiki:WikiStart]__', '__[wiki:WikiStart wiki:WikiStart]__', '__[wiki:WikiStart]__', '__[wiki:WikiStart]__' ].join(" ")); }); unit.add("token + br", function() { var dom = fragment( element("p", "head ", a("http://localhost/", "http://localhost/"), element("br"), "tail"), element("p", "head http://localhost/", element("br"), "tail"), element("p", "head ", element("tt", "teletype"), element("br"), "tail"), element("p", "head ", a("wiki:TracLinks", "TracLinks"), element("br"), "tail"), element("p", "head ", a("http://localhost/", "http://localhost/"), " ", a("wiki:TracLinks", "wiki:TracLinks"), element("br"), "tail"), element("p", "head http://localhost/ wiki:TracLinks", element("br"), "tail")); generateWikitext.call(this, dom, [ "head http://localhost/ [[BR]]tail", "", "head !http://localhost/ [[BR]]tail", "", "head `teletype`[[BR]]tail", "", "head TracLinks[[BR]]tail", "", "head http://localhost/ wiki:TracLinks [[BR]]tail", "", "head !http://localhost/ !wiki:TracLinks [[BR]]tail" ].join("\n")); }); if (window.getSelection) { unit.add("block + br", function() { function br() { return element("br"); } var wikitext = [ "text, br", "", "text'', br[[BR]]''", "", "|| 1,1[[BR]] || || 1,3 ||", "|| || 2,2[[BR]][[BR]] ||", "", " * list, br[[BR]]", " * list, br", " * ", "", "text, br[[BR]]" ].join("\n") generateWikitext.call(this, fragment( element("p", "text, br", br()), element("p", "text", element("i", ", br", br()), br()), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br(), br()), element("td", br()), element("td", "1,3", br())), element("tr", element("td", br()), element("td", "2,2", br(), br(), br())))), element("ul", element("li", "list, br", br(), br()), element("li", "list, br", br()), element("li")), element("p", "text, br", br(), br())), wikitext); generateFragment.call(this, fragment( element("p", "text, br"), element("p", "text", element("i", ", br", br()), br()), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br(), br()), element("td", br()), element("td", "1,3")), element("tr", element("td", br()), element("td", "2,2", br(), br(), br())))), element("ul", element("li", "list, br", br(), br()), element("li", "list, br"), element("li", br())), element("p", "text, br", br(), br())), wikitext); }); } else { unit.add("block + br", function() { function br() { return element("br"); } var wikitext = [ "text, br", "", "text'', br[[BR]]''", "", "|| 1,1[[BR]] || || 1,3 ||", "|| || 2,2[[BR]][[BR]] ||", "", " * list, br[[BR]]", " * list, br", " * ", "", "text, br[[BR]]" ].join("\n") generate.call(this, fragment( element("p", "text, br"), element("p", "text", element("i", ", br", br())), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1,1", br()), element("td"), element("td", "1,3")), element("tr", element("td"), element("td", "2,2", br(), br())))), element("ul", element("li", "list, br", br()), element("li", "list, br"), element("li")), element("p", "text, br", br())), wikitext); }); } unit.add("citation", function() { var dom = fragment( element("blockquote", { "class": "citation" }, element("p", "This is the quoted text continued"), element("blockquote", { "class": "citation" }, element("p", "a nested quote"), element("blockquote", { "class": "citation" }, element("p", "a nested-nested quote")))), element("p", "A comment on the above"), element("blockquote", { "class": "citation" }, element("blockquote", { "class": "citation" }, element("p", "start 2nd level")), element("p", "first level"))); generateFragment.call(this, dom, [ "> This is the quoted text", "> continued", "> > a nested quote", "> > > a nested-nested quote", "A comment on the above", "> > start 2nd level", ">first level" ].join("\n")); generate.call(this, dom, [ "> This is the quoted text continued", "> > a nested quote", "> > > a nested-nested quote", "", "A comment on the above", "", "> > start 2nd level", "> first level" ].join("\n")); }); unit.add("header", function() { var dom = fragment( element("h1", "Heading 1"), element("h2", { id: "anchor-2" }, "Heading 2"), element("h3", element("u", "Heading"), " ", element("i", "3")), element("h4", { id: "アンカー-4" }, "Heading 4 with ", a("wiki:WikiStart", "link")), element("h5", "Heading 5"), element("h6", { id: "anchor-6" }, "Heading 6")); generate.call(this, dom, [ "= Heading 1 =", "== Heading 2 == #anchor-2", "=== __Heading__ ''3'' ===", "==== Heading 4 with [wiki:WikiStart link] ==== #アンカー-4", "===== Heading 5 =====", "====== Heading 6 ====== #anchor-6" ].join("\n")); }); unit.add("list", function() { var dom = fragment( element("p", "Paragraph"), element("ul", element("li", "foo bar boo baz"), element("ul", element("li", "Subitem Subitem line 2")), element("li", "item 2 item 2 line 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " * foo bar", " boo baz", " * Subitem", " Subitem line 2", " * item 2", " item 2 line 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " * foo bar boo baz", " * Subitem Subitem line 2", " * item 2 item 2 line 2", "", "Paragraph" ].join("\n")); }); unit.add("list 2", function() { var dom = fragment( element("ul", element("li", "foo bar boo baz"), element("ul", element("li", "Subitem 1"), element("ul", element("li", "nested item 1"), element("li", "nested item 2 nested item 2 continued")), element("li", "Subitem 2 subitem 2 continued"), element("li", "Subitem 3 subitem 3 continued")), element("li", "item 2 item 2 line 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ " * foo bar", " boo baz", " * Subitem 1", " - nested item 1", " - nested item 2", " nested item 2 continued", " * Subitem 2", " subitem 2 continued", " * Subitem 3", " subitem 3 continued", " * item 2", " item 2 line 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ " * foo bar boo baz", " * Subitem 1", " * nested item 1", " * nested item 2 nested item 2 continued", " * Subitem 2 subitem 2 continued", " * Subitem 3 subitem 3 continued", " * item 2 item 2 line 2", "", "Paragraph" ].join("\n")); }); unit.add("ordered list", function() { var dom = fragment( element("p", "Paragraph"), element("ol", element("li", "item 1"), element("ol", { "class": "arabiczero" }, element("li", "item 1.1"), element("li", "item 1.2"), element("ol", { "class": "loweralpha" }, element("li", "item 1.2.a"), element("li", "item 1.2.b")), element("li", "item 1.3"), element("ol", { "class": "loweralpha" }, element("li", "item 1.3.a"), element("li", "item 1.3.b")), element("li", "item 1.4"), element("ol", { "class": "upperalpha" }, element("li", "item 1.4.A"), element("li", "item 1.4.B"), element("li", "item 1.4.C")), element("li", "item 1.5"), element("ol", { "class": "upperalpha" }, element("li", "item 1.5.A")), element("li", "item 1.6"), element("ol", { "class": "lowerroman" }, element("li", "item 1.6.i"), element("li", "item 1.6.ii")), element("li", "item 1.7"), element("ol", { "class": "upperroman" }, element("li", "item 1.7.I"), element("li", "item 1.7.II")))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " 1. item 1", " 0. item 1.1", " 2. item 1.2", " a. item 1.2.a", " z. item 1.2.b", " a. item 1.3", " b. item 1.3.a", " y. item 1.3.b", " Z. item 1.4", " A. item 1.4.A", " z. item 1.4.B", " z. item 1.4.C", " ii. item 1.5", " C. item 1.5.A", " XVI. item 1.6", " i. item 1.6.i", " x. item 1.6.ii", " 0. item 1.7", " I. item 1.7.I", " III. item 1.7.II", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " 1. item 1", " 0. item 1.1", " 0. item 1.2", " a. item 1.2.a", " a. item 1.2.b", " 0. item 1.3", " a. item 1.3.a", " a. item 1.3.b", " 0. item 1.4", " A. item 1.4.A", " A. item 1.4.B", " A. item 1.4.C", " 0. item 1.5", " A. item 1.5.A", " 0. item 1.6", " i. item 1.6.i", " i. item 1.6.ii", " 0. item 1.7", " I. item 1.7.I", " I. item 1.7.II", "", "Paragraph" ].join("\n")); }); unit.add("list + ordered list", function() { var dom = fragment( element("ul", element("li", "Item 1"), element("ul", element("li", "Item 1.1")), element("li", "Item 2")), element("ol", element("li", "Item 1"), element("ol", { "class": "loweralpha" }, element("li", "Item 1.a"), element("li", "Item 1.b"), element("ol", { "class": "lowerroman" }, element("li", "Item 1.b.i"), element("li", "Item 1.b.ii"))), element("li", "Item 2")), element("p", "And numbered lists can also be given an explicit number:"), element("ol", { start: 3 }, element("li", "Item 3"))); generateFragment.call(this, dom, [ " * Item 1", " * Item 1.1", " * Item 2", " 1. Item 1", " a. Item 1.a", " a. Item 1.b", " i. Item 1.b.i", " i. Item 1.b.ii", " 1. Item 2", "And numbered lists can also be given an explicit number:", " 3. Item 3" ].join("\n")); generate.call(this, dom, [ " * Item 1", " * Item 1.1", " * Item 2", "", " 1. Item 1", " a. Item 1.a", " a. Item 1.b", " i. Item 1.b.i", " i. Item 1.b.ii", " 1. Item 2", "", "And numbered lists can also be given an explicit number:", "", " 3. Item 3" ].join("\n")); }); unit.add("list + code block", function() { var dom = fragment( element("p", "Paragraph"), element("ul", element("li", "item 1", element("pre", { "class": "wiki" }, "code")), element("ul", element("li", "item 1.1", element("pre", { "class": "wiki" }, "code"), "cont.", element("pre", { "class": "wiki" }, "code"))), element("li", "item 2", element("pre", { "class": "wiki" }, "code"))), element("ol", element("li", "item 1"))); generateFragment.call(this, dom, [ "Paragraph", " * item 1", "{{{", "code", "}}}", " * item 1.1", "{{{", "code", "}}}", " cont.", "{{{", "code", "}}}", " * item 2", "{{{", "code", "}}}", " 1. item 1" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " * item 1", "{{{", "code", "}}}", " * item 1.1", "{{{", "code", "}}}", " cont.", "{{{", "code", "}}}", " * item 2", "{{{", "code", "}}}", "", " 1. item 1" ].join("\n")); }); unit.add("list + citation", function() { var dom = fragment( element('ol', element('li', 'item 1')), element('blockquote', { 'class': 'citation' }, element("p", "citation 1")), element('ul', element('li', 'item 2'), element("ol", element('li', 'item 2.1'), element('li', 'item 2.2'))), element('blockquote', { 'class': 'citation' }, element("p", "citation 2 citation 3")), element('ol', element('li', 'item 3'))); generateFragment.call(this, dom, [ ' 1. item 1', '> citation 1', ' * item 2', ' 1. item 2.1', ' 1. item 2.2', '> citation 2', '> citation 3', ' 1. item 3' ].join("\n")); generateWikitext.call(this, dom, [ ' 1. item 1', '', '> citation 1', '', ' * item 2', ' 1. item 2.1', ' 1. item 2.2', '', '> citation 2 citation 3', '', ' 1. item 3' ].join("\n")); }); unit.add("definition", function() { var dom = element("dl", element("dt", "python"), element("dd", "www.python.org :: cont."), element("dt", element("b", "trac")), element("dd", element("b", "trac"), ".edgewall.org cont.", " ", element("tt", "trac-hacks::"), " trac-hacks.org")); generateFragment.call(this, dom, [ " python:: www.python.org :: cont.", " '''trac''':: '''trac'''.edgewall.org", " cont.", " `trac-hacks::` trac-hacks.org" ].join("\n")); generate.call(this, dom, [ " python:: www.python.org :: cont.", " '''trac''':: '''trac'''.edgewall.org cont. `trac-hacks::` trac-hacks.org" ].join("\n")); }); unit.add("blockquote", function() { var dom = fragment( element("p", "Paragraph"), element("blockquote", element("p", "blockquote 1 cont. 1"), element("blockquote", element("p", "blockquote 1.1"), element("blockquote", element("p", "blockquote 1.1.1 cont. 1.1.1")), element("p", "blockquote 1.2")), element("p", "blockquote 2")), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", " blockquote 1", " cont. 1", " blockquote 1.1", " blockquote 1.1.1", " cont. 1.1.1", " blockquote 1.2", " blockquote 2", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", " blockquote 1 cont. 1", " blockquote 1.1", " blockquote 1.1.1 cont. 1.1.1", " blockquote 1.2", " blockquote 2", "", "Paragraph" ].join("\n")); }); unit.add("table", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2")), element("tr", element("td", "2.1")), element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3"), " ", element("tt", "-"))))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||1.1||1.2||", "||2.1", "||3.1||__3.2__||`3` `-`", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| 1.1 || 1.2 ||", "|| 2.1 ||", "|| 3.1 || __3.2__ || `3` `-` ||", "", "Paragraph" ].join("\n")); }); unit.add("table + rule", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1st")))), element("p", element("b", "bold")), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "2nd")))), element("p", "'''normal")); generateFragment.call(this, dom, [ "||1st||", "'''bold'''", "||2nd||", "!'''normal" ].join("\n")); generate.call(this, dom, [ "|| 1st ||", "", "'''bold'''", "", "|| 2nd ||", "", "!'''normal" ].join("\n")); }); unit.add("blockquote + table", function() { var dom = fragment( element("p", "Paragraph"), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "pre.1"), element("td", "pre.2")))), element("blockquote", element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "1.1"), element("td", "1.2")), element("tr", element("td", "2.1")))), element("blockquote", element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "deep"))))), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "3.1"), element("td", element("u", "3.2")), element("td", element("tt", "3.3")))))), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "post.1"), element("td", "post.2")))), element("p", "Paragraph")); generateFragment.call(this, dom, [ "Paragraph", "||pre.1||pre.2||", " ||1.1||1.2||", " ||2.1", " ||deep||", " ||3.1||__3.2__||`3.3`", "||post.1||post.2||", "Paragraph" ].join("\n")); generate.call(this, dom, [ "Paragraph", "", "|| pre.1 || pre.2 ||", "", " || 1.1 || 1.2 ||", " || 2.1 ||", " || deep ||", " || 3.1 || __3.2__ || `3.3` ||", "", "|| post.1 || post.2 ||", "", "Paragraph" ].join("\n")); }); unit.add("table [ paragraph, ul ]", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", element("p", "1.1")), element("td", element("ul", element("li", "item 1"), element("li", "item 2")))), element("tr", element("td", element("p", "2.1"), element("ul", element("li", "item 3"), element("li", "item 4"))))))); generateWikitext.call(this, dom, [ "|| 1.1 || * item 1[[BR]] * item 2 ||", "|| 2.1[[BR]][[BR]] * item 3[[BR]] * item 4 ||" ].join("\n")); }); unit.add("table with incomplete markups", function() { var dom = fragment( element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", element("b", element("i", "'"))), element("td", element("b", "bold"))) ) ) ); generateFragment.call(this, dom, "|| '''''' || '''bold''' ||"); }); unit.add("table from word", function() { var dom = element("div"); dom.innerHTML = [ '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '
', '

a

', '

b

', '
', '', '

b

', '
', '

c

', '
', '', '

d

', '
', '' ].join("\n"); generateWikitext.call(this, dom, [ "|| a[[BR]][[BR]]b || b ||", "|| c || d ||" ].join("\n")); }); unit.add("domToWikitext for code block", function() { var br = function() { return element("br") }; var dom = fragment( element("h1", "Heading", br(), "1"), element("h2", "Heading", br(), "2"), element("h3", "Heading", br(), "3"), element("h4", "Heading", br(), "4"), element("h5", "Heading", br(), "5"), element("h6", "Heading", br(), "6"), element("p", "var TracWysiwyg = function(textarea) {", br(), "...", br(), "}"), element("blockquote", { "class": "citation" }, element("p", "citation", br(), "continued")), element("blockquote", element("p", "quote", br(), "continued")), element("ul", element("li", "item 1", br(), "continued"), element("ol", element("li", "item", br(), "1.1"))), element("dl", element("dt", "def to_s(", br(), ")"), element("dd", "dt", br(), "dd")), element("table", element("tbody", element("tr", element("td", "cell", br(), "1"), element("th", "cell", br(), "2"))))); var wikitext = instance.domToWikitext(dom, { formatCodeBlock: true }); this.assertEqual([ "= Heading 1 =", "== Heading 2 ==", "=== Heading 3 ===", "==== Heading 4 ====", "===== Heading 5 =====", "====== Heading 6 ======", "var TracWysiwyg = function(textarea) {", "...", "}", "", "> citation", "> continued", "", " quote", " continued", "", " * item 1", " continued", " 1. item", " 1.1", "", " def to_s( ):: dt", " dd", "", "|| cell[[BR]]1 || cell[[BR]]2 ||" ].join("\n"), wikitext); }); unit.add("escape newlines", function() { var dom = fragment( element("h1", "header"), element("blockquote", { "class": "citation" }, element("p", br(), "preserve", br(), "newlines", br(), br(), element("i", "(since 0.11)"), br(), br(), br())), element("p", "Whether Wiki formatter should respect the new lines present", br(), "in the Wiki text. If set to ", element("b", "default"), ", this is equivalent to", br(), element("i", "yes"), " for new environments but keeps the old behavior for", br(), "upgraded environments (i.e. 'no')."), element("p", "must_preserve_newlines"), element("ul", element("li", "first", br(), "word"), element("li", "second", br(), "word")), element("dl", element("dt", "trac"), element("dd", "trac.edgewall.org", br(), "trac-hacks.org")), element("table", { "class": "wiki" }, element("tbody", element("tr", element("td", "cell", br(), "cell"))))); generate.call(this, dom, [ "= header =", "> ", "> preserve", "> newlines", "> ", "> ''(since 0.11)''", "> ", "> ", "", "Whether Wiki formatter should respect the new lines present", "in the Wiki text. If set to '''default''', this is equivalent to", "''yes'' for new environments but keeps the old behavior for", "upgraded environments (i.e. 'no').", "", "must_preserve_newlines", "", " * first[[BR]]word", " * second[[BR]]word", "", " trac:: trac.edgewall.org[[BR]]trac-hacks.org", "", "|| cell[[BR]]cell ||" ].join("\n"), { escapeNewlines: true }); }); unit.add("selectRange", function() { var d = instance.contentDocument; function _element() { var args = [ d ]; args.push.apply(args, arguments); return element.apply(this, args); } function _text() { var args = [ d ]; args.push.apply(args, arguments); return text.apply(this, args); } function assertRangeText(expected, start, startOffset, end, endOffset) { instance.selectRange(start, startOffset, end, endOffset); if (expected instanceof RegExp) { unit.assertMatch(expected, instance.getSelectionText()); } else { unit.assertEqual(expected, instance.getSelectionText()); } } var body = d.body; while (body.childNodes.length > 0) { body.removeChild(body.lastChild); } body.appendChild(fragment(d, _element("p", "The", " quick", " brown", _element("b", " fox", " jumps", " over"), " the", " lazy", " dog."), _element("p", "Brick ", "quiz ", "whangs ", "jumpy ", "veldt ", "fox."))); var paragraph1 = body.childNodes[0]; var paragraph2 = body.childNodes[1]; var bold = paragraph1.childNodes[3]; assertRangeText("The", paragraph1.childNodes[0], 0, paragraph1.childNodes[0], 3); assertRangeText("he", paragraph1.childNodes[0], 1, paragraph1.childNodes[0], 3); assertRangeText("e quick brow", paragraph1.childNodes[0], 2, paragraph1.childNodes[2], 5); assertRangeText("ick brown", paragraph1.childNodes[1], 3, paragraph1.childNodes[2], 6); assertRangeText("ick brown fox j", paragraph1.childNodes[1], 3, bold.childNodes[1], 2); assertRangeText("ver the laz", bold.childNodes[2], 2, paragraph1.childNodes[5], 4); assertRangeText(" the lazy", paragraph1.childNodes[4], 0, paragraph1.childNodes[5], 5); assertRangeText("lazy dog.", paragraph1.childNodes[5], 1, paragraph1.childNodes[6], 5); assertRangeText(/^fox jumps over the lazy dog\.[\r\n]*Brick quiz whangs$/, bold.childNodes[0], 1, paragraph2.childNodes[2], 6); assertRangeText(" fox jumps over", paragraph1, 3, paragraph1, 4); assertRangeText(" dog.", paragraph1, 6, paragraph1, 7); assertRangeText("", paragraph1, 7, paragraph1, 7); assertRangeText("quick brown fox jumps over", paragraph1.childNodes[1], 1, paragraph1, 4); assertRangeText(" fox jumps over t", paragraph1, 3, paragraph1.childNodes[4], 2); }); unit.run(); } var button = document.createElement("button"); button.innerHTML = "run »"; button.style.textDecoration = "underline"; document.body.appendChild(button); addEvent(button, "click", run); button.focus(); }); trac-wysiwyg-0.12.0.3+r10725/0.11/tests/testunit.js0000644000175000017500000001527311642336132017343 0ustar wmbwmbTracWysiwyg.TestUnit = function() { this.cases = {}; this.assertCounts = {}; this.current = null; }; (function() { var prototype = TracWysiwyg.TestUnit.prototype; prototype.inspect = function(value) { var type = typeof value; switch (type) { case "string": return value.replace(/[\u0000-\u001f\\\u007f\ufffe\uffff]/g, function(m) { var code = m.charCodeAt(0); switch (code) { case 9: return "\\t"; case 10: return "\\n"; case 11: return "\\v"; case 12: return "\\f"; case 13: return "\\r"; case 92: return "\\\\"; } return "\\u" + (0x10000 + code).toString(16).substring(1); }); break; case "object": case "function": if (value instanceof RegExp) { return value.toString(); } } return "{%}".replace("%", type) + value.toString(); }; prototype.fragment = function() { var start = 0; var arg = arguments[0]; var d; if (arg.nodeType != 9) { d = document; } else { d = arg; start = 1; } var fragment = d.createDocumentFragment(); var length = arguments.length; for (var i = start; i < length; i++) { fragment.appendChild(arguments[i]); } return fragment; }; prototype.element = function(tag) { var start = 0; var arg = arguments[start++]; var d, tag; if (typeof arg == "string") { d = document; tag = arg; } else { d = arg; tag = arguments[start++]; } var element = d.createElement(tag); for (var i = start; i < arguments.length; i++) { arg = arguments[i]; switch (typeof arg) { case "object": if (typeof arg.nodeType == "undefined") { for (var name in arg) { var value = arg[name]; switch (name) { case "id": element.id = value; break; case "class": case "className": element.className = value; break; default: element.setAttribute(name, value); break; } } continue; } break; case "string": arg = d.createTextNode(arg); break; } element.appendChild(arg); } return element; }; prototype.text = function() { var start = 0; var arg = arguments[start++]; var d, text; if (typeof arg == "string") { d = document; text = arg; } else { d = arg; text = arguments[start++]; } return d.createTextNode(text); }; prototype.$ = function(id) { return typeof id == "string" ? document.getElementById(id) : id; }; prototype.add = function(name, method) { if (name in this.cases) { throw "'" + name + "' is in use."; } this.cases[name] = method; this.assertCounts[name] = 0; }; prototype.assertEqual = function(expected, actual, label) { var count = ++this.assertCounts[this.current]; if (typeof (expected) == typeof (actual) && expected == actual) { return true; } throw (label || "") + "[" + count + "]\n" + this.inspect(expected) + " (" + expected.length + ")\n" + this.inspect(actual) + " (" + actual.length + ")"; }; prototype.assertMatch = function(pattern, string, label) { var count = ++this.assertCounts[this.current]; if (pattern.test(string)) { return true; } throw (label || "") + "[" + count + "]\n" + this.inspect(pattern) + "\n" + this.inspect(string) + " (" + string.length + ")"; }; prototype.run = function() { var self = this var $ = this.$, element = this.element, text = this.text; var d = document; var cases = this.cases; var assertCounts = this.assertCounts; var names = []; for (var name in cases) { names.push(name); assertCounts[name] = 0; } var container = $("testunit"); var count; if (container) { container.parentNode.removeChild(container); } container = element( "table", { id: "testunit" }, element("caption", { id: "testunit.summary" }), element("tbody", { id: "testunit.body" })); d.body.appendChild(container); var body = $("testunit.body"); var summary = $("testunit.summary"); for (count = 0; count < names.length; count++) { body.appendChild( element("tr", element("td", names[count]), element("td", { id: "testcase." + count }, "..."))); } count = 0; var success = 0; var invoke = function() { if (count >= names.length) { self.current = null; return; } var current = names[count]; self.current = current; var cell = $("testcase." + count); cell.className = "current"; try { cases[current].call(self); cell.className = "success"; cell.replaceChild(text("OK"), cell.firstChild); success++; } catch (e) { cell.className = "failure"; var message = e.message || e.toString(); if (e.stack) { message = [ message, e.stack ].join("\n\n"); } cell.replaceChild( element("textarea", { id: "testcase." + count + ".textarea", rows: message.split("\n").length, cols: 80, readonly: "readonly" }), cell.firstChild); $("testcase." + count + ".textarea").value = message; } summary.innerHTML = success + " / " + names.length; count++; setTimeout(invoke, 10); }; invoke(); }; })(); trac-wysiwyg-0.12.0.3+r10725/0.11/tests/index.html0000644000175000017500000000401211463324376017120 0ustar wmbwmb tracwysiwyg test
 
trac-wysiwyg-0.12.0.3+r10725/0.11/tests/trac.js0000644000175000017500000000101010714574614016405 0ustar wmbwmbfunction addEvent(element, type, listener) { if (element.addEventListener) { element.addEventListener(type, listener, false); return true; } else if (element.attachEvent) { return element.attachEvent("on" + type, listener); } return false; } function getAncestorByTagName(node, tag) { tag = tag.toLowerCase(); do { node = node.parentNode; } while (node.nodeType == 1 && node.tagName.toLowerCase() != tag); return node.nodeType == 1 ? node : null; } trac-wysiwyg-0.12.0.3+r10725/0.11/MANIFEST.in0000644000175000017500000000014210672463456015523 0ustar wmbwmbinclude tracwysiwyg/htdocs/*.js include tracwysiwyg/htdocs/*.css include tracwysiwyg/htdocs/*.png trac-wysiwyg-0.12.0.3+r10725/0.11/bookmarklet.js0000644000175000017500000000471411314717400016627 0ustar wmbwmb/* * javascript:(function(d,u){var s=d.createElement('script');s.charset='utf-8';s.src=u;d.getElementsByTagName('head')[0].appendChild(s)})(document,'http://trac-hacks.org/svn/tracwysiwygplugin/0.11/bookmarklet.js') */ (function() { var w = window; var d = document; var base = 'http://trac-hacks.org/svn/tracwysiwygplugin/0.11/tracwysiwyg/htdocs/'; var head = d.getElementsByTagName('head')[0]; var script = d.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('charset', 'utf-8'); script.src = base + 'wysiwyg.js'; head.appendChild(script); var link = d.createElement('link'); link.setAttribute('rel', 'stylesheet'); link.setAttribute('type', 'text/css'); link.setAttribute('href', base + 'wysiwyg.css'); head.appendChild(link); function getTracPaths() { var paths = { stylesheets: [] }; var links = head.getElementsByTagName('link'); var length = links.length; for (var i = 0; i < length; i++) { var link = links[i]; var rel = (link.getAttribute('rel') || '').toLowerCase(); var type = (link.getAttribute('type') || '').toLowerCase(); var href = link.getAttribute('href') || ''; switch (rel) { case 'help': if (!paths.base && /\/wiki\/TracGuide$/.test(href)) { paths.base = href.slice(0, -14); } break; case 'search': if (!paths.search && !type && /\/search$/.test(href)) { paths.search = href; paths.base = href.slice(0, -6); } break; case 'stylesheet': if (/\/css\/trac\.css$/.test(href)) { paths.stylesheets.push(href); } break; } } if (paths.base && paths.stylesheets.length > 0) { if (!paths.search) { paths.search = paths.base + 'search'; } paths.stylesheets.push(base + 'editor.css'); return paths; } return null; } function lazy() { switch (typeof w.TracWysiwyg) { case 'undefined': setTimeout(lazy, 100); return; case 'function': TracWysiwyg.getTracPaths = getTracPaths; TracWysiwyg.initialize(); break; } } lazy(); })();