diff --git a/core/modules/editor/engines/framed.js b/core/modules/editor/engines/framed.js index a4cf983b0..01b9974c2 100644 --- a/core/modules/editor/engines/framed.js +++ b/core/modules/editor/engines/framed.js @@ -72,6 +72,9 @@ function FramedEngine(options) { if(this.widget.editRows) { this.domNode.setAttribute("rows",this.widget.editRows); } + if(this.widget.editDir) { + this.domNode.setAttribute("dir",this.widget.editDir); + } if(this.widget.editTabIndex) { this.iframeNode.setAttribute("tabindex",this.widget.editTabIndex); } @@ -120,6 +123,7 @@ FramedEngine.prototype.copyStyles = function() { this.domNode.style["-webkit-text-fill-color"] = "currentcolor"; // Ensure we don't force text direction to LTR this.domNode.style.removeProperty("direction"); + this.domNode.style.removeProperty("unicodeBidi"); }; /* diff --git a/core/modules/editor/engines/simple.js b/core/modules/editor/engines/simple.js index 9840cb623..64c087133 100644 --- a/core/modules/editor/engines/simple.js +++ b/core/modules/editor/engines/simple.js @@ -52,6 +52,9 @@ function SimpleEngine(options) { if(this.widget.editTabIndex) { this.domNode.setAttribute("tabindex",this.widget.editTabIndex); } + if(this.widget.editDir) { + this.domNode.setAttribute("dir",this.widget.editDir); + } if(this.widget.editAutoComplete) { this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete); } diff --git a/core/modules/editor/factory.js b/core/modules/editor/factory.js index 6157ec67f..7e43f709b 100644 --- a/core/modules/editor/factory.js +++ b/core/modules/editor/factory.js @@ -183,6 +183,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { this.editFocusSelectFromStart = $tw.utils.parseNumber(this.getAttribute("focusSelectFromStart","0")); this.editFocusSelectFromEnd = $tw.utils.parseNumber(this.getAttribute("focusSelectFromEnd","0")); this.editTabIndex = this.getAttribute("tabindex"); + this.editDir = this.getAttribute("dir"); this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes"; this.editInputActions = this.getAttribute("inputActions"); this.editRefreshTitle = this.getAttribute("refreshTitle"); @@ -220,7 +221,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { EditTextWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Completely rerender if any of our attributes have changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.dir || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) { this.refreshSelf(); return true; } else if (changedTiddlers[this.editRefreshTitle]) { diff --git a/core/modules/parsers/wikiparser/rules/dir.js b/core/modules/parsers/wikiparser/rules/dir.js new file mode 100644 index 000000000..e30fe7a47 --- /dev/null +++ b/core/modules/parsers/wikiparser/rules/dir.js @@ -0,0 +1,51 @@ +/*\ +title: $:/core/modules/parsers/wikiparser/rules/dir.js +type: application/javascript +module-type: wikirule + +Wiki pragma rule for specifying text direction + +``` +\dir rtl +\dir ltr +\dir auto +``` + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.name = "dir"; +exports.types = {pragma: true}; + +/* +Instantiate parse rule +*/ +exports.init = function(parser) { + this.parser = parser; + // Regexp to match + this.matchRegExp = /^\\dir[^\S\n]*(\S+)\r?\n/mg; +}; + +/* +Parse the most recent match +*/ +exports.parse = function() { + var self = this; + // Move past the pragma invocation + this.parser.pos = this.matchRegExp.lastIndex; + // Parse tree nodes to return + return [{ + type: "element", + tag: this.parser.parseAsInline ? "span" : "div", + attributes: { + dir: {type: "string", value: this.match[1]} + }, + children: [] + }]; +}; + +})(); diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index bb457b205..9cdb91913 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -36,6 +36,7 @@ options: see below: */ var WikiParser = function(type,text,options) { this.wiki = options.wiki; + this.parseAsInline = options.parseAsInline; var self = this; // Check for an externally linked tiddler if($tw.browser && (text || "") === "" && options._canonical_uri) { diff --git a/core/modules/widgets/edit.js b/core/modules/widgets/edit.js index e7bd49b93..ce72f0926 100644 --- a/core/modules/widgets/edit.js +++ b/core/modules/widgets/edit.js @@ -48,6 +48,7 @@ EditWidget.prototype.execute = function() { this.editPlaceholder = this.getAttribute("placeholder"); this.editTabIndex = this.getAttribute("tabindex"); this.editFocus = this.getAttribute("focus",""); + this.editDir = this.getAttribute("dir"); this.editCancelPopups = this.getAttribute("cancelPopups",""); this.editInputActions = this.getAttribute("inputActions"); this.editRefreshTitle = this.getAttribute("refreshTitle"); @@ -90,7 +91,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of EditWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Refresh if an attribute has changed, or the type associated with the target tiddler has changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.dir || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { this.refreshSelf(); return true; } else { diff --git a/core/modules/widgets/reveal.js b/core/modules/widgets/reveal.js index 3e3510f75..fde810439 100755 --- a/core/modules/widgets/reveal.js +++ b/core/modules/widgets/reveal.js @@ -42,6 +42,9 @@ RevealWidget.prototype.render = function(parent,nextSibling) { if(this.style) { domNode.setAttribute("style",this.style); } + if(this.direction) { + domNode.setAttribute("dir",this.direction); + } parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); if(!domNode.isTiddlyWikiFakeDom && this.type === "popup" && this.isOpen) { @@ -123,6 +126,7 @@ RevealWidget.prototype.execute = function() { this["default"] = this.getAttribute("default",""); this.animate = this.getAttribute("animate","no"); this.retain = this.getAttribute("retain","no"); + this.direction = this.getAttribute("dir"); this.openAnimation = this.animate === "no" ? undefined : "open"; this.closeAnimation = this.animate === "no" ? undefined : "close"; this.updatePopupPosition = this.getAttribute("updatePopupPosition","no") === "yes"; @@ -214,7 +218,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ RevealWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes.positionAllowNegative || changedAttributes["default"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex) { + if(changedAttributes.state || changedAttributes.type || changedAttributes.text || changedAttributes.position || changedAttributes.positionAllowNegative || changedAttributes["default"] || changedAttributes.animate || changedAttributes.stateTitle || changedAttributes.stateField || changedAttributes.stateIndex || changedAttributes.dir) { this.refreshSelf(); return true; } else { diff --git a/core/templates/single.tiddler.window.tid b/core/templates/single.tiddler.window.tid index aa5175c01..48ce49247 100644 --- a/core/templates/single.tiddler.window.tid +++ b/core/templates/single.tiddler.window.tid @@ -12,7 +12,8 @@ tc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$ tv-config-toolbar-class={{$:/config/Toolbar/ButtonClass}} tv-show-missing-links={{$:/config/MissingLinks}} storyviewTitle={{$:/view}} - languageTitle={{{ [{$:/language}get[name]] }}}> + languageTitle={{{ [{$:/language}get[name]] }}} + tv-text-direction={{$:/config/DefaultTextDirection}}>