Skip to content

Instantly share code, notes, and snippets.

@EvanBalster
Created December 25, 2017 06:26
Show Gist options
  • Save EvanBalster/6ad703a32fd330dc58522cf512800f71 to your computer and use it in GitHub Desktop.
Save EvanBalster/6ad703a32fd330dc58522cf512800f71 to your computer and use it in GitHub Desktop.
TiddlyWiki Attribute Modules
// widget.js
/*
Compute the current values of the attributes of the widget. Returns a hashmap of the names of the attributes that have changed
*/
var AttributeTypes = null;
Widget.prototype.computeAttributes = function() {
var changedAttributes = {},
self = this,
value;
if (!this.attributeGizmos) {
if (!AttributeTypes) {
AttributeTypes = {};
$tw.modules.applyMethods("attributevalue", AttributeTypes);
}
// First-time attribute preparation
this.attributeGizmos = {};
$tw.utils.each(this.parseTreeNode.attributes,function(attribute,name) {
// Try to instantiate an attribute type.
var AttributeType = AttributeTypes[attribute.type];
if (AttributeType) {
self.attributeGizmos[name] = new AttributeType(self, attribute);
self.attributes[name] = self.attributeGizmos[name].value;
changedAttributes[name] = true;
return true;
}
// Unknown attribute types are treated as strings.
// String attributes don't change after the first computeAttributes().
self.attributes[name] = attribute.value;
changedAttributes[name] = true;
return true;
});
}
else {
$tw.utils.each(this.attributeGizmos,function(gizmo,name) {
// Full recompute (no selectivity is available)
value = gizmo.compute();
if(self.attributes[name] !== value) {
self.attributes[name] = value;
changedAttributes[name] = true;
}
});
}
return changedAttributes;
};
// parseutils.js
/*
Look for an HTML attribute definition. Returns null if not found, otherwise returns {type: "attribute", name:, valueType: "string|indirect|macro", value:, start:, end:,}
*/
var AttributeRules = null;
exports.parseAttribute = function(source,pos) {
var node = {
start: pos
};
// Define our regexps
var reAttributeName = /([^\/\s>"'=]+)/g,
reUnquotedAttribute = /([^\/\s<>"'=]+)/g,
reFilteredValue = /\{\{\{(.+?)\}\}\}/g,
reIndirectValue = /\{\{([^\}]+)\}\}/g;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Get the attribute name
var name = $tw.utils.parseTokenRegExp(source,pos,reAttributeName);
if(!name) {
return null;
}
node.name = name.match[1];
pos = name.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for an equals sign
var token = $tw.utils.parseTokenString(source,pos,"=");
if(token) {
pos = token.end;
// Skip whitespace
pos = $tw.utils.skipWhiteSpace(source,pos);
// Look for a string literal
var stringLiteral = $tw.utils.parseStringLiteral(source,pos);
if(stringLiteral) {
node.type = "string";
node.value = stringLiteral.value;
node.end = stringLiteral.end;
return node;
}
// Load attribute rules if needed
if (!AttributeRules)
{
AttributeRules = {};
$tw.modules.applyMethods("attributerule", AttributeRules);
}
// Look for an attribute rule
var match = null;
$tw.utils.each(AttributeRules, function(rule) {
match = rule(source,pos,node);
return !match;
});
if (match) return match;
// Look for a unquoted value
var unquotedValue = $tw.utils.parseTokenRegExp(source,pos,reUnquotedAttribute);
if(unquotedValue) {
node.type = "string";
node.value = unquotedValue.match[1];
node.end = unquotedValue.end;
return node;
} else {
node.type = "string";
node.value = "true";
}
//*/
} else {
node.type = "string";
node.value = "true";
}
// Update the end position
node.end = pos;
return node;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment