tw5-graph 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +65 -0
  2. package/package.json +39 -0
  3. package/plugins/graph/DefaultColourMappings.multids +8 -0
  4. package/plugins/graph/ViewTemplateBodyFilter/graph.tid +5 -0
  5. package/plugins/graph/ViewTemplateBodyFilter/properties.tid +5 -0
  6. package/plugins/graph/edges/fields/list.tid +7 -0
  7. package/plugins/graph/edges/fields/tags.tid +7 -0
  8. package/plugins/graph/edges/functions/links.tid +8 -0
  9. package/plugins/graph/edges/functions/transcludes.tid +8 -0
  10. package/plugins/graph/fieldtypes/filter.js +212 -0
  11. package/plugins/graph/fieldtypes/list.js +31 -0
  12. package/plugins/graph/fieldtypes/title.js +27 -0
  13. package/plugins/graph/filterrunprefixes/cache.js +118 -0
  14. package/plugins/graph/filters/gettyped.js +26 -0
  15. package/plugins/graph/graphengine.js +38 -0
  16. package/plugins/graph/icon.tid +16 -0
  17. package/plugins/graph/images/drag.tid +13 -0
  18. package/plugins/graph/macros/action.addedge.tid +16 -0
  19. package/plugins/graph/macros/edges.typed.tid +54 -0
  20. package/plugins/graph/macros/graph.view.tid +24 -0
  21. package/plugins/graph/macros/node.default.tid +9 -0
  22. package/plugins/graph/macros/nodes.neighbors.tid +62 -0
  23. package/plugins/graph/macros/nodes.writable.tid +37 -0
  24. package/plugins/graph/macros/properties.persistent.tid +27 -0
  25. package/plugins/graph/macros/properties.popup.tid +76 -0
  26. package/plugins/graph/macros/properties.river.tid +27 -0
  27. package/plugins/graph/macros/properties.settings.tid +54 -0
  28. package/plugins/graph/macros/properties.stack.tid +17 -0
  29. package/plugins/graph/macros/tiddlywiki.files +17 -0
  30. package/plugins/graph/nodes/neighbors/1.tid +8 -0
  31. package/plugins/graph/plugin.info +14 -0
  32. package/plugins/graph/presettypes/edges/fields.tid +18 -0
  33. package/plugins/graph/presettypes/edges/functions.tid +5 -0
  34. package/plugins/graph/presettypes/nodes/neighbors.tid +4 -0
  35. package/plugins/graph/presettypes/nodes/stack.tid +6 -0
  36. package/plugins/graph/propertytypes/actions.js +15 -0
  37. package/plugins/graph/propertytypes/boolean.js +23 -0
  38. package/plugins/graph/propertytypes/color.js +61 -0
  39. package/plugins/graph/propertytypes/enum.js +25 -0
  40. package/plugins/graph/propertytypes/filter.js +44 -0
  41. package/plugins/graph/propertytypes/image.js +185 -0
  42. package/plugins/graph/propertytypes/number.js +24 -0
  43. package/plugins/graph/propertytypes/string.js +13 -0
  44. package/plugins/graph/propertytypes/tiddlywiki.files +17 -0
  45. package/plugins/graph/readme.tid +5 -0
  46. package/plugins/graph/relink/attributes.js +52 -0
  47. package/plugins/graph/relink/attributes.multids +19 -0
  48. package/plugins/graph/relink/configprefix.js +76 -0
  49. package/plugins/graph/relink/fieldedgeprefix.js +39 -0
  50. package/plugins/graph/relink/fields.multids +11 -0
  51. package/plugins/graph/relink/graphprefix.js +28 -0
  52. package/plugins/graph/relink/operators.multids +3 -0
  53. package/plugins/graph/relink/propertyfields.js +81 -0
  54. package/plugins/graph/relink/utils.js +99 -0
  55. package/plugins/graph/settings.tid +13 -0
  56. package/plugins/graph/startup/messages.js +46 -0
  57. package/plugins/graph/stylesheets/base.css.tid +272 -0
  58. package/plugins/graph/stylesheets/fullscreen/core.css +11 -0
  59. package/plugins/graph/stylesheets/fullscreen/core.css.meta +3 -0
  60. package/plugins/graph/stylesheets/fullscreen.css.tid +48 -0
  61. package/plugins/graph/stylesheets/popup.css.tid +107 -0
  62. package/plugins/graph/subfilters.tid +23 -0
  63. package/plugins/graph/tags/GraphToolbar.tid +2 -0
  64. package/plugins/graph/tags/SettingsTab.tid +2 -0
  65. package/plugins/graph/tags/Template.tid +2 -0
  66. package/plugins/graph/tags/ViewEditTemplate.tid +2 -0
  67. package/plugins/graph/templates/live-graph.tid +34 -0
  68. package/plugins/graph/templates/standard-graph.tid +40 -0
  69. package/plugins/graph/ui/Buttons/center.tid +38 -0
  70. package/plugins/graph/ui/Buttons/export.tid +65 -0
  71. package/plugins/graph/ui/Buttons/fullscreen.tid +35 -0
  72. package/plugins/graph/ui/Buttons/settings.tid +28 -0
  73. package/plugins/graph/ui/Buttons/tiddlywiki.files +16 -0
  74. package/plugins/graph/ui/EditTemplate/Edges.tid +22 -0
  75. package/plugins/graph/ui/EditTemplate/Neighbors.tid +35 -0
  76. package/plugins/graph/ui/EditTemplate/Nodes.tid +12 -0
  77. package/plugins/graph/ui/EditTemplate/Popups.tid +27 -0
  78. package/plugins/graph/ui/EditTemplate/Properties.tid +21 -0
  79. package/plugins/graph/ui/EditTemplate/tiddlywiki.files +16 -0
  80. package/plugins/graph/ui/Modals/NewPropertySet.tid +20 -0
  81. package/plugins/graph/ui/Modals/NewView.tid +20 -0
  82. package/plugins/graph/ui/Modals/Select.tid +72 -0
  83. package/plugins/graph/ui/Modals/SelectField.tid +21 -0
  84. package/plugins/graph/ui/Modals/SelectTiddler.tid +15 -0
  85. package/plugins/graph/ui/Modals/Tiddler.tid +22 -0
  86. package/plugins/graph/ui/Modals/TiddlerHeader.tid +15 -0
  87. package/plugins/graph/ui/PropertyTypes/boolean.tid +11 -0
  88. package/plugins/graph/ui/PropertyTypes/color.tid +16 -0
  89. package/plugins/graph/ui/PropertyTypes/enum.tid +15 -0
  90. package/plugins/graph/ui/PropertyTypes/number.tid +17 -0
  91. package/plugins/graph/ui/Settings/Engine.tid +23 -0
  92. package/plugins/graph/ui/Settings/Graphs/EditTemplate.tid +52 -0
  93. package/plugins/graph/ui/Settings/Graphs.tid +49 -0
  94. package/plugins/graph/ui/Settings/Properties/ObjectsTypeTemplate.tid +46 -0
  95. package/plugins/graph/ui/Settings/Properties.tid +14 -0
  96. package/plugins/graph/ui/Settings/Toolbar.tid +5 -0
  97. package/plugins/graph/ui/SideBar/Graph.tid +77 -0
  98. package/plugins/graph/ui/Toolbars/GraphToolbar.tid +15 -0
  99. package/plugins/graph/ui/ViewTemplate/graph-object.tid +13 -0
  100. package/plugins/graph/ui/ViewTemplate/graph.tid +11 -0
  101. package/plugins/graph/ui/ViewTemplate/properties.tid +80 -0
  102. package/plugins/graph/ui/grouped-tabs.tid +109 -0
  103. package/plugins/graph/ui/selector.tid +74 -0
  104. package/plugins/graph/utils/propertyholder.js +80 -0
  105. package/plugins/graph/utils/widgetiterator.js +47 -0
  106. package/plugins/graph/utils.js +95 -0
  107. package/plugins/graph/widgets/action-delay.js +72 -0
  108. package/plugins/graph/widgets/action-modal.js +121 -0
  109. package/plugins/graph/widgets/action-typed.js +56 -0
  110. package/plugins/graph/widgets/action-with.js +70 -0
  111. package/plugins/graph/widgets/boundingbox.js +126 -0
  112. package/plugins/graph/widgets/fieldtranscriber/filter.js +93 -0
  113. package/plugins/graph/widgets/fieldtranscriber/json.js +34 -0
  114. package/plugins/graph/widgets/fieldtranscriber/plain.js +11 -0
  115. package/plugins/graph/widgets/fieldtranscriber.js +98 -0
  116. package/plugins/graph/widgets/graphobject.js +154 -0
  117. package/plugins/graph/widgets/messagerelay.js +115 -0
  118. package/plugins/graph/widgets/properties.js +130 -0
  119. package/plugins/graph/widgets/subclass/edge.js +55 -0
  120. package/plugins/graph/widgets/subclass/edit-color.js +52 -0
  121. package/plugins/graph/widgets/subclass/graph.js +380 -0
  122. package/plugins/graph/widgets/subclass/node.js +56 -0
  123. package/plugins/graph/widgets/tiddlywiki.files +43 -0
