mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +00:00
Added wikitext image support
We’ve added a parser to recognise the `[img[URL or tiddler title]]` format, and an associated image widget.
This commit is contained in:
parent
ace57dd205
commit
ad4b03506a
137
core/modules/parsers/wikiparser/rules/image.js
Normal file
137
core/modules/parsers/wikiparser/rules/image.js
Normal file
@ -0,0 +1,137 @@
|
||||
/*\
|
||||
title: $:/core/modules/parsers/wikiparser/rules/image.js
|
||||
type: application/javascript
|
||||
module-type: wikirule
|
||||
|
||||
Wiki text inline rule for embedding images. For example:
|
||||
|
||||
```
|
||||
[img[http://tiddlywiki.com/fractalveg.jpg]]
|
||||
[img width=23 height=24 [http://tiddlywiki.com/fractalveg.jpg]]
|
||||
[img 23x24 [http://tiddlywiki.com/fractalveg.jpg]]
|
||||
[img width={{!!width}} height={{!!height}} [http://tiddlywiki.com/fractalveg.jpg]]
|
||||
[img {{!!width}}x{{!!height}} [http://tiddlywiki.com/fractalveg.jpg]]
|
||||
[img[Description of image|http://tiddlywiki.com/fractalveg.jpg]]
|
||||
[img[TiddlerTitle]]
|
||||
[img[Description of image|TiddlerTitle]]
|
||||
```
|
||||
|
||||
Generates the `<$image>` widget.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.name = "image";
|
||||
exports.types = {inline: true};
|
||||
|
||||
exports.init = function(parser) {
|
||||
this.parser = parser;
|
||||
};
|
||||
|
||||
exports.findNextMatch = function(startPos) {
|
||||
// Find the next tag
|
||||
this.nextImage = this.findNextImage(this.parser.source,startPos);
|
||||
return this.nextImage ? this.nextImage.start : undefined;
|
||||
};
|
||||
|
||||
exports.parse = function() {
|
||||
// Move past the match
|
||||
this.parser.pos = this.nextImage.end;
|
||||
var node = {
|
||||
type: "element",
|
||||
tag: "$image",
|
||||
attributes: this.nextImage.attributes
|
||||
};
|
||||
return [node];
|
||||
};
|
||||
|
||||
/*
|
||||
Find the next image from the current position
|
||||
*/
|
||||
exports.findNextImage = function(source,pos) {
|
||||
// A regexp for finding candidate HTML tags
|
||||
var reLookahead = /(\[img)/g;
|
||||
// Find the next candidate
|
||||
reLookahead.lastIndex = pos;
|
||||
var match = reLookahead.exec(source);
|
||||
while(match) {
|
||||
// Try to parse the candidate as a tag
|
||||
var tag = this.parseImage(source,match.index);
|
||||
// Return success
|
||||
if(tag) {
|
||||
return tag;
|
||||
}
|
||||
// Look for the next match
|
||||
reLookahead.lastIndex = match.index + 1;
|
||||
match = reLookahead.exec(source);
|
||||
}
|
||||
// Failed
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
Look for an image at the specified position. Returns null if not found, otherwise returns {type: "element", name: "$image", attributes: [], isSelfClosing:, start:, end:,}
|
||||
*/
|
||||
exports.parseImage = function(source,pos) {
|
||||
var token,
|
||||
node = {
|
||||
type: "element",
|
||||
name: "$image",
|
||||
start: pos,
|
||||
attributes: {}
|
||||
};
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for the `[img`
|
||||
token = $tw.utils.parseTokenString(source,pos,"[img");
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
pos = token.end;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Process attributes
|
||||
if(source.charAt(pos) !== "[") {
|
||||
var attribute = $tw.utils.parseAttribute(source,pos);
|
||||
while(attribute) {
|
||||
node.attributes[attribute.name] = attribute;
|
||||
pos = attribute.end;
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
if(source.charAt(pos) !== "[") {
|
||||
// Get the next attribute
|
||||
attribute = $tw.utils.parseAttribute(source,pos);
|
||||
} else {
|
||||
attribute = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Look for the `[` after the attributes
|
||||
token = $tw.utils.parseTokenString(source,pos,"[");
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
pos = token.end;
|
||||
// Skip whitespace
|
||||
pos = $tw.utils.skipWhiteSpace(source,pos);
|
||||
// Get the source up to the terminating `]]`
|
||||
token = $tw.utils.parseTokenRegExp(source,pos,/(?:([^|\]]*?)\|)?([^\]]+?)\]\]/g);
|
||||
if(!token) {
|
||||
return null;
|
||||
}
|
||||
pos = token.end;
|
||||
if(token.match[1]) {
|
||||
node.attributes.tooltip = {type: "string", value: token.match[1].trim()};
|
||||
}
|
||||
node.attributes.source = {type: "string", value: (token.match[2] || "").trim()};
|
||||
// Update the end position
|
||||
node.end = pos;
|
||||
return node;
|
||||
};
|
||||
|
||||
})();
|
123
core/modules/widgets/image.js
Normal file
123
core/modules/widgets/image.js
Normal file
@ -0,0 +1,123 @@
|
||||
/*\
|
||||
title: $:/core/modules/widgets/image.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
The image widget displays an image referenced with an external URI or with a local tiddler title.
|
||||
|
||||
```
|
||||
<$image src="TiddlerTitle" width="320" height="400" class="classnames">
|
||||
```
|
||||
|
||||
The image source can be the title of an existing tiddler or the URL of an external image.
|
||||
|
||||
External images always generate an HTML `<img>` tag.
|
||||
|
||||
Tiddlers that have a _canonical_uri field generate an HTML `<img>` tag with the src attribute containing the URI.
|
||||
|
||||
Tiddlers that contain image data generate an HTML `<img>` tag with the src attribute containing a base64 representation of the image.
|
||||
|
||||
Tiddlers that contain wikitext could be rendered to a DIV of the usual size of a tiddler, and then transformed to the size requested.
|
||||
|
||||
The width and height attributes are interpreted as a number of pixels, and do not need to include the "px" suffix.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||
|
||||
var ImageWidget = function(parseTreeNode,options) {
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
|
||||
/*
|
||||
Inherit from the base widget class
|
||||
*/
|
||||
ImageWidget.prototype = new Widget();
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
ImageWidget.prototype.render = function(parent,nextSibling) {
|
||||
this.parentDomNode = parent;
|
||||
this.computeAttributes();
|
||||
this.execute();
|
||||
// Create element
|
||||
// Determine what type of image it is
|
||||
var tag = "img", src = "",
|
||||
tiddler = this.wiki.getTiddler(this.imageSource);
|
||||
if(!tiddler) {
|
||||
// The source isn't the title of a tiddler, so we'll assume it's a URL
|
||||
src = this.imageSource;
|
||||
} else {
|
||||
// Check if it is an image tiddler
|
||||
if(this.wiki.isImageTiddler(this.imageSource)) {
|
||||
// Render the appropriate element for the image type
|
||||
var type = tiddler.fields.type,
|
||||
text = tiddler.fields.text;
|
||||
switch(type) {
|
||||
case "application/pdf":
|
||||
tag = "embed";
|
||||
src = "data:application/pdf;base64," + text;
|
||||
break;
|
||||
case "image/svg+xml":
|
||||
src = "data:image/svg+xml," + encodeURIComponent(text);
|
||||
break;
|
||||
default:
|
||||
src = "data:" + type + ";base64," + text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create the element and assign the attributes
|
||||
var domNode = this.document.createElement(tag);
|
||||
domNode.setAttribute("src",src);
|
||||
if(this.imageClass) {
|
||||
domNode.setAttribute("class",this.imageClass);
|
||||
}
|
||||
if(this.imageWidth) {
|
||||
domNode.setAttribute("width",parseInt(this.imageWidth,10) + "px");
|
||||
}
|
||||
if(this.imageHeight) {
|
||||
domNode.setAttribute("height",parseInt(this.imageHeight,10) + "px");
|
||||
}
|
||||
if(this.imageTooltip) {
|
||||
domNode.setAttribute("title",this.imageTooltip);
|
||||
}
|
||||
// Insert element
|
||||
parent.insertBefore(domNode,nextSibling);
|
||||
this.domNodes.push(domNode);
|
||||
};
|
||||
|
||||
/*
|
||||
Compute the internal state of the widget
|
||||
*/
|
||||
ImageWidget.prototype.execute = function() {
|
||||
// Get our parameters
|
||||
this.imageSource = this.getAttribute("source");
|
||||
this.imageWidth = this.getAttribute("width");
|
||||
this.imageHeight = this.getAttribute("height");
|
||||
this.imageClass = this.getAttribute("class");
|
||||
this.imageTooltip = this.getAttribute("tooltip");
|
||||
};
|
||||
|
||||
/*
|
||||
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||
*/
|
||||
ImageWidget.prototype.refresh = function(changedTiddlers) {
|
||||
var changedAttributes = this.computeAttributes();
|
||||
if(changedAttributes.source || changedAttributes.width || changedAttributes.height || changedAttributes["class"] || changedAttributes.tooltip || changedTiddlers[this.imageSource]) {
|
||||
this.refreshSelf();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
exports.image = ImageWidget;
|
||||
|
||||
})();
|
20
editions/tw5.com/tiddlers/widgets/ImageWidget.tid
Normal file
20
editions/tw5.com/tiddlers/widgets/ImageWidget.tid
Normal file
@ -0,0 +1,20 @@
|
||||
title: ImageWidget
|
||||
created: 20140416160234142
|
||||
modified: 20140416160234142
|
||||
tags: widget
|
||||
|
||||
! Introduction
|
||||
|
||||
The image widget displays images that can be specified as a remote URL or the title of a local tiddler containing the image.
|
||||
|
||||
! Content and Attributes
|
||||
|
||||
Any content of the `<$image>` widget is ignored.
|
||||
|
||||
|!Attribute |!Description |
|
||||
|source |The URL of the image, or the title of an image tiddler |
|
||||
|width |The width of the image as a number |
|
||||
|height |The height of the image |
|
||||
|tooltip |The tooltip to be displayed over the image |
|
||||
|class |CSS classes to be assigned to the `<img>` element |
|
||||
|
@ -1,10 +1,44 @@
|
||||
created: 20131205160221762
|
||||
modified: 20131205160234142
|
||||
modified: 20140416160234142
|
||||
tags: wikitext
|
||||
title: Images in WikiText
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
To display an image stored in a tiddler just transclude that tiddler:
|
||||
! Image Formatting
|
||||
|
||||
Images can be included in WikiText with the following syntax:
|
||||
|
||||
```
|
||||
[img[Motovun Jack.jpg]]
|
||||
[img[http://tiddlywiki.com/favicon.ico]]
|
||||
```
|
||||
|
||||
If the image source is the title of an image tiddler then that tiddler is directly displayed. Otherwise it is interpreted as a URL and an HTML `<img>` tag is generated with the `src` attribute containing the URL.
|
||||
|
||||
A tooltip can also be specified:
|
||||
|
||||
```
|
||||
[img[An explanatory tooltip|Motovun Jack.jpg]]
|
||||
```
|
||||
|
||||
Attributes can be provided to specify CSS classes and the image width and height:
|
||||
|
||||
```
|
||||
[img width=32 [Motovun Jack.jpg]]
|
||||
[img width=32 class="tw-image" [Motovun Jack.jpg]]
|
||||
```
|
||||
|
||||
Note that attributes can be specified as transclusions or variable references:
|
||||
|
||||
```
|
||||
[img width={{!!mywidth}} class=<<image-classes>> [Motovun Jack.jpg]]
|
||||
```
|
||||
|
||||
The image syntax is a shorthand for invoking the ImageWidget.
|
||||
|
||||
! Displaying Images via Transclusion
|
||||
|
||||
You can also display an image stored in a tiddler by transcluding that tiddler. The disadvantage of this approach is that there is no direct way to control the size of the image.
|
||||
|
||||
```
|
||||
{{Motovun Jack.jpg}}
|
||||
@ -13,3 +47,4 @@ To display an image stored in a tiddler just transclude that tiddler:
|
||||
Renders as:
|
||||
|
||||
{{Motovun Jack.jpg}}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user