From 7108e0d8613f1d7fcfc7e0b162f30f28a3100dd3 Mon Sep 17 00:00:00 2001 From: Jermolene Date: Fri, 21 Oct 2016 11:27:07 +0100 Subject: [PATCH] Add support for filtered attributes to HTML elements and widgets Fixes #2624 --- core/modules/parsers/parseutils.js | 49 ++++++++------- core/modules/widgets/widget.js | 4 +- .../tiddlers/wikitext/HTML in WikiText.tid | 59 +++++++++++++++---- .../wikitext/HTML_Links_in_WikiText.tid | 17 ++++++ .../tiddlers/wikitext/Widgets in WikiText.tid | 5 +- 5 files changed, 99 insertions(+), 35 deletions(-) create mode 100644 editions/tw5.com/tiddlers/wikitext/HTML_Links_in_WikiText.tid diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 97c994050..0d74355f7 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -218,6 +218,7 @@ exports.parseAttribute = function(source,pos) { // Define our regexps var reAttributeName = /([^\/\s>"'=]+)/g, reUnquotedAttribute = /([^\/\s<>"'=]+)/g, + reFilteredValue = /\{\{\{(.+?)\}\}\}/g, reIndirectValue = /\{\{([^\}]+)\}\}/g; // Skip whitespace pos = $tw.utils.skipWhiteSpace(source,pos); @@ -243,29 +244,37 @@ exports.parseAttribute = function(source,pos) { node.type = "string"; node.value = stringLiteral.value; } else { - // Look for an indirect value - var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue); - if(indirectValue) { - pos = indirectValue.end; - node.type = "indirect"; - node.textReference = indirectValue.match[1]; + // Look for a filtered value + var filteredValue = $tw.utils.parseTokenRegExp(source,pos,reFilteredValue); + if(filteredValue) { + pos = filteredValue.end; + node.type = "filtered"; + node.filter = filteredValue.match[1]; } else { - // Look for a unquoted value - var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute); - if(unquotedValue) { - pos = unquotedValue.end; - node.type = "string"; - node.value = unquotedValue.match[1]; + // Look for an indirect value + var indirectValue = $tw.utils.parseTokenRegExp(source,pos,reIndirectValue); + if(indirectValue) { + pos = indirectValue.end; + node.type = "indirect"; + node.textReference = indirectValue.match[1]; } else { - // Look for a macro invocation value - var macroInvocation = $tw.utils.parseMacroInvocation(source,pos); - if(macroInvocation) { - pos = macroInvocation.end; - node.type = "macro"; - node.value = macroInvocation; - } else { + // Look for a unquoted value + var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute); + if(unquotedValue) { + pos = unquotedValue.end; node.type = "string"; - node.value = "true"; + node.value = unquotedValue.match[1]; + } else { + // Look for a macro invocation value + var macroInvocation = $tw.utils.parseMacroInvocation(source,pos); + if(macroInvocation) { + pos = macroInvocation.end; + node.type = "macro"; + node.value = macroInvocation; + } else { + node.type = "string"; + node.value = "true"; + } } } } diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 5d8b167d1..f4905d433 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -222,7 +222,9 @@ Widget.prototype.computeAttributes = function() { self = this, value; $tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) { - if(attribute.type === "indirect") { + if(attribute.type === "filtered") { + value = self.wiki.filterTiddlers(attribute.filter,self)[0] || ""; + } else if(attribute.type === "indirect") { value = self.wiki.getTextReference(attribute.textReference,"",self.getVariable("currentTiddler")); } else if(attribute.type === "macro") { value = self.getVariable(attribute.value.name,{params: attribute.value.params}); diff --git a/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid index f8575f002..f18aad0d1 100644 --- a/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/HTML in WikiText.tid @@ -1,6 +1,6 @@ caption: HTML created: 20131205160816081 -modified: 20160622112259272 +modified: 20161021102422842 tags: WikiText title: HTML in WikiText type: text/vnd.tiddlywiki @@ -14,25 +14,29 @@ This is my nice and simple block of text. HelloThere ``` +[[Widgets share the same syntax as HTML tags|Widgets in WikiText]], and so the following information applies to them, too. + ! Content Parsing -The content of an HTML element will be parsed in inline mode unless the opening tag is followed by two linebreaks, in which case it is parsed in block mode. (Inline mode means that block mode formatting such as tables, lists and headings is not recognised). +The content of an HTML element will be parsed in inline mode unless the opening tag is followed by two linebreaks, in which case it will be parsed in block mode. (Inline mode means that block mode formatting such as tables, lists and headings is not recognised). ! Attributes -Attributes in HTML tags can be specified as a literal, a transclusion or a macro invocation. For example, here the value of the `href` attribute will be set to the value of the tiddler MyLinkDestination: +In an extension of conventional HTML syntax, attributes of elements/widgets can be specified in several different ways: -``` -link -``` +* a literal string +* a transclusion of a TextReference +* a transclusion of a [[macro/variable|Macros in WikiText]] +* as the result of a [[Filter Expression]] -Note that the link should have the `rel` attribute set to `noopener noreferrer` to maintain privacy of the URLs of private TiddlyWiki's (eg on Dropbox). See https://mathiasbynens.github.io/rel-noopener/ for more information. +!! Literal Attribute Values -Here an attribute is specified as a macro invocation: +Literal attribute values can use several different styles of quoting: -``` -> rel="noopener noreferrer">link -``` +* Single quotes (eg `attr='value'`) +* Double quotes (eg `attr="value"`) +* Tripe double quotes (eg `attr="""value"""`) +* No quoting is necessary for values that do not contain spaces (eg `attr=value`) Literal attribute values can include line breaks. For example: @@ -43,7 +47,7 @@ Rodentville, Ratland."/> ``` -By using triple-double quotes you can specify attribute values that include single double quotes. For example: +By using triple-double quotes you can specify attribute values that contain single double quotes. For example: ```
``` + +!! Transcluded Attribute Values + +Transcluded attribute values are indicated with double curly braces around a TextReference. For example: + +``` +attr={{tiddler}} +attr={{!!field}} +attr={{tiddler!!field}} +``` + +!! Variable Attribute Values + +Variable attribute values are indicated with double angle brackets around a [[macro invocation|Macro Calls in WikiText]]. For example: + +``` +
>> +... +
+``` + +!! Filtered Attribute Values + +Filtered attribute values are indicated with triple curly braces around a [[Filter Expression]]. The value will be the first item in the resulting list, or the empty string if the list is empty. + +This example shows how to add a prefix to a value: + +``` +<$text text={{{ []addPrefix[$:/myprefix/]] }}}> +``` + diff --git a/editions/tw5.com/tiddlers/wikitext/HTML_Links_in_WikiText.tid b/editions/tw5.com/tiddlers/wikitext/HTML_Links_in_WikiText.tid new file mode 100644 index 000000000..99ad2b447 --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/HTML_Links_in_WikiText.tid @@ -0,0 +1,17 @@ +created: 20161021101834041 +modified: 20161021102041147 +tags: [[HTML in WikiText]] +title: HTML Links in WikiText +type: text/vnd.tiddlywiki + +It is often useful to be able to create HTML links to external resources. For example, here the value of the `href` attribute will be set to the value of the tiddler MyLinkDestination: + +``` +link +``` + +However, there is an unexpected security issue that means that most of the time the link should have the `rel` attribute set to `noopener noreferrer` to maintain privacy of the URLs of private TiddlyWiki's (eg on Dropbox). See https://mathiasbynens.github.io/rel-noopener/ for more information. + +``` +link +``` diff --git a/editions/tw5.com/tiddlers/wikitext/Widgets in WikiText.tid b/editions/tw5.com/tiddlers/wikitext/Widgets in WikiText.tid index 97566ab7d..5ef9253c9 100644 --- a/editions/tw5.com/tiddlers/wikitext/Widgets in WikiText.tid +++ b/editions/tw5.com/tiddlers/wikitext/Widgets in WikiText.tid @@ -1,9 +1,9 @@ +caption: Widgets created: 20131205160840915 -modified: 20140619111725471 +modified: 20161020210726813 tags: WikiText title: Widgets in WikiText type: text/vnd.tiddlywiki -caption: Widgets Widgets provide rich functionality within WikiText. They have the same syntax as [[HTML elements|HTML in WikiText]], but the tag name always starts with `$`. For example: @@ -19,6 +19,7 @@ Note that widgets inherit all the features of [[HTML in WikiText]]: ** Strings quoted with triple-double quotes ** Macro invocations (eg `attr=<>`) ** Transclusions (eg, `attr={{MyTiddler!!field}}`) +** Filtered transclusions (eg, `attr={{{ [filter[op]] }}}`) * The content of a widget is parsed in inline mode unless the opening tag is followed by two linebreaks, which forces block mode ** 'Inline mode' means that 'block mode' parse rules like headings, tables and lists are not recognised