mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-01-23 07:26:54 +00:00
Support global macros via the importvariables widget
The new importvariables widget imports macro/variable definitions from the specified tiddlers and makes them available to its children. Allows us to split PageMacros up into separate tiddlers. We still support loading macros from $:/core/ui/PageMacros to help people upgrading. Fixes #644 and #559
This commit is contained in:
parent
0e09fbf46a
commit
9ab0c84140
@ -21,7 +21,7 @@ exports.synchronous = true;
|
||||
// Default story and history lists
|
||||
var PAGE_TITLE_TITLE = "$:/core/wiki/title"
|
||||
var PAGE_STYLESHEET_TITLE = "$:/core/ui/PageStylesheet";
|
||||
var PAGE_TEMPLATE_TITLE = "$:/core/ui/PageMacros";
|
||||
var PAGE_TEMPLATE_TITLE = "$:/core/ui/PageTemplate";
|
||||
|
||||
// Time (in ms) that we defer refreshing changes to draft tiddlers
|
||||
var DRAFT_TIDDLER_TIMEOUT = 400;
|
||||
@ -49,7 +49,7 @@ exports.startup = function() {
|
||||
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
|
||||
}
|
||||
}));
|
||||
// Display the $:/core/ui/PageMacros tiddler to kick off the display
|
||||
// Display the $:/core/ui/PageTemplate tiddler to kick off the display
|
||||
$tw.perf.report("mainRender",function() {
|
||||
$tw.pageWidgetNode = $tw.wiki.makeTranscludeWidget(PAGE_TEMPLATE_TITLE,{document: document, parentWidget: $tw.rootWidget});
|
||||
$tw.pageContainer = document.createElement("div");
|
||||
|
115
core/modules/widgets/importvariables.js
Normal file
115
core/modules/widgets/importvariables.js
Normal file
@ -0,0 +1,115 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/importvariables.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
Import variable definitions from other tiddlers
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var ImportVariablesWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
ImportVariablesWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
ImportVariablesWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
this.renderChildren(parent,nextSibling);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
ImportVariablesWidget.prototype.execute = function(tiddlerList) {
|
||||
var self = this;
|
||||
// Get our parameters
|
||||
this.filter = this.getAttribute("filter");
|
||||
// Compute the filter
|
||||
this.tiddlerList = tiddlerList || this.wiki.filterTiddlers(this.filter,this);
|
||||
// Accumulate the <$set> widgets from each tiddler
|
||||
var widgetStackStart,widgetStackEnd;
|
||||
function addWidgetNode(widgetNode) {
|
||||
if(widgetNode) {
|
||||
if(!widgetStackStart && !widgetStackEnd) {
|
||||
widgetStackStart = widgetNode;
|
||||
widgetStackEnd = widgetNode;
|
||||
} else {
|
||||
widgetStackEnd.children = [widgetNode];
|
||||
widgetStackEnd = widgetNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
$tw.utils.each(this.tiddlerList,function(title) {
|
||||
var parser = self.wiki.parseTiddler(title);
|
||||
if(parser) {
|
||||
var parseTreeNode = parser.tree[0];
|
||||
while(parseTreeNode && parseTreeNode.type === "set") {
|
||||
addWidgetNode({
|
||||
type: "set",
|
||||
attributes: parseTreeNode.attributes,
|
||||
params: parseTreeNode.params
|
||||
});
|
||||
parseTreeNode = parseTreeNode.children[0];
|
||||
}
|
||||
}
|
||||
});
|
||||
// Add our own children to the end of the pile
|
||||
var parseTreeNodes;
|
||||
if(widgetStackStart && widgetStackEnd) {
|
||||
parseTreeNodes = [widgetStackStart];
|
||||
widgetStackEnd.children = this.parseTreeNode.children;
|
||||
} else {
|
||||
parseTreeNodes = this.parseTreeNode.children;
|
||||
}
|
||||
// Construct the child widgets
|
||||
this.makeChildWidgets(parseTreeNodes);
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
ImportVariablesWidget.prototype.refresh = function(changedTiddlers) {
|
||||
// Recompute our attributes and the filter list
|
||||
var changedAttributes = this.computeAttributes(),
|
||||
tiddlerList = this.wiki.filterTiddlers(this.getAttribute("filter"),this);
|
||||
// Refresh if the filter has changed, or the list of tiddlers has changed, or any of the tiddlers in the list has changed
|
||||
function haveListedTiddlersChanged() {
|
||||
var changed = false;
|
||||
tiddlerList.forEach(function(title) {
|
||||
if(changedTiddlers[title]) {
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
return changed;
|
||||
}
|
||||
if(changedAttributes.filter || !$tw.utils.isArrayEqual(this.tiddlerList,tiddlerList) || haveListedTiddlersChanged()) {
|
||||
// Compute the filter
|
||||
console.log("Refreshing importvariables with filter=",this.getAttribute("filter"));
|
||||
this.removeChildDomNodes();
|
||||
this.execute(tiddlerList);
|
||||
this.renderChildren(this.parentDomNode,this.findNextSiblingDomNode());
|
||||
return true;
|
||||
} else {
|
||||
return this.refreshChildren(changedTiddlers);
|
||||
}
|
||||
};
|
||||
|
||||
exports.importvariables = ImportVariablesWidget;
|
||||
|
||||
})();
|
@ -21,6 +21,6 @@ type: text/vnd.tiddlywiki-html
|
||||
</head>
|
||||
<body class="tw-body">
|
||||
{{$:/StaticBanner||$:/core/templates/html-tiddler}}
|
||||
{{$:/core/ui/PageMacros||$:/core/templates/html-tiddler}}
|
||||
{{$:/core/ui/PageTemplate||$:/core/templates/html-tiddler}}
|
||||
</body>
|
||||
</html>
|
||||
|
@ -15,7 +15,9 @@ title: $:/core/templates/static.tiddler.html
|
||||
<body class="tw-body">
|
||||
`{{$:/StaticBanner||$:/core/templates/html-tiddler}}`
|
||||
<section class="story-river">
|
||||
`<$view tiddler="$:/core/ui/ViewTemplate" format="htmlwikified"/>`
|
||||
`<$importvariables filter="[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]">
|
||||
<$view tiddler="$:/core/ui/ViewTemplate" format="htmlwikified"/>
|
||||
</$importvariables>`
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,6 +4,8 @@ title: $:/core/ui/PageTemplate
|
||||
tw-page-container tw-page-view-$(themeTitle)$ tw-language-$(languageTitle)$
|
||||
\end
|
||||
|
||||
<$importvariables filter="[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]">
|
||||
|
||||
<$set name="themeTitle" value={{$:/view}}>
|
||||
|
||||
<$set name="currentTiddler" value={{$:/language}}>
|
||||
@ -37,3 +39,5 @@ tw-page-container tw-page-view-$(themeTitle)$ tw-language-$(languageTitle)$
|
||||
</$set>
|
||||
|
||||
</$set>
|
||||
|
||||
</$importvariables>
|
||||
|
10
core/wiki/macros/CSS.tid
Normal file
10
core/wiki/macros/CSS.tid
Normal file
@ -0,0 +1,10 @@
|
||||
title: $:/core/macros/CSS
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\define colour(name)
|
||||
<$transclude tiddler={{$:/palette}} index="$name$"/>
|
||||
\end
|
||||
|
||||
\define color(name)
|
||||
<<colour $name$>>
|
||||
\end
|
10
core/wiki/macros/lingo.tid
Normal file
10
core/wiki/macros/lingo.tid
Normal file
@ -0,0 +1,10 @@
|
||||
title: $:/core/macros/lingo
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\define lingo-base()
|
||||
$:/lingo/
|
||||
\end
|
||||
|
||||
\define lingo(title)
|
||||
{{$(lingo-base)$$title$}}
|
||||
\end
|
@ -1,12 +1,5 @@
|
||||
title: $:/core/ui/PageMacros
|
||||
|
||||
\define colour(name)
|
||||
<$transclude tiddler={{$:/palette}} index="$name$"/>
|
||||
\end
|
||||
|
||||
\define color(name)
|
||||
<<colour $name$>>
|
||||
\end
|
||||
title: $:/core/macros/tabs
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\define tabs(tabsList,default,state:"$:/state/tab",class)
|
||||
<div class="tw-tab-set $class$">
|
||||
@ -27,40 +20,3 @@ title: $:/core/ui/PageMacros
|
||||
</div>
|
||||
</div>
|
||||
\end
|
||||
|
||||
\define wikitext-example(src)
|
||||
```
|
||||
$src$
|
||||
```
|
||||
|
||||
Renders as:
|
||||
|
||||
$src$
|
||||
|
||||
In HTML:
|
||||
|
||||
$$$text/vnd.tiddlywiki>text/html
|
||||
$src$
|
||||
$$$
|
||||
|
||||
\end
|
||||
|
||||
\define wikitext-example-without-html(src)
|
||||
```
|
||||
$src$
|
||||
```
|
||||
|
||||
Renders as:
|
||||
|
||||
$src$
|
||||
|
||||
\end
|
||||
|
||||
\define lingo-base()
|
||||
$:/lingo/
|
||||
\end
|
||||
|
||||
\define lingo(title)
|
||||
{{$(lingo-base)$$title$}}
|
||||
\end
|
||||
{{$:/core/ui/PageTemplate}}
|
@ -23,4 +23,4 @@ It also determines the standard UI flow:
|
||||
# The core then issues a store change event which triggers the refresh cycle
|
||||
# Each widget in the tree then gets a chance to refresh itself to reflect the changes in the store if they need to
|
||||
|
||||
From a technical perspective, TiddlyWiki is a fairly classic MVC architecture, with strict separation of concerns. The model is the tiddler store, the view is a rendering tree (such as the one created from [[$:/core/ui/PageMacros]] in startup.js), and the controller is the core code itself.
|
||||
From a technical perspective, TiddlyWiki is a fairly classic MVC architecture, with strict separation of concerns. The model is the tiddler store, the view is a rendering tree (such as the one created from [[$:/core/ui/PageTemplate]] in startup.js), and the controller is the core code itself.
|
||||
|
@ -6,7 +6,7 @@ type: text/vnd.tiddlywiki
|
||||
|
||||
The StateMechanism in TiddlyWiki is at the heart of how complex user interfaces can be built from WikiText.
|
||||
|
||||
In the browser, the TiddlyWiki display is produced by dynamically rendering the tiddler [[$:/core/ui/PageMacros]]. Through various transclusions and other widgets it renders the entire user interface. The dynamic rendering is accomplished by a mechanism called "binding": any changes to the tiddlers in the store are dynamically reflected in the browser display.
|
||||
In the browser, the TiddlyWiki display is produced by dynamically rendering the tiddler [[$:/core/ui/PageTemplate]]. Through various transclusions and other widgets it renders the entire user interface. The dynamic rendering is accomplished by a mechanism called "binding": any changes to the tiddlers in the store are dynamically reflected in the browser display.
|
||||
|
||||
The stack of templates that make up the TiddlyWiki display are complex but we'll focus on the line that displays the main story column:
|
||||
|
||||
|
30
editions/tw5.com/tiddlers/system/wikitext-macros.tid
Normal file
30
editions/tw5.com/tiddlers/system/wikitext-macros.tid
Normal file
@ -0,0 +1,30 @@
|
||||
title: $:/editions/tw5.com/wikitext-macros
|
||||
tags: $:/tags/Macro
|
||||
|
||||
\define wikitext-example(src)
|
||||
```
|
||||
$src$
|
||||
```
|
||||
|
||||
Renders as:
|
||||
|
||||
$src$
|
||||
|
||||
In HTML:
|
||||
|
||||
$$$text/vnd.tiddlywiki>text/html
|
||||
$src$
|
||||
$$$
|
||||
|
||||
\end
|
||||
|
||||
\define wikitext-example-without-html(src)
|
||||
```
|
||||
$src$
|
||||
```
|
||||
|
||||
Renders as:
|
||||
|
||||
$src$
|
||||
|
||||
\end
|
32
editions/tw5.com/tiddlers/widgets/ImportVariablesWidget.tid
Normal file
32
editions/tw5.com/tiddlers/widgets/ImportVariablesWidget.tid
Normal file
@ -0,0 +1,32 @@
|
||||
created: 20140612142500000
|
||||
modified: 20140612175900970
|
||||
tags: widget
|
||||
title: ImportVariablesWidget
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
! Introduction
|
||||
|
||||
The ImportVariablesWidget imports macro and variable definitions from a list of other tiddlers and makes them available to its children. For example:
|
||||
|
||||
```
|
||||
<$importvariables filter="[tag[mySpecialMacros]]">
|
||||
All the macros defined in tiddlers with the tag "mySpecialMacros" are available here
|
||||
</$importvariables>
|
||||
```
|
||||
|
||||
! Attributes and Content
|
||||
|
||||
The content of the importvariables widget is the scope within which the imported variable definitions are available.
|
||||
|
||||
|!Attribute |!Description |
|
||||
|filter |[[Tiddler filter|TiddlerFilters]] defining the tiddlers from which macro definitions will be imported |
|
||||
|
||||
! Global Macros
|
||||
|
||||
So-called global macros are implemented within the main page template ([[$:/core/ui/PageTemplate]]) by wrapping the page content in the following importvariables widget:
|
||||
|
||||
```
|
||||
<$importvariables filter="[[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]">
|
||||
...
|
||||
</$importvariables>
|
||||
```
|
Loading…
Reference in New Issue
Block a user