Index: trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt |
— | — | @@ -803,7 +803,79 @@ |
804 | 804 | } |
805 | 805 | |
806 | 806 | |
| 807 | +/** |
| 808 | + * Image option productions, only called from the LinkHandler token stream |
| 809 | + * transformer, and only for images. |
| 810 | + */ |
| 811 | +img_options = os:img_option* c:img_caption { |
| 812 | + var options = {}; |
| 813 | + os = flatten( os ); |
| 814 | + for ( var i = 0, l = options.length; i < l; i++ ) { |
| 815 | + var o = os[i]; |
| 816 | + options[o.k] = o.v; |
| 817 | + } |
| 818 | + options.options = os; |
| 819 | + options.caption = c; |
| 820 | + return options; |
| 821 | +} |
807 | 822 | |
| 823 | +img_option |
| 824 | + = space* |
| 825 | + ( |
| 826 | + img_format |
| 827 | + / img_dimensions |
| 828 | + / img_halign |
| 829 | + / img_valign |
| 830 | + / img_link |
| 831 | + / img_attribute |
| 832 | + ) |
| 833 | + ("|" / eof) |
| 834 | + |
| 835 | +img_format |
| 836 | + = f:( 'border' / 'frameless' / 'frame' / 'thumb' / 'thumbnail' ) { |
| 837 | + return new KV( 'format', f ); |
| 838 | + } |
| 839 | + |
| 840 | +img_dimensions |
| 841 | + = x:([0-9]+)? y:('x' [0-9]+)? 'px' { |
| 842 | + if ( x === '' && y ) { |
| 843 | + return new KV( 'height', y ); |
| 844 | + } else if ( y === '' && x ) { |
| 845 | + return new KV( 'width', x ); |
| 846 | + } else { |
| 847 | + return [ new KV( 'width', x ), new KV( 'height', y ) ]; |
| 848 | + } |
| 849 | + } |
| 850 | + / 'upright' { return [ new KV( 'width', 'upright' ) ] } |
| 851 | + |
| 852 | +img_halign |
| 853 | + = a:( 'left' / 'right' / 'center' / 'none' ) { |
| 854 | + return new KV( 'halign', a ); |
| 855 | + } |
| 856 | + |
| 857 | +img_valign |
| 858 | + = a:( 'baseline' / 'sub' / 'super' / 'top' / 'text-top' |
| 859 | + / 'middle' / 'bottom' / 'text-bottom' ) { |
| 860 | + return new KV( 'valign', a ); |
| 861 | + } |
| 862 | + |
| 863 | +// External link targets are already parsed as link tokens. If we can make |
| 864 | +// sure that those cleanly convert back to the original text, then we could |
| 865 | +// re-parse them here. |
| 866 | +img_link |
| 867 | + = 'link=' t:urltext { |
| 868 | + return new KV( 'link', t ); |
| 869 | + } |
| 870 | + |
| 871 | +img_attribute |
| 872 | + = k:( 'page' / 'alt' / 'thumb' ) '=' t:preprocessor_text { |
| 873 | + return new KV( k, t ); |
| 874 | + } |
| 875 | + |
| 876 | +// catch-all |
| 877 | +img_caption = .* |
| 878 | + |
| 879 | + |
808 | 880 | /*********************************************************** |
809 | 881 | * Pre and xmlish tags |
810 | 882 | ***********************************************************/ |
Index: trunk/extensions/VisualEditor/modules/parser/ext.core.LinkHandler.js |
— | — | @@ -4,26 +4,21 @@ |
5 | 5 | * |
6 | 6 | * @author Gabriel Wicke <gwicke@wikimedia.org> |
7 | 7 | * |
8 | | - * * Collect description/parameter tokens between 'a' tags |
9 | | - * * Extract image options and add image html if target is media/image |
10 | | - * namespace |
11 | | - * * |
12 | | - * |
13 | | - * |
14 | 8 | * TODO: keep round-trip information in meta tag or the like |
15 | | - * |
16 | | - * |
17 | | - * |
18 | | - * Pro/Contra of single token vs. tags and tokens |
19 | | - * - Need to collect description tokens between a and /a |
20 | | - * + noinclude etc handled automatically by having all tokens on content level |
21 | 9 | */ |
22 | 10 | |
23 | | -var jshashes = require('jshashes'); |
| 11 | +var jshashes = require('jshashes'), |
| 12 | + PegTokenizer = require('./mediawiki.tokenizer.peg.js').PegTokenizer; |
24 | 13 | |
25 | 14 | function WikiLinkHandler( manager, isInclude ) { |
26 | 15 | this.manager = manager; |
27 | 16 | this.manager.addTransform( this.onWikiLink.bind( this ), this.rank, 'tag', 'wikilink' ); |
| 17 | + // create a new peg parser for image options.. |
| 18 | + if ( !this.imageParser ) { |
| 19 | + // Actually the regular tokenizer, but we'll call it with the |
| 20 | + // img_options production only. |
| 21 | + WikiLinkHandler.prototype.imageParser = new PegTokenizer(); |
| 22 | + } |
28 | 23 | } |
29 | 24 | |
30 | 25 | WikiLinkHandler.prototype.rank = 1.15; // after AttributeExpander |
— | — | @@ -55,28 +50,40 @@ |
56 | 51 | |
57 | 52 | |
58 | 53 | WikiLinkHandler.prototype.renderFile = function ( token, manager, cb, title ) { |
| 54 | + var env = manager.env; |
59 | 55 | // distinguish media types |
60 | 56 | // if image: parse options |
61 | 57 | // XXX: get /wiki from config! |
62 | 58 | var a = new TagTk( 'a', [ new KV( 'href', '/wiki' + title.makeLink() ) ] ); |
63 | 59 | |
64 | | - var MD5 = new jshashes.MD5, |
| 60 | + var MD5 = new jshashes.MD5(), |
65 | 61 | hash = MD5.hex( title.key ), |
| 62 | + // XXX: Hackhack.. |
66 | 63 | path = 'http://example.com/images/' + |
67 | 64 | [ hash[0], hash.substr(0, 2) ].join('/') + '/' + title.key; |
68 | 65 | |
69 | 66 | |
| 67 | + // XXX: parse options |
| 68 | + var options = this.parseImageOptions( env.lookupKV( token.attribs, 'content' ) ); |
| 69 | + // XXX: check if the file exists, generate thumbnail |
| 70 | + // XXX: render according to mode (inline, thumb, framed etc) |
70 | 71 | var img = new SelfclosingTagTk( 'img', |
71 | 72 | [ |
| 73 | + // FIXME! |
72 | 74 | new KV( 'height', '220' ), |
73 | 75 | new KV( 'width', '1941' ), |
74 | 76 | new KV( 'src', path ), |
75 | | - new KV( 'alt', title.key ), |
| 77 | + new KV( 'alt', title.key ) |
| 78 | + ] ); |
76 | 79 | |
77 | | - ] ); |
78 | 80 | return { tokens: [ a, img, new EndTagTk( 'a' )] }; |
79 | 81 | }; |
80 | 82 | |
| 83 | +WikiLinkHandler.prototype.parseImageOptions = function ( tokens ) { |
| 84 | + var text = this.manager.env.tokensToString( tokens ); |
| 85 | + |
| 86 | +}; |
| 87 | + |
81 | 88 | if (typeof module == "object") { |
82 | 89 | module.exports.WikiLinkHandler = WikiLinkHandler; |
83 | 90 | } |
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.tokenizer.peg.js |
— | — | @@ -15,8 +15,6 @@ |
16 | 16 | defines = require('./mediawiki.parser.defines.js'); |
17 | 17 | |
18 | 18 | function PegTokenizer() { |
19 | | - var pegSrcPath = path.join( __dirname, 'pegTokenizer.pegjs.txt' ); |
20 | | - this.src = fs.readFileSync( pegSrcPath, 'utf8' ); |
21 | 19 | } |
22 | 20 | |
23 | 21 | |
— | — | @@ -35,6 +33,8 @@ |
36 | 34 | PegTokenizer.prototype.process = function( text ) { |
37 | 35 | var out, err; |
38 | 36 | if ( !this.parser ) { |
| 37 | + var pegSrcPath = path.join( __dirname, 'pegTokenizer.pegjs.txt' ); |
| 38 | + this.src = fs.readFileSync( pegSrcPath, 'utf8' ); |
39 | 39 | // Only create a single parser, as parse() is a static method. |
40 | 40 | var parserSource = PEG.buildParser(this.src).toSource(); |
41 | 41 | //console.warn( parserSource ); |