mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-26 18:10:27 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
d03f4585f6
@ -27,18 +27,13 @@ exports.init = function(parser) {
|
|||||||
this.matchRegExp = /\[\[(.*?)(?:\|(.*?))?\]\]/mg;
|
this.matchRegExp = /\[\[(.*?)(?:\|(.*?))?\]\]/mg;
|
||||||
};
|
};
|
||||||
|
|
||||||
var isLinkExternal = function(to) {
|
|
||||||
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\s<>{}\[\]`|'"\\^~]+(?:\/|\b)/i;
|
|
||||||
return externalRegExp.test(to);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.parse = function() {
|
exports.parse = function() {
|
||||||
// Move past the match
|
// Move past the match
|
||||||
this.parser.pos = this.matchRegExp.lastIndex;
|
this.parser.pos = this.matchRegExp.lastIndex;
|
||||||
// Process the link
|
// Process the link
|
||||||
var text = this.match[1],
|
var text = this.match[1],
|
||||||
link = this.match[2] || text;
|
link = this.match[2] || text;
|
||||||
if(isLinkExternal(link)) {
|
if($tw.utils.isLinkExternal(link)) {
|
||||||
return [{
|
return [{
|
||||||
type: "element",
|
type: "element",
|
||||||
tag: "a",
|
tag: "a",
|
||||||
|
@ -439,6 +439,12 @@ exports.escapeRegExp = function(s) {
|
|||||||
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
|
return s.replace(/[\-\/\\\^\$\*\+\?\.\(\)\|\[\]\{\}]/g, '\\$&');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Checks whether a link target is external, i.e. not a tiddler title
|
||||||
|
exports.isLinkExternal = function(to) {
|
||||||
|
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\s<>{}\[\]`|'"\\^~]+(?:\/|\b)/i;
|
||||||
|
return externalRegExp.test(to);
|
||||||
|
};
|
||||||
|
|
||||||
exports.nextTick = function(fn) {
|
exports.nextTick = function(fn) {
|
||||||
/*global window: false */
|
/*global window: false */
|
||||||
if(typeof process === "undefined") {
|
if(typeof process === "undefined") {
|
||||||
|
@ -106,8 +106,8 @@ LinkWidget.prototype.renderLink = function(parent,nextSibling) {
|
|||||||
this.domNodes.push(domNode);
|
this.domNodes.push(domNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
LinkWidget.prototype.handleClickEvent = function (event) {
|
LinkWidget.prototype.handleClickEvent = function(event) {
|
||||||
// Send the click on it's way as a navigate event
|
// Send the click on its way as a navigate event
|
||||||
var bounds = this.domNodes[0].getBoundingClientRect();
|
var bounds = this.domNodes[0].getBoundingClientRect();
|
||||||
this.dispatchEvent({
|
this.dispatchEvent({
|
||||||
type: "tm-navigate",
|
type: "tm-navigate",
|
||||||
|
@ -60,16 +60,18 @@ ListWidget.prototype.execute = function() {
|
|||||||
this.variableName = this.getAttribute("variable","currentTiddler");
|
this.variableName = this.getAttribute("variable","currentTiddler");
|
||||||
this.storyViewName = this.getAttribute("storyview");
|
this.storyViewName = this.getAttribute("storyview");
|
||||||
this.historyTitle = this.getAttribute("history");
|
this.historyTitle = this.getAttribute("history");
|
||||||
|
this.iterator = this.getAttribute("iterator","iterator");
|
||||||
// Compose the list elements
|
// Compose the list elements
|
||||||
this.list = this.getTiddlerList();
|
this.list = this.getTiddlerList();
|
||||||
var members = [],
|
var members = [],
|
||||||
self = this;
|
self = this,
|
||||||
|
count = self.list.length;
|
||||||
// Check for an empty list
|
// Check for an empty list
|
||||||
if(this.list.length === 0) {
|
if(0 === count) {
|
||||||
members = this.getEmptyMessage();
|
members = this.getEmptyMessage();
|
||||||
} else {
|
} else {
|
||||||
$tw.utils.each(this.list,function(title,index) {
|
$tw.utils.each(this.list,function(title,index) {
|
||||||
members.push(self.makeItemTemplate(title));
|
members.push(self.makeItemTemplate(title,index,count,self.iterator));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Construct the child widgets
|
// Construct the child widgets
|
||||||
@ -96,7 +98,7 @@ ListWidget.prototype.getEmptyMessage = function() {
|
|||||||
/*
|
/*
|
||||||
Compose the template for a list item
|
Compose the template for a list item
|
||||||
*/
|
*/
|
||||||
ListWidget.prototype.makeItemTemplate = function(title) {
|
ListWidget.prototype.makeItemTemplate = function(title,index,count,iterator) {
|
||||||
// Check if the tiddler is a draft
|
// Check if the tiddler is a draft
|
||||||
var tiddler = this.wiki.getTiddler(title),
|
var tiddler = this.wiki.getTiddler(title),
|
||||||
isDraft = tiddler && tiddler.hasField("draft.of"),
|
isDraft = tiddler && tiddler.hasField("draft.of"),
|
||||||
@ -119,7 +121,15 @@ ListWidget.prototype.makeItemTemplate = function(title) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Return the list item
|
// Return the list item
|
||||||
return {type: "listitem", itemTitle: title, variableName: this.variableName, children: templateTree};
|
return {
|
||||||
|
type: "listitem",
|
||||||
|
itemTitle: title,
|
||||||
|
variableName: this.variableName,
|
||||||
|
children: templateTree,
|
||||||
|
index: index,
|
||||||
|
count: count,
|
||||||
|
iterator: iterator
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -291,8 +301,12 @@ ListItemWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
Compute the internal state of the widget
|
Compute the internal state of the widget
|
||||||
*/
|
*/
|
||||||
ListItemWidget.prototype.execute = function() {
|
ListItemWidget.prototype.execute = function() {
|
||||||
|
var item = this.parseTreeNode;
|
||||||
// Set the current list item title
|
// Set the current list item title
|
||||||
this.setVariable(this.parseTreeNode.variableName,this.parseTreeNode.itemTitle);
|
this.setVariable(item.variableName,item.itemTitle);
|
||||||
|
this.setVariable(item.iterator,(item.index + 1).toString());
|
||||||
|
this.setVariable(item.iterator + "-even",item.index % 2 == 1 ? "true" : "false");
|
||||||
|
this.setVariable(item.iterator + "-last",item.index + 1 == item.count ? "true" : "false");
|
||||||
// Construct the child widgets
|
// Construct the child widgets
|
||||||
this.makeChildWidgets();
|
this.makeChildWidgets();
|
||||||
};
|
};
|
||||||
|
@ -167,7 +167,7 @@ tags: $:/tags/Macro
|
|||||||
<div class="tc-tabbed-table-of-contents-content">
|
<div class="tc-tabbed-table-of-contents-content">
|
||||||
<$reveal state="""$selectedTiddler$""" type="nomatch" text="">
|
<$reveal state="""$selectedTiddler$""" type="nomatch" text="">
|
||||||
<$transclude mode="block" tiddler="$template$">
|
<$transclude mode="block" tiddler="$template$">
|
||||||
<h1><$transclude field="caption"><$view field="title"/></$transclude></h1>
|
<h1><<toc-caption>></h1>
|
||||||
<$transclude mode="block">$missingText$</$transclude>
|
<$transclude mode="block">$missingText$</$transclude>
|
||||||
</$transclude>
|
</$transclude>
|
||||||
</$reveal>
|
</$reveal>
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
caption: Développable
|
||||||
|
created: 20150104182842728
|
||||||
|
modified: 20150104183013132
|
||||||
|
tags: table-of-contents-example
|
||||||
|
title: TableOfContentsMacro Expandable Example
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
!! Table des matières développable
|
||||||
|
|
||||||
|
<$macrocall $name='wikitext-example-without-html'
|
||||||
|
src='<div class="tc-table-of-contents">
|
||||||
|
<<toc-expandable "Contents">>
|
||||||
|
</div>
|
||||||
|
'/>
|
@ -0,0 +1,14 @@
|
|||||||
|
caption: Développable sélectivement
|
||||||
|
created: 20150104182559211
|
||||||
|
modified: 20150104183032161
|
||||||
|
tags: table-of-contents-example
|
||||||
|
title: TableOfContentsMacro Selective Expandable Example
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
!! Table des matières développable sélectivement
|
||||||
|
|
||||||
|
<$macrocall $name='wikitext-example-without-html'
|
||||||
|
src='<div class="tc-table-of-contents">
|
||||||
|
<<toc-selective-expandable "Contents">>
|
||||||
|
</div>
|
||||||
|
'/>
|
@ -0,0 +1,14 @@
|
|||||||
|
caption: Simple
|
||||||
|
created: 20150104182258371
|
||||||
|
modified: 20150104182323524
|
||||||
|
tags: table-of-contents-example
|
||||||
|
title: TableOfContentsMacro Simple Example
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
!! Table des matières simple
|
||||||
|
|
||||||
|
<$macrocall $name='wikitext-example-without-html'
|
||||||
|
src='<div class="tc-table-of-contents">
|
||||||
|
<<toc "Contents">>
|
||||||
|
</div>
|
||||||
|
'/>
|
@ -0,0 +1,14 @@
|
|||||||
|
caption: Développable triée
|
||||||
|
created: 20150104182748334
|
||||||
|
modified: 20150104182956846
|
||||||
|
tags: table-of-contents-example
|
||||||
|
title: TableOfContentsMacro Sorted Expandable Example
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
!! Table des matières développable triée
|
||||||
|
|
||||||
|
<$macrocall $name='wikitext-example-without-html'
|
||||||
|
src='<div class="tc-table-of-contents">
|
||||||
|
<<toc-expandable "Contents" "sort[title]">>
|
||||||
|
</div>
|
||||||
|
'/>
|
@ -0,0 +1,45 @@
|
|||||||
|
caption: Tabbed
|
||||||
|
created: 20150104183128274
|
||||||
|
modified: 20150104222928663
|
||||||
|
tags: table-of-contents-example
|
||||||
|
title: TableOfContentsMacro Tabbed Example
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
!! Table des matières tabulée
|
||||||
|
|
||||||
|
La variante tabulée de la macro table des matières affiche une table des matières développable sélectivement à côté d'un panneau qui affiche le tiddler en cours de sélection.
|
||||||
|
|
||||||
|
!!! Paramètres
|
||||||
|
|
||||||
|
|!Position |!Nom |!Description |!Défaut |
|
||||||
|
|1^^re^^ |tag |Tag à utiliser pour construire la table des matières | |
|
||||||
|
|2^^e^^ |sort |Sous-filtre de tri optionnel (par exemple `sort[title]`) | |
|
||||||
|
|3^^e^^ |selectedTiddler |Titre du tiddler contenant le titre du tiddler en cours d'affichage |"$:/temp/toc/selectedTiddler" |
|
||||||
|
|4^^e^^ |unselectedText |Texte à afficher lorsqu'aucun tiddler n'est sélectionné | |
|
||||||
|
|5^^e^^ |missingText |Texte à afficher quand le tiddler sélectionné est manquant | |
|
||||||
|
|6^^e^^ |template |Titre optionnel d'un tiddler à utiliser comme template pour le rendu du tiddler sélectionné | |
|
||||||
|
|
||||||
|
!!! Navigation interne
|
||||||
|
|
||||||
|
Cet exemple montre comment construire une table des matières tabulée avec navigation interne, de sorte que cliquer sur les liens du tiddler en cours d'affichage remplacera le tiddler en question.
|
||||||
|
|
||||||
|
```
|
||||||
|
<<toc-tabbed-internal-nav tag:"TableOfContents" selectedTiddler:"$:/temp/toc/selectedTiddler" unselectedText:"Choisissez un sujet dans la table des matières. Cliquez sur la flèche pour développer un sujet.">>
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Navigation externe
|
||||||
|
|
||||||
|
Cet exemple montre comment construire une table des matières tabulée avec navigation externe, de sorte que cliquer sur les liens du tiddler en cours d'affichage ouvrira les tiddlers référencés dans le déroulé principal, selon la manière habituelle.
|
||||||
|
|
||||||
|
```
|
||||||
|
<<toc-tabbed-external-nav tag:"TableOfContents" selectedTiddler:"$:/temp/toc/selectedTiddler" unselectedText:"Choisissez un sujet dans la table des matières. Cliquez sur la flèche pour développer un sujet.">>
|
||||||
|
```
|
||||||
|
|
||||||
|
!! Exemple
|
||||||
|
|
||||||
|
Type<<:>> <$select tiddler="TabbedExampleType">
|
||||||
|
<option value="toc-tabbed-internal-nav">Ouvre les liens du tiddler affiché dans le même espace (toc-tabbed-internal-nav)</option>
|
||||||
|
<option value="toc-tabbed-external-nav">Ouvre les liens du tiddler affiché hors de son espace (toc-tabbed-external-nav)</option>
|
||||||
|
</$select>
|
||||||
|
|
||||||
|
<$macrocall $name={{TabbedExampleType}} tag="TableOfContents" selectedTiddler="$:/temp/toc/selectedTiddler" unselectedText="<p>Choisissez un sujet dans la table des matières. Cliquez sur la flèche pour développer un sujet.</p>" missingText="<p>Tiddler manquant.</p>"/>
|
51
editions/fr-FR/tiddlers/TableOfContentsMacro.tid
Normal file
51
editions/fr-FR/tiddlers/TableOfContentsMacro.tid
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
caption: toc
|
||||||
|
created: 20140919155729620
|
||||||
|
modified: 20150105102807522
|
||||||
|
tags: Macros
|
||||||
|
title: TableOfContentsMacro
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
La macro //~TableOfContents// (Table des Matières) produit une arborescence hiérarchique de tiddlers, en se basant sur leurs tags.
|
||||||
|
|
||||||
|
Les entrées de premier niveau de la table des matières sont définies par un tag racine. Les sous-entrées de chacune de ces entrées sont taguées avec le titre de l'entrée. Les entrées peuvent être triées à l'aide du champ `list` du tiddler de tag correspondant, comme décrit dans [[Tagging]].
|
||||||
|
|
||||||
|
Le libellé utilisé pour chaque entrée est tiré du champ ''caption'' s'il est présent<<;>> dans le cas contraire, c'est le titre (champ ''title'') qui est utilisé.
|
||||||
|
|
||||||
|
Les entrées sont affichées sous forme de liens vers le tiddler correspondant, à moins que le tiddler contienne un champ ''toc-link'' avec la valeur ''no''. Dans les exemples ci-dessous, l'entrée SecondThree est configurée ainsi, de manière à ne pas apparaître comme un lien.
|
||||||
|
|
||||||
|
Il existe plusieurs variantes de cette macro<<:>>
|
||||||
|
|
||||||
|
* `<<toc>>` produit une arborescence hiérarchique de liens simple
|
||||||
|
* `<<toc-expandable>>` produit une arborescence de liens développable
|
||||||
|
* `<<toc-selective-expandable>>` produit une arborescence de liens développable où les boutons développer / contracter ne sont affichés que pour les entrées qui possèdent des nœuds fils
|
||||||
|
|
||||||
|
Les macros génèrent des listes HTML ordonnées. Les éléments `<ol>` bénéficient de la classe `tc-toc`, ceux de la variante //expandable// bénéficiant également de la classe `tc-toc-expandable` tandis que ceux de la variante //selective expandable// bénéficient de la classe `tc-toc-selective-expandable`.
|
||||||
|
|
||||||
|
! Paramètres
|
||||||
|
|
||||||
|
|!Position |!Nom |!Description |!Défaut |
|
||||||
|
|1^^re^^ |tag |Le tag racine qui identifie le premier niveau de la hiérachie | |
|
||||||
|
|2^^e^^ |sort |Sous-fitre optionnel de tri (par exemple `sort[title]`) | |
|
||||||
|
|
||||||
|
Les paramètres ''tag'' et ''sort'' sont combinés pour construire une expression de filtre de la forme<<:>>
|
||||||
|
|
||||||
|
```
|
||||||
|
[tag[$tag$]$sort$]
|
||||||
|
```
|
||||||
|
|
||||||
|
! Exemples
|
||||||
|
|
||||||
|
Dans les exemples suivants, les entrées de premier niveau de la table des matières sont définies par leur tag racine ''Contents''. Les sous-entrées sous chacune de ces entrées sont taguées avec le titre de leur parent, ici ''First'', ''Second'', ''Third'', et ''Fourth''. Au niveau du dessous, seul ''~SecondThree'' comporte des sous-entrées.
|
||||||
|
|
||||||
|
Voici la structure des tags, affichée à l'aide de pastilles de tag cliquables<<:>>
|
||||||
|
|
||||||
|
{{Contents||$:/core/ui/TagTemplate}}
|
||||||
|
*{{First||$:/core/ui/TagTemplate}}
|
||||||
|
*{{Second||$:/core/ui/TagTemplate}}
|
||||||
|
**{{SecondThree||$:/core/ui/TagTemplate}}
|
||||||
|
*{{Third||$:/core/ui/TagTemplate}}
|
||||||
|
*{{Fourtth||$:/core/ui/TagTemplate}}
|
||||||
|
|
||||||
|
Pour des instructions sur la manière d'ajouter une table des matières dans la barre latérale, voyez<<:>> [[Comment ajouter un nouvel onglet dans la barre latérale|How to add a new tab to the sidebar]].
|
||||||
|
|
||||||
|
<<tabs "[tag[table-of-contents-example]]" "TableOfContentsMacro Simple Example">>
|
@ -4,7 +4,7 @@ tags: documenting
|
|||||||
|
|
||||||
Each of the main words of a tiddler title begins with a capital letter, but minor words such as "and", "or", "the", "to" and "with" do not. Avoid starting a tiddler with the word "the".
|
Each of the main words of a tiddler title begins with a capital letter, but minor words such as "and", "or", "the", "to" and "with" do not. Avoid starting a tiddler with the word "the".
|
||||||
|
|
||||||
[[Reference Tiddlers]] have ~CamelCase nouns as their titles, e.g. ''~RevealWidget'', ''~CamelCase'', ''CSS''. The title is plural if it denotes a category, e.g. ''~KeyboardShorcuts'', ''~TiddlerFields''. Such categories are used to tag more specific tiddlers within the category.
|
[[Reference Tiddlers]] have ~CamelCase nouns as their titles, e.g. ''~RevealWidget'', ''~CamelCase'', ''CSS''. The title is plural if it denotes a category, e.g. ''~KeyboardShortcuts'', ''~TiddlerFields''. Such categories are used to tag more specific tiddlers within the category.
|
||||||
|
|
||||||
Other tags usually consist of a single lowercase word. Avoid spaces in tags.
|
Other tags usually consist of a single lowercase word. Avoid spaces in tags.
|
||||||
|
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
created: 20141122093837330
|
created: 20141122093837330
|
||||||
modified: 20141122093837330
|
modified: 20141122093837330
|
||||||
tags: Resources
|
tags: Resources
|
||||||
title: "Taskgraph Plugin" by Felix Küppers
|
title: TiddlyMap Plugin by Felix Küppers
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
url: http://wkpr.de/hosting/tmp/tw5/taskgraph/
|
url: http://bit.ly/tiddlymap
|
||||||
|
|
||||||
An interactive network visualisation plugin based on [[Vis.js|http://visjs.org]].
|
An interactive network visualisation plugin based on [[Vis.js|http://visjs.org]]. A demo can be found here: {{!!url}}.
|
||||||
|
|
||||||
{{!!url}}
|
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
TW-Taskgraph is a TiddlyWiki plugin that allows you to link your wiki-topics (tiddlers) in order to create clickable graphs. By creating relations between your topics you can easily do the following:
|
~TiddlyMap is a TiddlyWiki plugin that allows you to link your wiki-topics (tiddlers) in order to create clickable graphs. By creating relations between your topics you can easily do the following:
|
||||||
|
|
||||||
* Create mindmaps and quickly manifest your ideas in tiddlers (wiki entries).
|
* Create mindmaps and quickly manifest your ideas in tiddlers (wiki entries).
|
||||||
* Create task-dependency graphs to organize and describe your tasks.
|
* Create task-dependency graphs to organize and describe your tasks.
|
15
editions/tw5.com/tiddlers/concepts/RailroadDiagrams.tid
Normal file
15
editions/tw5.com/tiddlers/concepts/RailroadDiagrams.tid
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
created: 20150105133800000
|
||||||
|
modified: 20150105134300000
|
||||||
|
title: RailroadDiagrams
|
||||||
|
|
||||||
|
Railroad diagrams, sometimes called syntax diagrams, are a visual way of explaining the syntax rules of a computer language. Reading one is like reading a public transport map.
|
||||||
|
|
||||||
|
Each diagram starts on the left and ends on the right. Simply follow any line from the startpoint to the endpoint. All the alternative lines are equally valid. A line will sometimes jump over an item that is optional, or loop back to indicate that an item can be repeated.
|
||||||
|
|
||||||
|
<$railroad text="""
|
||||||
|
start [:optional] {repeated +","} end
|
||||||
|
"""/>
|
||||||
|
|
||||||
|
Characters in round boxes are literal, i.e. they denote themselves. A name in a rectangular box denotes a further railroad diagram.
|
||||||
|
|
||||||
|
The railroad diagrams on this site are generated using the [[Railroad Plugin]].
|
@ -4,11 +4,11 @@ tags: Learning
|
|||||||
title: Introduction to Filters
|
title: Introduction to Filters
|
||||||
type: text/vnd.tiddlywiki
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
A step by step introduction to how [[Filters]] are used.
|
This is a step-by-step introduction to how [[Filters]] are used. [[Filter Syntax]] presents a more technical summary of this information.
|
||||||
|
|
||||||
! Using Filters
|
! Using Filters
|
||||||
|
|
||||||
Filters are a special language within WikiText for expressing lists of tiddlers.
|
Filters are a special notation for expressing lists of tiddlers within WikiText.
|
||||||
|
|
||||||
Filters are used in the ListMacro, TabsMacro, ListWidget, CountWidget, and many other areas of TiddlyWiki.
|
Filters are used in the ListMacro, TabsMacro, ListWidget, CountWidget, and many other areas of TiddlyWiki.
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ For example, this is how the ListMacro would be used to display the first examp
|
|||||||
<<list-links "HelloThere Introduction [[Title with Spaces]]">>
|
<<list-links "HelloThere Introduction [[Title with Spaces]]">>
|
||||||
```
|
```
|
||||||
|
|
||||||
The easiest way to experiment with tiddler filters is by typing them into the "Filter" tab of the [[advanced search panel|$:/AdvancedSearch]].
|
The easiest way to experiment with tiddler filters is by typing them into the ''Filter'' tab of the [[advanced search panel|$:/AdvancedSearch]].
|
||||||
|
|
||||||
! Simple Filters
|
! Simple Filters
|
||||||
|
|
||||||
@ -32,13 +32,13 @@ The titles must be separated by one or more spaces and/or linebreaks.
|
|||||||
|
|
||||||
! Filter Operators
|
! Filter Operators
|
||||||
|
|
||||||
Filter operators are used to select tiddlers based on some criteria. For example, this filter consists of a single operation that selects all tiddlers tagged "introduction":
|
Filter operators are used to select tiddlers in particular ways. For example, this filter consists of a single step that selects all tiddlers tagged ''introduction'':
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]]
|
[tag[introduction]]
|
||||||
```
|
```
|
||||||
|
|
||||||
The word "tag" is the ''operator'' and "introduction" is the ''operand''.
|
The word `tag` is the ''operator'' and `introduction` is the ''parameter'' (sometimes called the ''operand'').
|
||||||
|
|
||||||
See [[Filters]] for a complete list of the available operators.
|
See [[Filters]] for a complete list of the available operators.
|
||||||
|
|
||||||
@ -46,9 +46,9 @@ See [[Filters]] for a complete list of the available operators.
|
|||||||
|
|
||||||
The operator defaults to `title` if omitted, so `[[HelloThere]]` is equivalent to `[title[HelloThere]]`. If there are no spaces in the title, then the double square brackets can also be omitted: `HelloThere`.
|
The operator defaults to `title` if omitted, so `[[HelloThere]]` is equivalent to `[title[HelloThere]]`. If there are no spaces in the title, then the double square brackets can also be omitted: `HelloThere`.
|
||||||
|
|
||||||
! Negating Filter Operators
|
! Negating Filter Steps
|
||||||
|
|
||||||
Filter operations can be negated by preceding the operator with an exclamation mark (!). This example selects all tiddlers that are not tagged "introduction":
|
A filter step can be negated by preceding the operator with an exclamation mark (`!`). This example selects all tiddlers that are not tagged ''introduction'':
|
||||||
|
|
||||||
```
|
```
|
||||||
[!tag[introduction]]
|
[!tag[introduction]]
|
||||||
@ -56,7 +56,7 @@ Filter operations can be negated by preceding the operator with an exclamation m
|
|||||||
|
|
||||||
! Operator Suffixes
|
! Operator Suffixes
|
||||||
|
|
||||||
Some filter operators can take an optional suffix that provides further information for the operation. For example, the "field" operator takes a suffix indicating the field to be compared. The following filter returns all tiddlers that have "JeremyRuston" in the "modifier" field:
|
Some filter operators can take an optional suffix that provides further information. For example, the `field` operator takes a suffix indicating the field to be compared. The following filter returns all tiddlers that have ''JeremyRuston'' in the `modifier` field:
|
||||||
|
|
||||||
```
|
```
|
||||||
[field:modifier[JeremyRuston]]
|
[field:modifier[JeremyRuston]]
|
||||||
@ -64,70 +64,72 @@ Some filter operators can take an optional suffix that provides further informat
|
|||||||
|
|
||||||
! Field Operator Shortcut
|
! Field Operator Shortcut
|
||||||
|
|
||||||
If an unknown operator is used then it is instead interpreted as the suffix of the "field" operator. Thus, these two filters both return all the tiddlers that contain the string "create" in their "caption" field:
|
If an operator is not recognised, then it is instead interpreted as the suffix of the `field` operator. Thus, these two filters both return all the tiddlers that contain the string ''create'' in their `caption` field:
|
||||||
|
|
||||||
```
|
```
|
||||||
[caption[create]]
|
[caption[create]]
|
||||||
[field:caption[create]]
|
[field:caption[create]]
|
||||||
```
|
```
|
||||||
|
|
||||||
! Indirect Operands
|
! Indirect Parameters
|
||||||
|
|
||||||
If a filter operator is written with curly brackets around the operand then it is taken to be a TextReference to the actual value. For example, this filter selects all tiddlers containing the string contained in the tiddler titled "$:/temp/search"
|
If a filter step has curly brackets around its parameter, then it is taken to be a TextReference to the actual value. For example, this filter selects all tiddlers containing the string contained in the ''$:/temp/search'' tiddler:
|
||||||
|
|
||||||
```
|
```
|
||||||
[search{$:/temp/search}]
|
[search{$:/temp/search}]
|
||||||
```
|
```
|
||||||
|
|
||||||
! Variable Operands
|
! Variable Parameters
|
||||||
|
|
||||||
If a filter operator is written with angle brackets around the operand then it is taken to be the name of a variable containing the actual value. For example, this filter selects all tiddlers containing the title of the current tiddler:
|
If a filter step has angle brackets around its parameter, then it is taken to be the name of a variable containing the actual value. For example, this filter selects all tiddlers containing the title of the current tiddler:
|
||||||
|
|
||||||
```
|
```
|
||||||
[search<currentTiddler>]
|
[search<currentTiddler>]
|
||||||
```
|
```
|
||||||
|
|
||||||
(Note that the `currentTiddler` variable is used to track the current tiddler).
|
(The built-in `currentTiddler` variable keeps track of which tiddler is the current one.)
|
||||||
|
|
||||||
! ORing Multiple Filter Operators
|
! ORing Multiple Filter Steps
|
||||||
|
|
||||||
You can use multiple filter operations at once. This example selects all tiddlers that are either tagged "introduction" or "demo":
|
You can use multiple filter steps at once. If you write the steps separately, the overall result is the set of tiddlers that match //any// of the steps. Each step is processed separately, adding its tiddlers to the overall result.
|
||||||
|
|
||||||
|
This example selects all tiddlers that are either tagged ''introduction'' or ''demo'':
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]] [tag[demo]]
|
[tag[introduction]] [tag[demo]]
|
||||||
```
|
```
|
||||||
|
|
||||||
Each separate operator is processed in turn, accumulating the tiddlers that they select.
|
Here's an example that returns tiddlers tagged ''alpha'' or ''beta'' that are also tagged ''task'' but not tagged ''done'':
|
||||||
|
|
||||||
Here's an example that returns tiddlers tagged ''alpha'' or ''beta'' that are also tagged ''task'' and not tagged ''done'':
|
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[alpha]] [tag[beta]] +[tag[task]!tag[done]]
|
[tag[alpha]] [tag[beta]] +[tag[task]!tag[done]]
|
||||||
```
|
```
|
||||||
|
|
||||||
! ANDing Multiple Filter Operators
|
! ANDing Multiple Filter Steps
|
||||||
|
|
||||||
A sequence of operators can be logically ANDed together by bashing them together and merging the outer square brackets. This is called a "run" of operations. For example, here we select tiddlers that are tagged "introduction" and also tagged "demo":
|
A sequence of steps can also be combined by bashing them together and merging the outer square brackets. This is called a "run". The result is the set of tiddlers that match //all// of the steps in the run.
|
||||||
|
|
||||||
|
For example, here we select tiddlers that are tagged ''introduction'' and also tagged ''demo'':
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]tag[demo]]
|
[tag[introduction]tag[demo]]
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's another example that selects all tiddlers tagged "introduction" that are not tagged "demo":
|
Here's another example that selects all tiddlers tagged ''introduction'' that are //not// tagged ''demo'':
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]!tag[demo]]
|
[tag[introduction]!tag[demo]]
|
||||||
```
|
```
|
||||||
|
|
||||||
! Negating Runs of Filter Operators
|
! Negating Runs
|
||||||
|
|
||||||
Ordinarily, each run of filter operations adds to the accumulated results. Prefixing a run with `-` causes the list of tiddlers to instead be removed from the results. For example, this example returns all the tiddlers tagged "introduction" apart from `HelloThere` and `Title with Spaces`:
|
Ordinarily, each run //adds// to the accumulated results. Prefixing a run with `-` instead causes the list of tiddlers selected to be //removed// from the results. For example, this example returns all the tiddlers tagged ''introduction'', apart from `HelloThere` and `Title with Spaces`:
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]] -HelloThere -[[Title with Spaces]]
|
[tag[introduction]] -HelloThere -[[Title with Spaces]]
|
||||||
```
|
```
|
||||||
|
|
||||||
This example returns all tiddlers tagged "introduction" that are not also tagged "demo":
|
This example returns all tiddlers tagged ''introduction'' that are not also tagged ''demo'':
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]] -[tag[demo]]
|
[tag[introduction]] -[tag[demo]]
|
||||||
@ -135,9 +137,9 @@ This example returns all tiddlers tagged "introduction" that are not also tagged
|
|||||||
|
|
||||||
! Working with Filter Results
|
! Working with Filter Results
|
||||||
|
|
||||||
Usually, each run of filter operations takes as its source the entire store of available tiddlers. Prefixing a run with `+` causes the accumulated results to be used as the source instead.
|
Usually, each run takes the entire store of available tiddlers as its source. Prefixing a run with `+` causes the results so far accumulated to be used as the source instead.
|
||||||
|
|
||||||
For example, this filter selects tiddlers tagged "introduction" or "demo" and then sorts the resulting list by the "title" field:
|
For example, this filter selects tiddlers tagged ''introduction'' or ''demo'', and then sorts the resulting list by the `title` field:
|
||||||
|
|
||||||
```
|
```
|
||||||
[tag[introduction]] [tag[demo]] +[sort[title]]
|
[tag[introduction]] [tag[demo]] +[sort[title]]
|
||||||
|
7
editions/tw5.com/tiddlers/plugins/Railroad Plugin.tid
Normal file
7
editions/tw5.com/tiddlers/plugins/Railroad Plugin.tid
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
title: Railroad Plugin
|
||||||
|
modified: 20150105134500000
|
||||||
|
tags: Plugins
|
||||||
|
|
||||||
|
{{$:/plugins/tiddlywiki/railroad/readme}}
|
||||||
|
|
||||||
|
{{$:/plugins/tiddlywiki/railroad/syntax}}
|
@ -89,13 +89,13 @@ Component.prototype.debug = function(output,indent) {
|
|||||||
Component.prototype.debugArray = function(array,output,indent) {
|
Component.prototype.debugArray = function(array,output,indent) {
|
||||||
for(var i=0; i<array.length; i++) {
|
for(var i=0; i<array.length; i++) {
|
||||||
var item = array[i];
|
var item = array[i];
|
||||||
// Choice content is a special case: an array of arrays
|
// Choice content is a special case: we number the branches
|
||||||
if(item.isChoiceBranch) {
|
if(item.isChoiceBranch) {
|
||||||
output.push(indent);
|
output.push(indent);
|
||||||
output.push("(");
|
output.push("(");
|
||||||
output.push(i);
|
output.push(i);
|
||||||
output.push(")\n");
|
output.push(")\n");
|
||||||
item.debug(output," " +indent);
|
item.debug(output," "+indent);
|
||||||
} else {
|
} else {
|
||||||
item.debug(output,indent);
|
item.debug(output,indent);
|
||||||
}
|
}
|
||||||
@ -205,6 +205,27 @@ Repeated.prototype.toSvg = function() {
|
|||||||
return railroad.OneOrMore(this.child.toSvg(),separatorSvg);
|
return railroad.OneOrMore(this.child.toSvg(),separatorSvg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Link = function(content,options) {
|
||||||
|
this.initialiseWithChild("Link",content);
|
||||||
|
this.options = options;
|
||||||
|
};
|
||||||
|
|
||||||
|
Link.prototype = new Component();
|
||||||
|
|
||||||
|
Link.prototype.toSvg = function() {
|
||||||
|
return railroad.Link(this.child.toSvg(),this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
var Transclusion = function(content) {
|
||||||
|
this.initialiseWithChild("Transclusion",content);
|
||||||
|
};
|
||||||
|
|
||||||
|
Transclusion.prototype = new Component();
|
||||||
|
|
||||||
|
Transclusion.prototype.toSvg = function() {
|
||||||
|
return this.child.toSvg();
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////// Components with an array of children
|
/////////////////////////// Components with an array of children
|
||||||
|
|
||||||
var Root = function(content) {
|
var Root = function(content) {
|
||||||
@ -252,13 +273,15 @@ exports.components = {
|
|||||||
Choice: Choice,
|
Choice: Choice,
|
||||||
Comment: Comment,
|
Comment: Comment,
|
||||||
Dummy: Dummy,
|
Dummy: Dummy,
|
||||||
|
Link: Link,
|
||||||
Nonterminal: Nonterminal,
|
Nonterminal: Nonterminal,
|
||||||
Optional: Optional,
|
Optional: Optional,
|
||||||
OptionalRepeated: OptionalRepeated,
|
OptionalRepeated: OptionalRepeated,
|
||||||
Repeated: Repeated,
|
Repeated: Repeated,
|
||||||
Root: Root,
|
Root: Root,
|
||||||
Sequence: Sequence,
|
Sequence: Sequence,
|
||||||
Terminal: Terminal
|
Terminal: Terminal,
|
||||||
|
Transclusion: Transclusion
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
@ -5,5 +5,5 @@ title: $:/plugins/tiddlywiki/railroad/example-source
|
|||||||
type: text/plain
|
type: text/plain
|
||||||
|
|
||||||
["+"]
|
["+"]
|
||||||
({digit} | "#" <'escape sequence'>)
|
({ [[digit|GettingStarted]] } | "#" <'escape sequence'>)
|
||||||
[{("@" name-char | :"--" )}]
|
[{("@" name-char | :"--" )}]
|
@ -8,7 +8,7 @@ title: $:/plugins/tiddlywiki/railroad/example
|
|||||||
```
|
```
|
||||||
<$railroad text="""
|
<$railroad text="""
|
||||||
["+"]
|
["+"]
|
||||||
({digit} | "#" <'escape sequence'>)
|
({ [[digit|GettingStarted]] } | "#" <'escape sequence'>)
|
||||||
[{("@" name-char | :"--" )}]
|
[{("@" name-char | :"--" )}]
|
||||||
"""/>
|
"""/>
|
||||||
```
|
```
|
||||||
|
@ -2,7 +2,7 @@ created: 20150102163222184
|
|||||||
modified: 20150102172016663
|
modified: 20150102172016663
|
||||||
title: $:/plugins/tiddlywiki/railroad/readme
|
title: $:/plugins/tiddlywiki/railroad/readme
|
||||||
|
|
||||||
This plugin provides a `<$railroad>` widget for generating railroad syntax diagrams as SVG images. It is based on [[a library by Tab Atkins|https://github.com/tabatkins/railroad-diagrams]].
|
This plugin provides a `<$railroad>` widget for generating railroad syntax diagrams as SVG images. It is based on [[a library by Tab Atkins|https://github.com/tabatkins/railroad-diagrams]], and has been extended to allow components of a diagram to function as links.
|
||||||
|
|
||||||
The content of the `<$railroad>` widget is ignored.
|
The content of the `<$railroad>` widget is ignored.
|
||||||
|
|
||||||
@ -10,8 +10,10 @@ The content of the `<$railroad>` widget is ignored.
|
|||||||
|text |Text in a special syntax that defines the diagram's layout |
|
|text |Text in a special syntax that defines the diagram's layout |
|
||||||
|mode |If set to `debug`, the diagram will display its internal tree structure. The default mode is `svg` |
|
|mode |If set to `debug`, the diagram will display its internal tree structure. The default mode is `svg` |
|
||||||
|
|
||||||
The `text` can be transcluded from another tiddler:
|
The entire `text` can be transcluded from another tiddler:
|
||||||
|
|
||||||
```
|
```
|
||||||
<$railroad tiddler={{diagram}}>
|
<$railroad tiddler={{diagram}}>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Alternatively, the diagram syntax allows specific parts of the `text` to be transcluded from other tiddlers.
|
@ -2,10 +2,12 @@ created: 20150103184022184
|
|||||||
modified: 20150103184022184
|
modified: 20150103184022184
|
||||||
title: $:/plugins/tiddlywiki/railroad/syntax
|
title: $:/plugins/tiddlywiki/railroad/syntax
|
||||||
|
|
||||||
The railroad widget constructs a diagram from the components defined below.
|
The railroad widget uses a special ''diagram syntax'' to construct the components defined below.
|
||||||
|
|
||||||
`x` and `y` here stand for any component.
|
`x` and `y` here stand for any component.
|
||||||
|
|
||||||
|
Names (as opposed to quoted strings) are available when a value starts with a letter and contains only letters, digits, underscores, dots and hyphens.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
; sequence
|
; sequence
|
||||||
@ -52,7 +54,6 @@ The railroad widget constructs a diagram from the components defined below.
|
|||||||
; nonterminal
|
; nonterminal
|
||||||
: <$railroad text=""" (name | "<" string ">") """/>
|
: <$railroad text=""" (name | "<" string ">") """/>
|
||||||
* A nonterminal component, i.e. the name of another diagram
|
* A nonterminal component, i.e. the name of another diagram
|
||||||
* The simple `name` option is available when the text starts with a letter and contains only letters, digits, underscores, dots and hyphens
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -65,3 +66,15 @@ The railroad widget constructs a diagram from the components defined below.
|
|||||||
; dummy
|
; dummy
|
||||||
: <$railroad text=""" "-" """/>
|
: <$railroad text=""" "-" """/>
|
||||||
* The absence of a component
|
* The absence of a component
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
; link
|
||||||
|
: <$railroad text=""" "[[" x "|" (name|string) "]]" """/>
|
||||||
|
* A link to the tiddler title or URI given by the string or name
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
; transclusion
|
||||||
|
: <$railroad text=""" "{{" (name|string) "}}" """/>
|
||||||
|
* Treats the content of another tiddler as diagram syntax and transcludes it into the current diagram
|
||||||
|
@ -467,15 +467,16 @@ var temp = (function(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TiddlyWiki: added linking ability */
|
/* TiddlyWiki: added linking ability */
|
||||||
function Link(target, item) {
|
function Link(item,options) {
|
||||||
if(!(this instanceof Link)) return new Link(target, item);
|
if(!(this instanceof Link)) return new Link(item,options);
|
||||||
FakeSVG.call(this, 'a', {'xlink:href': target});
|
FakeSVG.call(this,'a',options);
|
||||||
this.item = item;
|
this.item = item;
|
||||||
this.width = item.width;
|
this.width = item.width;
|
||||||
this.up = item.up;
|
this.up = item.up;
|
||||||
this.down = item.down;
|
this.down = item.down;
|
||||||
}
|
}
|
||||||
subclassOf(Link, FakeSVG);
|
subclassOf(Link, FakeSVG);
|
||||||
|
Link.prototype.needsSpace = true;
|
||||||
Link.prototype.format = function(x, y, width) {
|
Link.prototype.format = function(x, y, width) {
|
||||||
this.item.format(x,y,width).addTo(this);
|
this.item.format(x,y,width).addTo(this);
|
||||||
return this;
|
return this;
|
||||||
|
@ -21,13 +21,11 @@ x y z sequence
|
|||||||
<"x"> nonterminal
|
<"x"> nonterminal
|
||||||
/"blah"/ comment
|
/"blah"/ comment
|
||||||
- dummy
|
- dummy
|
||||||
|
[[x|"tiddler"]] link
|
||||||
|
{{"tiddler"}} transclusion
|
||||||
|
|
||||||
"x" can also be written 'x' or """x"""
|
"x" can also be written 'x' or """x"""
|
||||||
|
|
||||||
Future extensions:
|
|
||||||
[[x|tiddler]] link
|
|
||||||
{{tiddler}} transclusion
|
|
||||||
|
|
||||||
\*/
|
\*/
|
||||||
(function(){
|
(function(){
|
||||||
|
|
||||||
@ -37,12 +35,14 @@ Future extensions:
|
|||||||
|
|
||||||
var components = require("$:/plugins/tiddlywiki/railroad/components.js").components;
|
var components = require("$:/plugins/tiddlywiki/railroad/components.js").components;
|
||||||
|
|
||||||
var Parser = function(source) {
|
var Parser = function(widget,source) {
|
||||||
|
this.widget = widget;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.tokens = this.tokenise(source);
|
this.tokens = this.tokenise(source);
|
||||||
this.tokenPos = 0;
|
this.tokenPos = 0;
|
||||||
this.advance();
|
this.advance();
|
||||||
this.root = new components.Root(this.parseContent());
|
this.content = this.parseContent();
|
||||||
|
this.root = new components.Root(this.content);
|
||||||
this.checkFinished();
|
this.checkFinished();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,8 +66,8 @@ Parser.prototype.parseComponent = function() {
|
|||||||
if(this.token) {
|
if(this.token) {
|
||||||
if(this.at("string")) {
|
if(this.at("string")) {
|
||||||
component = this.parseTerminal();
|
component = this.parseTerminal();
|
||||||
} else if(this.at("identifier")) {
|
} else if(this.at("name")) {
|
||||||
component = this.parseIdentifier();
|
component = this.parseName();
|
||||||
} else {
|
} else {
|
||||||
switch(this.token.value) {
|
switch(this.token.value) {
|
||||||
case "[":
|
case "[":
|
||||||
@ -85,6 +85,12 @@ Parser.prototype.parseComponent = function() {
|
|||||||
case "/":
|
case "/":
|
||||||
component = this.parseComment();
|
component = this.parseComment();
|
||||||
break;
|
break;
|
||||||
|
case "[[":
|
||||||
|
component = this.parseLink();
|
||||||
|
break;
|
||||||
|
case "{{":
|
||||||
|
component = this.parseTransclusion();
|
||||||
|
break;
|
||||||
case "<-":
|
case "<-":
|
||||||
component = this.parseSequence();
|
component = this.parseSequence();
|
||||||
break;
|
break;
|
||||||
@ -112,25 +118,21 @@ Parser.prototype.parseChoice = function() {
|
|||||||
// Parse the next branch
|
// Parse the next branch
|
||||||
content.push(this.parseContent());
|
content.push(this.parseContent());
|
||||||
} while(this.eat("|"));
|
} while(this.eat("|"));
|
||||||
// Create a component
|
|
||||||
var component = new components.Choice(content,colon === -1 ? 0 : colon);
|
|
||||||
// Consume the closing bracket
|
// Consume the closing bracket
|
||||||
this.close(")");
|
this.close(")");
|
||||||
return component;
|
// Create a component
|
||||||
|
return new components.Choice(content,colon === -1 ? 0 : colon);
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseComment = function() {
|
Parser.prototype.parseComment = function() {
|
||||||
// Consume the /
|
// Consume the /
|
||||||
this.advance();
|
this.advance();
|
||||||
// The comment's content should be in a string literal
|
// The comment's content should be in a string literal
|
||||||
this.expectStringLiteral("/");
|
var content = this.expectString("after /");
|
||||||
// Create a component
|
|
||||||
var component = new components.Comment(this.token.value);
|
|
||||||
// Consume the string literal
|
|
||||||
this.advance();
|
|
||||||
// Consume the closing /
|
// Consume the closing /
|
||||||
this.close("/");
|
this.close("/");
|
||||||
return component;
|
// Create a component
|
||||||
|
return new components.Comment(content);
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseDummy = function() {
|
Parser.prototype.parseDummy = function() {
|
||||||
@ -140,27 +142,43 @@ Parser.prototype.parseDummy = function() {
|
|||||||
return new components.Dummy();
|
return new components.Dummy();
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseIdentifier = function() {
|
Parser.prototype.parseLink = function() {
|
||||||
|
// Consume the [[
|
||||||
|
this.advance();
|
||||||
|
// Parse the content
|
||||||
|
var content = this.parseContent();
|
||||||
|
// Consume the |
|
||||||
|
this.expect("|");
|
||||||
|
// Consume the target
|
||||||
|
var target = this.expectNameOrString("as link target");
|
||||||
|
// Prepare some attributes for the SVG "a" element to carry
|
||||||
|
var options = {"data-tw-target": target};
|
||||||
|
if($tw.utils.isLinkExternal(target)) {
|
||||||
|
options["data-tw-external"] = true;
|
||||||
|
}
|
||||||
|
// Consume the closing ]]
|
||||||
|
this.close("]]");
|
||||||
|
// Create a component
|
||||||
|
return new components.Link(content,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
Parser.prototype.parseName = function() {
|
||||||
// Create a component
|
// Create a component
|
||||||
var component = new components.Nonterminal(this.token.value);
|
var component = new components.Nonterminal(this.token.value);
|
||||||
// Consume the identifier
|
// Consume the name
|
||||||
this.advance();
|
this.advance();
|
||||||
return component;
|
return component;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Parser.prototype.parseNonterminal = function() {
|
Parser.prototype.parseNonterminal = function() {
|
||||||
// Consume the <
|
// Consume the <
|
||||||
this.advance();
|
this.advance();
|
||||||
// The nonterminal's name should be in a string literal
|
// The nonterminal's name should be in a string literal
|
||||||
this.expectStringLiteral("<");
|
var content = this.expectString("after <");
|
||||||
// Create a component
|
|
||||||
var component = new components.Nonterminal(this.token.value);
|
|
||||||
// Consume the string literal
|
|
||||||
this.advance();
|
|
||||||
// Consume the closing bracket
|
// Consume the closing bracket
|
||||||
this.close(">");
|
this.close(">");
|
||||||
return component;
|
// Create a component
|
||||||
|
return new components.Nonterminal(content);
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseOptional = function() {
|
Parser.prototype.parseOptional = function() {
|
||||||
@ -177,14 +195,13 @@ Parser.prototype.parseOptional = function() {
|
|||||||
if(repeated && this.eat("+")) {
|
if(repeated && this.eat("+")) {
|
||||||
separator = this.parseContent();
|
separator = this.parseContent();
|
||||||
}
|
}
|
||||||
// Create a component
|
|
||||||
var component = repeated ? new components.OptionalRepeated(content,separator,normal) : new components.Optional(content,normal);
|
|
||||||
// Consume the closing brackets
|
// Consume the closing brackets
|
||||||
if(repeated) {
|
if(repeated) {
|
||||||
this.close("}");
|
this.close("}");
|
||||||
}
|
}
|
||||||
this.close("]");
|
this.close("]");
|
||||||
return component;
|
// Create a component
|
||||||
|
return repeated ? new components.OptionalRepeated(content,separator,normal) : new components.Optional(content,normal);
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseRepeated = function() {
|
Parser.prototype.parseRepeated = function() {
|
||||||
@ -197,23 +214,21 @@ Parser.prototype.parseRepeated = function() {
|
|||||||
if(this.eat("+")) {
|
if(this.eat("+")) {
|
||||||
separator = this.parseContent();
|
separator = this.parseContent();
|
||||||
}
|
}
|
||||||
// Create a component
|
|
||||||
var component = new components.Repeated(content,separator);
|
|
||||||
// Consume the closing bracket
|
// Consume the closing bracket
|
||||||
this.close("}");
|
this.close("}");
|
||||||
return component;
|
// Create a component
|
||||||
|
return new components.Repeated(content,separator);
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseSequence = function() {
|
Parser.prototype.parseSequence = function() {
|
||||||
// Consume the ~
|
// Consume the <-
|
||||||
this.advance();
|
this.advance();
|
||||||
// Parse the content
|
// Parse the content
|
||||||
var content = this.parseContent();
|
var content = this.parseContent();
|
||||||
// Create a component
|
// Consume the closing ->
|
||||||
var component = new components.Sequence(content);
|
|
||||||
// Consume the closing ~
|
|
||||||
this.close("->");
|
this.close("->");
|
||||||
return component;
|
// Create a component
|
||||||
|
return new components.Sequence(content);
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.parseTerminal = function() {
|
Parser.prototype.parseTerminal = function() {
|
||||||
@ -223,6 +238,21 @@ Parser.prototype.parseTerminal = function() {
|
|||||||
return component;
|
return component;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.prototype.parseTransclusion = function() {
|
||||||
|
// Consume the {{
|
||||||
|
this.advance();
|
||||||
|
// Consume the text reference
|
||||||
|
var textRef = this.expectNameOrString("as transclusion source");
|
||||||
|
// Consume the closing }}
|
||||||
|
this.close("}}");
|
||||||
|
// Retrieve the content of the text reference
|
||||||
|
var source = this.widget.wiki.getTextReference(textRef,"",this.widget.getVariable("currentTiddler"));
|
||||||
|
// Parse the content
|
||||||
|
var content = new Parser(this.widget,source).content;
|
||||||
|
// Create a component
|
||||||
|
return new components.Transclusion(content);
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////// Token manipulation
|
/////////////////////////// Token manipulation
|
||||||
|
|
||||||
Parser.prototype.advance = function() {
|
Parser.prototype.advance = function() {
|
||||||
@ -244,10 +274,10 @@ Parser.prototype.eat = function(token) {
|
|||||||
return at;
|
return at;
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.expectStringLiteral = function(preamble) {
|
Parser.prototype.tokenValue = function() {
|
||||||
if(!this.at("string")) {
|
var output = this.token.value;
|
||||||
throw "String expected after " + preamble;
|
this.advance();
|
||||||
}
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.close = function(token) {
|
Parser.prototype.close = function(token) {
|
||||||
@ -262,6 +292,27 @@ Parser.prototype.checkFinished = function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Parser.prototype.expect = function(token) {
|
||||||
|
if(!this.eat(token)) {
|
||||||
|
throw token + " expected";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parser.prototype.expectString = function(context,token) {
|
||||||
|
if(!this.at("string")) {
|
||||||
|
token = token || "String";
|
||||||
|
throw token + " expected " + context;
|
||||||
|
}
|
||||||
|
return this.tokenValue();
|
||||||
|
};
|
||||||
|
|
||||||
|
Parser.prototype.expectNameOrString = function(context) {
|
||||||
|
if(this.at("name")) {
|
||||||
|
return this.tokenValue();
|
||||||
|
}
|
||||||
|
return this.expectString(context,"Name or string");
|
||||||
|
};
|
||||||
|
|
||||||
/////////////////////////// Tokenisation
|
/////////////////////////// Tokenisation
|
||||||
|
|
||||||
Parser.prototype.tokenise = function(source) {
|
Parser.prototype.tokenise = function(source) {
|
||||||
@ -294,12 +345,12 @@ Parser.prototype.tokenise = function(source) {
|
|||||||
} else if(c === "-") {
|
} else if(c === "-") {
|
||||||
// - or ->
|
// - or ->
|
||||||
s = source.charAt(pos+1) === ">" ? "->" : "-";
|
s = source.charAt(pos+1) === ">" ? "->" : "-";
|
||||||
} else if("()>+|/:".indexOf(c) !== -1) {
|
} else if("()>+/:|".indexOf(c) !== -1) {
|
||||||
// Single character
|
// Single character
|
||||||
s = c;
|
s = c;
|
||||||
} else if(c.match(/[a-zA-Z]/)) {
|
} else if(c.match(/[a-zA-Z]/)) {
|
||||||
// Identifier
|
// Name
|
||||||
token = this.readIdentifier(source,pos);
|
token = this.readName(source,pos);
|
||||||
} else {
|
} else {
|
||||||
throw "Syntax error at " + c;
|
throw "Syntax error at " + c;
|
||||||
}
|
}
|
||||||
@ -316,14 +367,14 @@ Parser.prototype.tokenise = function(source) {
|
|||||||
return tokens;
|
return tokens;
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser.prototype.readIdentifier = function(source,pos) {
|
Parser.prototype.readName = function(source,pos) {
|
||||||
var re = /([a-zA-Z0-9_.-]+)/g;
|
var re = /([a-zA-Z0-9_.-]+)/g;
|
||||||
re.lastIndex = pos;
|
re.lastIndex = pos;
|
||||||
var match = re.exec(source);
|
var match = re.exec(source);
|
||||||
if(match && match.index === pos) {
|
if(match && match.index === pos) {
|
||||||
return {type: "identifier", value: match[1], start: pos, end: pos + match[1].length};
|
return {type: "name", value: match[1], start: pos, end: pos+match[1].length};
|
||||||
} else {
|
} else {
|
||||||
throw "Invalid identifier";
|
throw "Invalid name";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,24 +38,73 @@ RailroadWidget.prototype.render = function(parent,nextSibling) {
|
|||||||
var div = this.document.createElement("div");
|
var div = this.document.createElement("div");
|
||||||
try {
|
try {
|
||||||
// Parse the source
|
// Parse the source
|
||||||
var parser = new Parser(source);
|
var parser = new Parser(this,source);
|
||||||
|
// Generate content into the div
|
||||||
if(this.getAttribute("mode","svg") === "debug") {
|
if(this.getAttribute("mode","svg") === "debug") {
|
||||||
var output = ["<pre>"];
|
this.renderDebug(parser,div);
|
||||||
parser.root.debug(output, "");
|
|
||||||
output.push("</pre>");
|
|
||||||
div.innerHTML = output.join("");
|
|
||||||
} else {
|
} else {
|
||||||
div.innerHTML = parser.root.toSvg();
|
this.renderSvg(parser,div);
|
||||||
}
|
}
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
div.className = "tc-error";
|
div.className = "tc-error";
|
||||||
div.textContent = ex;
|
div.textContent = ex;
|
||||||
}
|
}
|
||||||
// Insert it into the DOM
|
// Insert the div into the DOM
|
||||||
parent.insertBefore(div,nextSibling);
|
parent.insertBefore(div,nextSibling);
|
||||||
this.domNodes.push(div);
|
this.domNodes.push(div);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RailroadWidget.prototype.renderDebug = function(parser,div) {
|
||||||
|
var output = ["<pre>"];
|
||||||
|
parser.root.debug(output, "");
|
||||||
|
output.push("</pre>");
|
||||||
|
div.innerHTML = output.join("");
|
||||||
|
};
|
||||||
|
|
||||||
|
RailroadWidget.prototype.renderSvg = function(parser,div) {
|
||||||
|
// Generate a model of the diagram
|
||||||
|
var fakeSvg = parser.root.toSvg();
|
||||||
|
// Render the model into a tree of SVG DOM nodes
|
||||||
|
var svg = fakeSvg.toSVG();
|
||||||
|
// Fill in the remaining attributes of any link nodes
|
||||||
|
this.patchLinks(svg);
|
||||||
|
// Insert the SVG tree into the div
|
||||||
|
div.appendChild(svg);
|
||||||
|
};
|
||||||
|
|
||||||
|
RailroadWidget.prototype.patchLinks = function(node) {
|
||||||
|
var self = this;
|
||||||
|
if(node.hasChildNodes()) {
|
||||||
|
var children = node.childNodes;
|
||||||
|
for(var i=0; i<children.length; i++) {
|
||||||
|
var child = children[i];
|
||||||
|
var attributes = child.attributes;
|
||||||
|
if(attributes) {
|
||||||
|
// Find each element that has a data-tw-target attribute
|
||||||
|
var target = child.attributes["data-tw-target"];
|
||||||
|
if(target !== undefined) {
|
||||||
|
target = target.value;
|
||||||
|
if(child.attributes["data-tw-external"]) {
|
||||||
|
// External links are straightforward
|
||||||
|
child.setAttribute("target","_blank");
|
||||||
|
} else {
|
||||||
|
// Each internal link gets its own onclick handler, capturing its own copy of target
|
||||||
|
(function(myTarget) {
|
||||||
|
child.onclick = function(event) {
|
||||||
|
self.dispatchLink(myTarget,event);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})(target);
|
||||||
|
target = "#" + target;
|
||||||
|
}
|
||||||
|
child.setAttributeNS("http://www.w3.org/1999/xlink","href",target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.patchLinks(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
RailroadWidget.prototype.refresh = function(changedTiddlers) {
|
RailroadWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
var changedAttributes = this.computeAttributes();
|
var changedAttributes = this.computeAttributes();
|
||||||
if(changedAttributes.text) {
|
if(changedAttributes.text) {
|
||||||
@ -65,6 +114,23 @@ RailroadWidget.prototype.refresh = function(changedTiddlers) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RailroadWidget.prototype.dispatchLink = function(to,event) {
|
||||||
|
// Send the click on its way as a navigate event
|
||||||
|
var bounds = this.domNodes[0].getBoundingClientRect();
|
||||||
|
this.dispatchEvent({
|
||||||
|
type: "tm-navigate",
|
||||||
|
navigateTo: to,
|
||||||
|
navigateFromTitle: this.getVariable("storyTiddler"),
|
||||||
|
navigateFromNode: this,
|
||||||
|
navigateFromClientRect: { top: bounds.top, left: bounds.left, width: bounds.width, right: bounds.right, bottom: bounds.bottom, height: bounds.height
|
||||||
|
},
|
||||||
|
navigateSuppressNavigation: event.metaKey || event.ctrlKey || (event.button === 1)
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
exports.railroad = RailroadWidget;
|
exports.railroad = RailroadWidget;
|
||||||
|
|
||||||
})();
|
})();
|
Loading…
Reference in New Issue
Block a user