@@ -0,0 +1,185 @@
1
+ /*\
2
+
3
+ Defines images types, and manages fetching a url from titles.
4
+
5
+ \*/
6
+
7
+ "use strict";
8
+
9
+ var Color = require("./color.js");
10
+
11
+ exports.name = "image";
12
+
13
+ exports.type = "title";
14
+
15
+ exports.toProperty = function(info, value, options) {
16
+ var parentWidget = options.widget;
17
+ var wiki = parentWidget.wiki;
18
+ var widget = parentWidget.imageWidget;
19
+ if (!wiki.tiddlerExists(value) && !wiki.isShadowTiddler(value)) {
20
+ // It's a tiddler. It must be a literal link to an external source.
21
+ return value;
22
+ }
23
+ if (!widget) {
24
+ var parser = wiki.getCacheForTiddler(value, "graphImageParser", function() {
25
+ return getImageParser(value, wiki);
26
+ });
27
+ widget = wiki.makeWidget(parser, {parentWidget: parentWidget});
28
+ widget.typeInfo = parser.typeInfo;
29
+ parentWidget.imageWidget = widget;
30
+ }
31
+ if (!widget.uri) {
32
+ var widget = parentWidget.imageWidget;
33
+ var container = $tw.fakeDocument.createElement("div");
34
+ var typeInfo = widget.typeInfo;
35
+ var url, svg;
36
+ widget.render(container, null);
37
+ if (!widget.typeInfo) {
38
+ // Probably just a literal link to an external image
39
+ url = container.innerHTML;
40
+ } else if (typeInfo.encoding === "base64") {
41
+ // .pdf .png .jpg etc.
42
+ url = "data:" + (typeInfo.deserializerType || "utf8") + ";base64," + container.innerHTML;
43
+ } else if (svg = findSVGElement(container)) {
44
+ // wikitext-based SVG?
45
+ //data = "data:" + deserializerType + ";" + encoding + "," + encodeURIComponent(text);
46
+ injectNamespace(svg);
47
+ var style = getStyle(info, parentWidget);
48
+ injectStyle(svg, style);
49
+ var encoding = "";
50
+ if(wiki.isImageTiddler(value)) {
51
+ encoding = ";utf8";
52
+ }
53
+ url = "data:image/svg+xml" + encoding + "," + encodeURIComponent(container.innerHTML);
54
+ } else {
55
+ url = null;
56
+ }
57
+ widget.url = url;
58
+ }
59
+ return parentWidget.imageWidget.url;
60
+ };
61
+
62
+ exports.refresh = function(info, value, changedTiddlers, widget) {
63
+ if (changedTiddlers[value]) {
64
+ widget.imageWidget = undefined;
65
+ return true;
66
+ }
67
+ if (!widget.imageWidget) {
68
+ return true;
69
+ }
70
+ if (widget.imageWidget.refresh(changedTiddlers)) {
71
+ widget.imageWidget.uri = undefined;
72
+ return true;
73
+ }
74
+ // Now we need to check whether any property-dependent styles for the
75
+ // image have changed.
76
+ return refreshStyle(info, widget, changedTiddlers);
77
+ };
78
+
79
+ function getImageParser(title, wiki) {
80
+ var parser;
81
+ var typeInfo;
82
+ // Check if it is an image tiddler
83
+ if(wiki.isImageTiddler(title)) {
84
+ var tiddler = wiki.getTiddler(title),
85
+ type = tiddler.fields.type,
86
+ text = tiddler.fields.text,
87
+ data;
88
+ typeInfo = $tw.config.contentTypeInfo[type] || {};
89
+ if(text) {
90
+ var encoding = typeInfo.encoding || "utf8";
91
+ if (encoding === "base64") {
92
+ parser = { tree: [{
93
+ type: "text",
94
+ attributes: { text: {type: "string", value: text} }
95
+ }]};
96
+ } else {
97
+ // It's an xml svg probably. We still need to parse it into
98
+ // a DOM tree for manipulation.
99
+ text = text.replace(/^<\?[^?]*\?>/, "");
100
+ // Also remove DOCTYPE declarations
101
+ text = text.replace(/^\s*<!DOCTYPE\s[^>]*>/, "");
102
+ parser = wiki.parseText("text/vnd.tiddlywiki", "\\rules only html commentinline commentblock\n" + text, {parseAsInline: true});
103
+ }
104
+ //deserializerType = typeInfo.deserializerType || type;
105
+ // Render the appropriate element for the image type by
106
+ // looking up the encoding in the content type info
107
+ } else if(tiddler.fields._canonical_uri) {
108
+ parser = {
109
+ tree: [{
110
+ type: "text",
111
+ attributes: { text: {type: "string", value: tiddler.fields._canonical_uri} }
112
+ }]};
113
+ // It's a link. We don't need to describe type info
114
+ typeInfo = null;
115
+ } else {
116
+ // This must be a lazily loaded tiddler. We don't support those yet.
117
+ text = null;
118
+ }
119
+ } else if (wiki.tiddlerExists(title) || wiki.isShadowTiddler(title)) {
120
+ // We assume it is wikitext trying to make an svg
121
+ parser = wiki.parseTiddler(title, {parseAsInline: true});
122
+ typeInfo = $tw.config.contentTypeInfo["image/svg+xml"];
123
+ } else {
124
+ parser = { tree: [{
125
+ type: "text",
126
+ attributes: { text: {type: "string", value: title} }
127
+ }]};
128
+ }
129
+ parser.typeInfo = typeInfo;
130
+ return parser;
131
+ };
132
+
133
+ function findSVGElement(element) {
134
+ if (element.tag === "svg") {
135
+ return element;
136
+ }
137
+ if (element.children) {
138
+ for (var i = 0; i < element.children.length; i++) {
139
+ var found = findSVGElement(element.children[i]);
140
+ if (found) {
141
+ return found;
142
+ }
143
+ }
144
+ }
145
+ return null;
146
+ };
147
+
148
+ function getStyle(info, objectWidget) {
149
+ if (!info.style) {
150
+ return "";
151
+ }
152
+ var styleParts = [];
153
+ for (var attribute in info.style) {
154
+ var key = info.style[attribute];
155
+ var styleValue = objectWidget.evaluateProperty(key);
156
+ if (styleValue) {
157
+ // probably "fill:color", but any kind of css styling is allowed.
158
+ styleParts.push(attribute + ":" + styleValue + ";");
159
+ }
160
+ }
161
+ return styleParts.length > 0? ":root{" + styleParts.join("") + "}": "";
162
+ };
163
+
164
+ function refreshStyle(info, objectWidget, changedTiddlers) {
165
+ for (var attribute in info.style) {
166
+ var key = info.style[attribute];
167
+ if (objectWidget.refreshProperty(key, changedTiddlers)) {
168
+ return true;
169
+ }
170
+ }
171
+ return false;
172
+ };
173
+
174
+ function injectNamespace(svg) {
175
+ // wikitext svg does not need namespacing, but data URIs do
176
+ svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
177
+ };
178
+
179
+ function injectStyle(svg, style) {
180
+ if (style) {
181
+ var styleElement = $tw.fakeDocument.createElement("style");
182
+ styleElement.textContent = style;
183
+ svg.insertBefore(styleElement, svg.children[0]);
184
+ }
185
+ };
@@ -0,0 +1,24 @@
1
+ /*\
2
+
3
+ Defines behavior for number types in graph engine properties.
4
+
5
+ \*/
6
+
7
+ "use strict";
8
+
9
+ exports.name = "number";
10
+
11
+ exports.toProperty = function(info, value) {
12
+ value = parseFloat(value);
13
+ if (isNaN(value)) {
14
+ // Ignore it. It's a bad number.
15
+ return null;
16
+ }
17
+ if (info.min !== undefined && value < info.min) {
18
+ value = info.min;
19
+ }
20
+ if (info.max !== undefined && value > info.max) {
21
+ value = info.max;
22
+ }
23
+ return value;
24
+ };
@@ -0,0 +1,13 @@
1
+ /*\
2
+
3
+ Defines behavior for string types in graph engine properties.
4
+
5
+ \*/
6
+
7
+ "use strict";
8
+
9
+ exports.name = "string";
10
+
11
+ exports.toProperty = function(info, value) {
12
+ return value || null;
13
+ };
@@ -0,0 +1,17 @@
1
+ {
2
+ "directories": [
3
+ {
4
+ "path": ".",
5
+ "filesRegExp": "^.*\\.js$",
6
+ "isTiddlerFile": false,
7
+ "fields": {
8
+ "title": {
9
+ "source": "filename",
10
+ "prefix": "$:/plugins/flibbles/graph/propertytypes/"
11
+ },
12
+ "type": "application/javascript",
13
+ "module-type": "graphpropertytype"
14
+ }
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,5 @@
1
+ title: $:/plugins/flibbles/graph/readme
2
+
3
+ //tw5-graph// is a plugin which provides a toolkit of widgets to interact with graph visualization software. This plugin does not include any visualization libraries itself. It must be coupled with a library plugin that acts as an engine.
4
+
5
+ [ext[Project page is available on github.|https://github.com/flibbles/tw5-graph]]
@@ -0,0 +1,52 @@
1
+ /*\
2
+ title: $:/plugins/flibbles/graph/relink/attributes.js
3
+ type: application/javascript
4
+ module-type: relinkhtmlattributes
5
+
6
+ Relinks attributes of $properties and other graph object widgets.
7
+
8
+ \*/
9
+
10
+ "use strict";
11
+
12
+ exports.name = "graph";
13
+
14
+ var utils = require("./utils.js");
15
+ var graphObjects = Object.create(null);
16
+
17
+ $tw.modules.forEachModuleOfType("widget-subclass", function(subclass, module) {
18
+ var type = module.prototype.graphObjectType;
19
+ if (module.baseClass === "graphobject") {
20
+ graphObjects["$" + module.name] = function() { return type; };
21
+ }
22
+ });
23
+
24
+ graphObjects["$graph"] = function() { return "graph"; };
25
+
26
+ // Current behavior is if $for is specified, but it's empty or wrong, then
27
+ // this widget gets ignored for relinking, just as it gets ignored by graphs.
28
+ graphObjects["$properties"] = function(element) {
29
+ var forAttr = element.attributes["$for"];
30
+ return forAttr !== undefined? forAttr.value: "nodes";
31
+ };
32
+
33
+ exports.getHandler = function(element, attribute, options) {
34
+ var forFunc = graphObjects[element.tag];
35
+ if (forFunc) {
36
+ return processAttribute(forFunc(element), attribute, options);
37
+ }
38
+ };
39
+
40
+ function processAttribute(forObject, attribute, options) {
41
+ var name = attribute.name;
42
+ if (name[0] !== "$") {
43
+ var engine = utils.getEngine(options.wiki);
44
+ if (engine) {
45
+ var properties = engine.prototype.properties[forObject];
46
+ if (properties) {
47
+ var propertyInfo = properties[attribute.name];
48
+ return utils.getRelinker(propertyInfo);
49
+ }
50
+ }
51
+ }
52
+ };
@@ -0,0 +1,19 @@
1
+ title: $:/config/flibbles/relink/attributes/
2
+
3
+ $action-addtyped/$field: fieldname
4
+ $action-addtyped/$tiddler: title
5
+ $action-delay/$state: title
6
+ $action-modal/$tiddler: title
7
+ $action-removetyped/$field: fieldname
8
+ $action-removetyped/$tiddler: title
9
+ $boundingbox/length: filter
10
+ $boundingbox/width: filter
11
+ $edge/$from: title
12
+ $edge/$to: title
13
+ $fieldtranscriber/state: title
14
+ $fieldtranscriber/field: fieldname
15
+ $fieldtranscriber/tiddler: title
16
+ $node/$tiddler: title
17
+ $properties/$tiddler: title
18
+ $properties/$field: fieldname
19
+ $properties/$filter: filter
@@ -0,0 +1,76 @@
1
+ /*\
2
+ title: $:/plugins/flibbles/graph/relink/configprefix.js
3
+ type: application/javascript
4
+ module-type: relinkprefix
5
+
6
+ Takes care of relinking property data tiddlers
7
+ in the $:/config/flibbles/graph namespace.
8
+
9
+ \*/
10
+
11
+ "use strict";
12
+
13
+ exports.prefix = "$:/config/flibbles/graph/";
14
+
15
+ var utils = require("./utils.js");
16
+ var jsonType = "application/json";
17
+
18
+
19
+ exports.report = function(tiddler, callback, options) {
20
+ forEachProperty(options.wiki, tiddler, function(key, data, relinker) {
21
+ relinker.report(data[key], function(title, blurb, info) {
22
+ var suffix = blurb? (": " + blurb): "";
23
+ callback(title, key + suffix, info);
24
+ }, options);
25
+ });
26
+ };
27
+
28
+ exports.relink = function(tiddler, fromTitle, toTitle, changes, options) {
29
+ var changed, tiddlerData;
30
+ var type = tiddler.fields.type;
31
+ var impossible = false;
32
+ forEachProperty(options.wiki, tiddler, function(key, data, relinker) {
33
+ var lineEntry = relinker.relink(data[key], fromTitle, toTitle, options);
34
+ if (lineEntry) {
35
+ changed = true;
36
+ if (lineEntry.output) {
37
+ data[key] = lineEntry.output;
38
+ tiddlerData = data;
39
+ if (!isLegalDictionaryValue(lineEntry.output)) {
40
+ type = jsonType;
41
+ changes.type = {output: jsonType};
42
+ }
43
+ }
44
+ impossible = lineEntry.impossible || impossible;
45
+ }
46
+ });
47
+ if (changed) {
48
+ changes.text = {};
49
+ if (tiddlerData) {
50
+ var text;
51
+ if (type === jsonType) {
52
+ text = JSON.stringify(tiddlerData, null, $tw.config.preferences.jsonSpaces);
53
+ } else {
54
+ text = $tw.utils.makeTiddlerDictionary(tiddlerData);
55
+ }
56
+ changes.text.output = text;
57
+ }
58
+ if (impossible) {
59
+ changes.text.impossible = true;
60
+ }
61
+ }
62
+ };
63
+
64
+ function forEachProperty(wiki, tiddler, callback) {
65
+ var title = tiddler.fields.title;
66
+ var slashPos = title.indexOf("/", exports.prefix.length);
67
+ if (slashPos >= 0) {
68
+ var objectType = title.substring(exports.prefix.length, slashPos);
69
+ var data = wiki.getTiddlerData(title);
70
+ utils.forEachPropertyIn(data, objectType, wiki, callback);
71
+ }
72
+ };
73
+
74
+ function isLegalDictionaryValue(text) {
75
+ return text.indexOf("\n") < 0;
76
+ };
@@ -0,0 +1,39 @@
1
+ /*\
2
+ title: $:/plugins/flibbles/graph/relink/fieldedgeprefix.js
3
+ type: application/javascript
4
+ module-type: relinkprefix
5
+
6
+ Takes care of relinking all edge property files in the "field" category.
7
+
8
+ \*/
9
+
10
+ "use strict";
11
+
12
+ // We only use this module if relink-fieldnames is installed and active
13
+ // Otherewise we don't engage in renaming field edges.
14
+ if ($tw.wiki.getShadowSource("$:/plugins/flibbles/relink-fieldnames/utils.js")) {
15
+
16
+ exports.prefix = "$:/config/flibbles/graph/edges/fields/";
17
+
18
+ var utils = require("$:/plugins/flibbles/relink-fieldnames/utils.js");
19
+
20
+ exports.report = function(tiddler, callback, options) {
21
+ var field = tiddler.fields.title.substr(exports.prefix.length);
22
+ if (!utils.isReserved(field, options)) {
23
+ callback(field, "#graph field edgetype: " + field);
24
+ }
25
+ };
26
+
27
+ exports.relink = function(tiddler, fromTitle, toTitle, changes, options) {
28
+ var field = tiddler.fields.title.substr(exports.prefix.length);
29
+ if (field === fromTitle && !utils.isReserved(field, options)) {
30
+ if (utils.isReserved(toTitle, options)
31
+ || options.wiki.tiddlerExists(exports.prefix + toTitle)) {
32
+ changes.title = {impossible: true};
33
+ } else {
34
+ changes.title = {output: exports.prefix + toTitle};
35
+ }
36
+ }
37
+ };
38
+
39
+ }
@@ -0,0 +1,11 @@
1
+ title: $:/config/flibbles/relink/fields/
2
+
3
+ # This configuration already exists in Relink. We duplicate it here in case
4
+ # anyone runs tw5-graph without relink installed. We'll still recognize filter.
5
+ filter: filter
6
+
7
+ # These, however, are unique to TW5-Graph
8
+ template: title
9
+ edges.fields: filter
10
+ edges.functions: filter
11
+ popup.template: wikitext
@@ -0,0 +1,28 @@
1
+ /*\
2
+ title: $:/plugins/flibbles/graph/relink/graphprefix.js
3
+ type: application/javascript
4
+ module-type: relinkprefix
5
+
6
+ Takes care of relinking everything graphTiddler related.
7
+ Such as the tiddlers in the $:/graph/ namespace.
8
+
9
+ \*/
10
+
11
+ "use strict";
12
+
13
+ exports.prefix = "$:/graph/";
14
+
15
+ var utils = require("./utils.js");
16
+ var tag = "$:/tags/flibbles/graph/TiddlerData";
17
+
18
+ exports.report = function(tiddler, callback, options) {
19
+ if (!tiddler.hasTag(tag)) {
20
+ return utils.reportTiddlerData(tiddler, callback, options);
21
+ }
22
+ };
23
+
24
+ exports.relink = function(tiddler, fromTitle, toTitle, changes, options) {
25
+ if (!tiddler.hasTag(tag)) {
26
+ return utils.relinkTiddlerData(tiddler, fromTitle, toTitle, changes, options);
27
+ }
28
+ };
@@ -0,0 +1,3 @@
1
+ title: $:/config/flibbles/relink/operators/
2
+
3
+ gettyped: fieldname
@@ -0,0 +1,81 @@
1
+ /*\
2
+ title: $:/plugins/flibbles/graph/relink/propertyfields.js
3
+ type: application/javascript
4
+ module-type: relinkoperator
5
+
6
+ Takes care of relinking graph.* properties across all tiddlers.
7
+
8
+ \*/
9
+
10
+ "use strict";
11
+
12
+ exports.name = "graph fields";
13
+
14
+ var utils = require("./utils.js");
15
+ var fieldPrefix = "graph.";
16
+ var tag = "$:/tags/flibbles/graph/TiddlerData";
17
+
18
+ exports.report = function(tiddler, callback, options) {
19
+ if (tiddler.hasTag(tag)) {
20
+ utils.reportTiddlerData(tiddler, callback, options);
21
+ }
22
+ for (var field in tiddler.fields) {
23
+ if ($tw.utils.startsWith(field, fieldPrefix)) {
24
+ var type = field.substr(fieldPrefix.length);
25
+ var data;
26
+ try {
27
+ data = JSON.parse(tiddler.fields[field]);
28
+ } catch {}
29
+ utils.forEachPropertyIn(data, type, options.wiki, function(key, data, relinker) {
30
+ relinker.report(data[key], function(title, blurb, info) {
31
+ var prefix = "#" + type + " - " + key;
32
+ if (blurb) {
33
+ prefix += ": " + blurb;
34
+ }
35
+ callback(title, prefix, info);
36
+ }, options);
37
+ });
38
+ }
39
+ }
40
+ };
41
+
42
+ exports.relink = function(tiddler, fromTitle, toTitle, changes, options) {
43
+ if (tiddler.hasTag(tag)) {
44
+ utils.relinkTiddlerData(tiddler, fromTitle, toTitle, changes, options);
45
+ }
46
+ var changedField = {};
47
+ var impossibleFields = {};
48
+ for (var field in tiddler.fields) {
49
+ if ($tw.utils.startsWith(field, fieldPrefix)) {
50
+ var fieldData = undefined,
51
+ changed = false,
52
+ impossible = false;
53
+ var type = field.substr(fieldPrefix.length);
54
+ var data;
55
+ try {
56
+ data = JSON.parse(tiddler.fields[field]);
57
+ } catch {}
58
+ utils.forEachPropertyIn(data, type, options.wiki, function(key, data, relinker) {
59
+ var lineEntry = relinker.relink(data[key], fromTitle, toTitle, options);
60
+ if (lineEntry) {
61
+ changed = true;
62
+ if (lineEntry.output) {
63
+ data[key] = lineEntry.output;
64
+ fieldData = data;
65
+ }
66
+ impossible = lineEntry.impossible || impossible;
67
+ }
68
+ });
69
+ if (changed) {
70
+ changes[field] = {};
71
+ if (fieldData) {
72
+ var text = JSON.stringify(fieldData);
73
+ changes[field].output = text;
74
+ }
75
+ if (impossible) {
76
+ changes[field].impossible = true;
77
+ }
78
+ }
79
+ }
80
+ }
81
+ };
@@ -0,0 +1,99 @@
1
+ /*\
2
+ title: $:/plugins/flibbles/graph/relink/utils.js
3
+ type: application/javascript
4
+ module-type: library
5
+
6
+ These utilities only ever get loaded if Relink is installed.
7
+
8
+ \*/
9
+
10
+ "use strict";
11
+
12
+ var baseUtils = require("../utils.js");
13
+ var relinkUtils = require("$:/plugins/flibbles/relink/js/utils.js");
14
+ var PropertyTypes = $tw.modules.getModulesByTypeAsHashmap("graphpropertytype");
15
+
16
+ exports.forEachPropertyIn = function(data, objectType, wiki, callback) {
17
+ if (data) {
18
+ var engine = exports.getEngine(wiki);
19
+ if (engine) {
20
+ var properties = engine.prototype.properties[objectType];
21
+ if (properties) {
22
+ for (var key in data) {
23
+ var propertyInfo = properties[key];
24
+ var relinker = exports.getRelinker(propertyInfo);
25
+ if (relinker) {
26
+ callback(key, data, relinker);
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ };
33
+
34
+ exports.getRelinker = function(propertyInfo) {
35
+ var relinker;
36
+ if (propertyInfo) {
37
+ var propertyClass = PropertyTypes[propertyInfo.type];
38
+ if (propertyClass && propertyClass.type) {
39
+ relinker = relinkUtils.getType(propertyClass.type);
40
+ }
41
+ }
42
+ return relinker;
43
+ };
44
+
45
+ exports.getEngine = function(wiki) {
46
+ var value = $tw.macros.graphengine.get(wiki);
47
+ return baseUtils.getEngine(value);
48
+ };
49
+
50
+ exports.reportTiddlerData = function(tiddler, callback, options) {
51
+ var data = options.wiki.getTiddlerDataCached(tiddler.fields.title, {});
52
+ for (var title in data) {
53
+ callback(title, data[title], {soft: true});
54
+ }
55
+ };
56
+
57
+ exports.relinkTiddlerData = function(tiddler, fromTitle, toTitle, changes, options) {
58
+ var data = options.wiki.getTiddlerDataCached(tiddler.fields.title, {});
59
+ if (data[fromTitle] !== undefined) {
60
+ var newData = {};
61
+ for (var title in data) {
62
+ if (title === fromTitle) {
63
+ newData[toTitle] = data[title];
64
+ } else {
65
+ newData[title] = data[title];
66
+ }
67
+ }
68
+ var newText;
69
+ var type = tiddler.fields.type;
70
+ if (type === "application/x-tiddler-dictionary") {
71
+ if (isLegalDictionaryKey(toTitle)) {
72
+ newText = $tw.utils.makeTiddlerDictionary(newData);
73
+ } else {
74
+ type = "application/json";
75
+ changes.type = {output: type};
76
+ }
77
+ }
78
+ if (type === "application/json") {
79
+ newText = JSON.stringify(newData, null, $tw.config.preferences.jsonSpaces);
80
+ }
81
+ changes.text = {output: newText};
82
+ }
83
+ };
84
+
85
+ function isLegalDictionaryKey(title) {
86
+ // We make a microdictionary with the value and make sure we get back
87
+ // a dictionary with the key pointing to an arbitrary x
88
+ var fields = $tw.utils.parseFields(title + ":x");
89
+ var found = false;
90
+ for (var key in fields) {
91
+ if (found
92
+ || key !== title
93
+ || fields[key] !== "x") {
94
+ return false;
95
+ }
96
+ found = true;
97
+ }
98
+ return found;
99
+ };
@@ -0,0 +1,13 @@
1
+ title: $:/plugins/flibbles/graph/settings
2
+ tags: [[$:/tags/ControlPanel/SettingsTab]]
3
+ caption: Graph
4
+
5
+ \procedure filterTab() [!has[filter]] ~[subfilter{!!filter}]
6
+ \procedure settingsTabs() [[$:/tags/flibbles/graph/SettingsTab]tagging[]filter<filterTab>]
7
+
8
+ Settings page for TW5-Graph. See the [ext[project website|https://flibbles.github.io/tw5-graph]] for complete documentation.
9
+
10
+ <$transclude $variable=tabs
11
+ tabsList=<<settingsTabs>>
12
+ default={{{ [subfilter<settingsTabs>] }}}
13
+ explicitState="$:/state/flibbles/graph/settings" />