mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
Parser: Fix inconsistent html-encoding of {{#tag}} calls [#312]
This commit is contained in:
parent
54ad1d697d
commit
1d54b8a756
31
400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr.java
Normal file
31
400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||
public interface Tag_html_mkr {
|
||||
Tag_html_wkr Tag__create(Xowe_wiki wiki, Xop_ctx ctx);
|
||||
}
|
||||
class Tag_html_mkr_noop implements Tag_html_mkr {
|
||||
public Tag_html_wkr Tag__create(Xowe_wiki wiki, Xop_ctx ctx) {return Tag_html_wkr_noop.Instance;}
|
||||
}
|
||||
class Tag_html_mkr_basic implements Tag_html_mkr {
|
||||
private final boolean atrs_encode;
|
||||
public Tag_html_mkr_basic(boolean atrs_encode) {
|
||||
this.atrs_encode = atrs_encode;
|
||||
}
|
||||
public Tag_html_wkr Tag__create(Xowe_wiki wiki, Xop_ctx ctx) {
|
||||
return new Tag_html_wkr_basic(wiki.Utl__bfr_mkr().Get_b512(), atrs_encode);
|
||||
}
|
||||
}
|
30
400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr_.java
Normal file
30
400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr_.java
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||
public class Tag_html_mkr_ {
|
||||
// This maker is being applied to:
|
||||
// * mapframe and maplink: currently unsupported by XOWA, but some pages will pass in HTML which will break tag; EX:{{#tag:mapframe||body='<div id="a">'}} PAGE:fr.v:France; DATE:2017-06-01
|
||||
public static final Tag_html_mkr Noop = new Tag_html_mkr_noop();
|
||||
|
||||
// This maker is being applied to:
|
||||
// - built-in xndes like b,i,li as specified by "/includes/parser/CoreParserFunctions.php|tagObj"
|
||||
// - built-in xndes like pre,nowiki,gallery,indicator with explicit setHook calls in "/includes/parser/CoreTagHooks.php"
|
||||
// - extension xndes like ref,poem with setHook calls from "/includes/parser/Parser.php|extensionSubstitution"
|
||||
// The latter two should be redirected to new mkrs
|
||||
public static Tag_html_mkr Basic(boolean atrs_encode) {
|
||||
return new Tag_html_mkr_basic(atrs_encode);
|
||||
}
|
||||
}
|
81
400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_wkr.java
Normal file
81
400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_wkr.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*;
|
||||
import gplx.xowa.parsers.*;
|
||||
import gplx.langs.htmls.encoders.*;
|
||||
public interface Tag_html_wkr {
|
||||
void Tag__process_name(byte[] name);
|
||||
void Tag__process_attr(byte[] key, byte[] val);
|
||||
void Tag__process_body(byte[] body);
|
||||
byte[] Tag__build(Xowe_wiki wiki, Xop_ctx ctx);
|
||||
void Tag__rls();
|
||||
}
|
||||
class Tag_html_wkr_noop implements Tag_html_wkr {
|
||||
public void Tag__process_name(byte[] name) {}
|
||||
public void Tag__process_attr(byte[] key, byte[] val) {}
|
||||
public void Tag__process_body(byte[] body) {}
|
||||
public byte[] Tag__build(Xowe_wiki wiki, Xop_ctx ctx) {return Bry_.Empty;}
|
||||
public void Tag__rls() {}
|
||||
public static final Tag_html_wkr_noop Instance = new Tag_html_wkr_noop(); Tag_html_wkr_noop() {}
|
||||
}
|
||||
class Tag_html_wkr_basic implements Tag_html_wkr {
|
||||
private final boolean atrs_encode;
|
||||
private final Bry_bfr tmp_bfr;
|
||||
private byte[] tag_name;
|
||||
public Tag_html_wkr_basic(Bry_bfr tmp_bfr, boolean atrs_encode) {
|
||||
this.tmp_bfr = tmp_bfr;
|
||||
this.atrs_encode = atrs_encode;
|
||||
}
|
||||
public void Tag__process_name(byte[] tag_name) {
|
||||
this.tag_name = tag_name;
|
||||
tmp_bfr.Add_byte(Byte_ascii.Lt).Add(tag_name); // EX: "<ref"
|
||||
}
|
||||
public void Tag__process_attr(byte[] key, byte[] val) {
|
||||
int val_len = Bry_.Len(val);
|
||||
if (val_len == 0) return; // ignore atrs with empty vals: EX:{{#tag:ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич DATE:2014-07-03
|
||||
|
||||
// NOTE: this behavior emulates /includes/parser/CoreParserFunctions.php|tagObj; REF: $attrText .= ' ' . htmlspecialchars( $name ) . '="' . htmlspecialchars( $value ) . '"';
|
||||
// write key
|
||||
tmp_bfr.Add_byte(Byte_ascii.Space); // write space between html_args
|
||||
int key_len = Bry_.Len(key);
|
||||
if (key_len > 0) {
|
||||
if (atrs_encode)
|
||||
Gfo_url_encoder_.Id.Encode(tmp_bfr, key, 0, key_len);
|
||||
else
|
||||
tmp_bfr.Add(key);
|
||||
tmp_bfr.Add_byte(Byte_ascii.Eq);
|
||||
}
|
||||
|
||||
// write val
|
||||
tmp_bfr.Add_byte(Byte_ascii.Quote);
|
||||
if (atrs_encode)
|
||||
Gfo_url_encoder_.Id.Encode(tmp_bfr, val, 0, val_len);
|
||||
else
|
||||
tmp_bfr.Add(val);
|
||||
tmp_bfr.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
public void Tag__process_body(byte[] body) {
|
||||
tmp_bfr.Add_byte(Byte_ascii.Gt);
|
||||
tmp_bfr.Add(body);
|
||||
tmp_bfr.Add_byte(Byte_ascii.Lt).Add_byte(Byte_ascii.Slash).Add(tag_name).Add_byte(Byte_ascii.Gt); // EX: "</ref>"
|
||||
}
|
||||
public byte[] Tag__build(Xowe_wiki wiki, Xop_ctx ctx) {
|
||||
return tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
public void Tag__rls() {
|
||||
tmp_bfr.Mkr_rls();
|
||||
}
|
||||
}
|
@ -57,6 +57,7 @@ public class Xop_xnde_tag {
|
||||
public Xop_xnde_tag Block_close_bgn_() {block_close = Block_bgn; return this;} public Xop_xnde_tag Block_close_end_() {block_close = Block_end; return this;}
|
||||
public boolean Xtn_auto_close() {return xtn_auto_close;} public Xop_xnde_tag Xtn_auto_close_() {xtn_auto_close = true; return this;} private boolean xtn_auto_close;
|
||||
public boolean Ignore_empty() {return ignore_empty;} public Xop_xnde_tag Ignore_empty_() {ignore_empty = true; return this;} private boolean ignore_empty;
|
||||
public Tag_html_mkr Html_mkr() {return html_mkr;} public Xop_xnde_tag Html_mkr_(Tag_html_mkr v) {this.html_mkr = v; return this;} private Tag_html_mkr html_mkr;
|
||||
public boolean Xtn_skips_template_args() {return xtn_skips_template_args;} public Xop_xnde_tag Xtn_skips_template_args_() {xtn_skips_template_args = true; return this;} private boolean xtn_skips_template_args;
|
||||
public Ordered_hash Langs() {return langs;} private Ordered_hash langs; private Int_obj_ref langs_key;
|
||||
public Xop_xnde_tag Langs_(int lang_code, String name) {
|
||||
|
@ -274,10 +274,10 @@ public class Xop_xnde_tag_ {
|
||||
, Tag__tabber = New(Tid__tabber, "tabber").Xtn_mw_()
|
||||
, Tag__tabview = New(Tid__tabview, "tabview").Xtn_mw_()
|
||||
, Tag__xowa_wiki_setup = New(Tid__xowa_wiki_setup, "xowa_Wiki_setup").Xtn_()
|
||||
, Tag__mapframe = New(Tid__mapframe, "mapframe").Xtn_mw_()
|
||||
, Tag__maplink = New(Tid__maplink, "maplink").Xtn_mw_()
|
||||
, Tag__mapframe = New(Tid__mapframe, "mapframe").Xtn_mw_().Html_mkr_(Tag_html_mkr_.Noop)
|
||||
, Tag__maplink = New(Tid__maplink, "maplink").Xtn_mw_().Html_mkr_(Tag_html_mkr_.Noop)
|
||||
, Tag__meta = New(Tid__meta, "meta")
|
||||
, Tag__link = New(Tid__link, "link")
|
||||
, Tag__template_styles = New(Tid__template_styles, "templatestyles").Xtn_()
|
||||
, Tag__template_styles = New(Tid__template_styles, "templatestyles").Xtn_().Html_mkr_(Tag_html_mkr_.Basic(false))
|
||||
;
|
||||
}
|
||||
|
@ -17,36 +17,41 @@ package gplx.xowa.parsers.xndes; import gplx.*; import gplx.xowa.*; import gplx.
|
||||
import gplx.core.btries.*;
|
||||
public class Xop_xnde_tag_regy {
|
||||
private boolean init_needed = true;
|
||||
private final Btrie_slim_mgr // NOTE:ci.utf8; he.s and <section> alias DATE:2014-07-18
|
||||
trie_tmpl = Btrie_slim_mgr.ci_u8()
|
||||
, trie_wtxt_main = Btrie_slim_mgr.ci_u8()
|
||||
, trie_wtxt_tmpl = Btrie_slim_mgr.ci_u8();
|
||||
private final Btrie_slim_mgr // NOTE:ci.utf8; he.s and <section> alias DATE:2014-07-18
|
||||
trie_tmpl = Btrie_slim_mgr.ci_u8()
|
||||
, trie_wtxt_main = Btrie_slim_mgr.ci_u8()
|
||||
, trie_wtxt_tmpl = Btrie_slim_mgr.ci_u8()
|
||||
;
|
||||
public Xop_xnde_tag Get_tag_in_tmpl(byte[] tag) {
|
||||
if (init_needed) Init_by_hash(null); // TEST:
|
||||
return (Xop_xnde_tag)trie_tmpl.Match_bgn(tag, 0, tag.length);
|
||||
}
|
||||
public Btrie_slim_mgr Get_trie(int i) {
|
||||
if (init_needed) Init_by_hash(null); // TEST:
|
||||
if (init_needed) Init_by_hash(null); // TEST:
|
||||
switch (i) {
|
||||
case Xop_parser_tid_.Tid__defn: return trie_tmpl;
|
||||
case Xop_parser_tid_.Tid__tmpl: return trie_wtxt_tmpl;
|
||||
case Xop_parser_tid_.Tid__wtxt: return trie_wtxt_main;
|
||||
case Xop_parser_tid_.Tid__null: default: return trie_wtxt_tmpl; // TODO_OLD: should throw Err_.new_unhandled(i);
|
||||
case Xop_parser_tid_.Tid__defn: return trie_tmpl;
|
||||
case Xop_parser_tid_.Tid__tmpl: return trie_wtxt_tmpl;
|
||||
case Xop_parser_tid_.Tid__wtxt: return trie_wtxt_main;
|
||||
default: throw Err_.new_unhandled(i);
|
||||
}
|
||||
}
|
||||
public void Init_by_meta(Hash_adp_bry xtn_hash) {Init_by_hash(xtn_hash);}
|
||||
private void Init_by_hash(Hash_adp_bry xtn_hash) {
|
||||
this.init_needed = false;
|
||||
Init_trie(trie_tmpl , xtn_hash, Bool_.Y);
|
||||
Init_trie(trie_wtxt_tmpl , xtn_hash, Bool_.Y);
|
||||
Init_trie(trie_wtxt_main , xtn_hash, Bool_.N);
|
||||
Init_trie(trie_tmpl , xtn_hash, Bool_.Y);
|
||||
Init_trie(trie_wtxt_tmpl , xtn_hash, Bool_.Y);
|
||||
Init_trie(trie_wtxt_main , xtn_hash, Bool_.N);
|
||||
}
|
||||
private void Init_trie(Btrie_slim_mgr trie, Hash_adp_bry xtn_hash, boolean is_tmpl) {
|
||||
int len = Xop_xnde_tag_.Tid__len;
|
||||
Xop_xnde_tag[] ary = Xop_xnde_tag_.Ary;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xop_xnde_tag xnde = ary[i];
|
||||
if (Ignore_xnde(xtn_hash, xnde)) continue; // skip; xtn is not defined in site_meta_db
|
||||
if (is_tmpl && !xnde.Xtn()) continue; // is_tmpl and basic_xnde; EX: <b>
|
||||
if (Ignore_xnde(xtn_hash, xnde)) continue; // skip; xtn is not defined in site_meta_db
|
||||
if (is_tmpl && !xnde.Xtn()) continue; // is_tmpl and basic_xnde; EX: <b>
|
||||
Add_itm(trie, xnde);
|
||||
}
|
||||
if (is_tmpl) { // is_tmpl also has <nowiki>, <includeonly>, <noinclude>, <onlyinclude>
|
||||
if (is_tmpl) { // is_tmpl also has <nowiki>, <includeonly>, <noinclude>, <onlyinclude>
|
||||
Add_itm(trie, Xop_xnde_tag_.Tag__nowiki);
|
||||
Add_itm(trie, Xop_xnde_tag_.Tag__includeonly);
|
||||
Add_itm(trie, Xop_xnde_tag_.Tag__noinclude);
|
||||
@ -58,9 +63,10 @@ public class Xop_xnde_tag_regy {
|
||||
&& xnde.Xtn_mw() // only apply filter to xtn_xnde, not basic_xnde; EX: <dynamicpagelist> not <table>
|
||||
&& !xtn_hash.Has(xnde.Name_bry()) // xtn_xnde is not in xtn_hash
|
||||
&& !Int_.In(xnde.Id(), Xop_xnde_tag_.Tid__translate, Xop_xnde_tag_.Tid__languages) // always include <translate> and <languages>; TODO_OLD:filter out when extensions supported in site_cfg; DATE:2015-10-13
|
||||
; // skip; xtn is not defined in site_meta_db
|
||||
;
|
||||
}
|
||||
private void Add_itm(Btrie_slim_mgr trie, Xop_xnde_tag xnde) {
|
||||
// register in individual trie
|
||||
trie.Add_obj(xnde.Name_bry(), xnde);
|
||||
Ordered_hash langs = xnde.Langs();
|
||||
if (langs != null) { // tag has langs; EX: <section>; DATE:2014-07-18
|
||||
|
@ -16,12 +16,23 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx.xowa.xtns.pfuncs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; import gplx.xowa.langs.kwds.*;
|
||||
import gplx.xowa.xtns.pfuncs.ifs.*; import gplx.xowa.xtns.pfuncs.times.*; import gplx.xowa.xtns.pfuncs.numbers.*; import gplx.xowa.xtns.pfuncs.ttls.*; import gplx.xowa.xtns.pfuncs.langs.*; import gplx.xowa.xtns.pfuncs.strings.*; import gplx.xowa.xtns.pfuncs.stringutils.*; import gplx.xowa.xtns.pfuncs.pages.*; import gplx.xowa.xtns.pfuncs.wikis.*;
|
||||
import gplx.xowa.xtns.pfuncs.ifs.*; import gplx.xowa.xtns.pfuncs.times.*; import gplx.xowa.xtns.pfuncs.numbers.*; import gplx.xowa.xtns.pfuncs.ttls.*; import gplx.xowa.xtns.pfuncs.langs.*; import gplx.xowa.xtns.pfuncs.strings.*; import gplx.xowa.xtns.pfuncs.tags.*; import gplx.xowa.xtns.pfuncs.stringutils.*; import gplx.xowa.xtns.pfuncs.pages.*; import gplx.xowa.xtns.pfuncs.wikis.*;
|
||||
import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*;
|
||||
import gplx.xowa.wikis.domains.*;
|
||||
public class Pf_func_ {
|
||||
public static byte[] Eval_arg_or_empty(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, int self_args_len, int i) {return Eval_arg_or(ctx, src, caller, self, self_args_len, i, Bry_.Empty);}
|
||||
public static final byte Name_dlm = Byte_ascii.Colon;
|
||||
public static boolean Eval_arg_to_kvp(byte[][] rslt, Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, int self_args_len, Bry_bfr tmp_bfr, int i) {
|
||||
if (i >= self_args_len) return false;
|
||||
// NOTE: must call Tmpl_evaluate; don't try to parse key / val by hand; EX:{{#tag:pre|a|{{#switch:a|a=id}}=c}}
|
||||
Arg_nde_tkn nde = self.Args_get_by_idx(i);
|
||||
nde.Key_tkn().Tmpl_evaluate(ctx, src, caller, tmp_bfr);
|
||||
rslt[0] = tmp_bfr.To_bry_and_clear_and_trim();
|
||||
|
||||
nde.Val_tkn().Tmpl_evaluate(ctx, src, caller, tmp_bfr);
|
||||
rslt[1] = tmp_bfr.To_bry_and_clear_and_trim();
|
||||
return true;
|
||||
}
|
||||
public static byte[] Eval_arg_or_empty(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, int self_args_len, int i) {return Eval_arg_or(ctx, src, caller, self, self_args_len, i, Bry_.Empty);}
|
||||
public static byte[] Eval_arg_or(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, int self_args_len, int i, byte[] or) {
|
||||
if (i >= self_args_len) return or;
|
||||
Arg_nde_tkn nde = self.Args_get_by_idx(i);
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*;
|
||||
import gplx.xowa.parsers.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.tmpls.*;
|
||||
public class Pfunc_tag extends Pf_func_base {// REF:CoreParserFunctions.php
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_misc_tag;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_tag().Name_(name);}
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
|
||||
// make <xnde> based on {{#tag}}; EX: {{#tag:ref|a|name=1}} -> <ref name='1'>a</ref>
|
||||
Bry_bfr tmp_bfr = ctx.Wiki().Utl__bfr_mkr().Get_b512();
|
||||
try {
|
||||
// get vars
|
||||
byte[] tag_name = Eval_argx(ctx, src, caller, self); if (tag_name.length == 0) return;
|
||||
|
||||
// open tag
|
||||
tmp_bfr.Add_byte(Byte_ascii.Lt).Add(tag_name); // EX: "<ref"
|
||||
|
||||
// iterate args and build attributes; EX: "|a=1|b=2" -> "a='1' b='2'"
|
||||
int args_len = self.Args_len();
|
||||
if (args_len > 1) { // NOTE: starting from 1 b/c 0 is innerText
|
||||
Pfunc_tag_kvp_wtr kvp_wtr = new Pfunc_tag_kvp_wtr();
|
||||
for (int i = 1; i < args_len; i++) {
|
||||
byte[] arg = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, i); // NOTE: must evaluate arg; don't try to parse arg_tkn's key / val separately; EX:{{#tag:pre|a|{{#switch:a|a=id}}=c}}
|
||||
if (arg.length == 0) continue; // skip empty atrs
|
||||
tmp_bfr.Add_byte(Byte_ascii.Space); // write space between html_args
|
||||
kvp_wtr.Write_as_html_atr(tmp_bfr, arg); // write html_arg
|
||||
}
|
||||
}
|
||||
tmp_bfr.Add_byte(Byte_ascii.Gt); // EX: ">"
|
||||
|
||||
// add innerText;
|
||||
if (args_len > 0) // handle no args; EX: "{{#tag:ref}}" -> "<ref></ref>"
|
||||
tmp_bfr.Add(Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 0));
|
||||
|
||||
// close tag
|
||||
tmp_bfr.Add_byte(Byte_ascii.Lt).Add_byte(Byte_ascii.Slash).Add(tag_name).Add_byte(Byte_ascii.Gt); // EX: "</ref>"
|
||||
|
||||
// add to UNIQ hash; DATE:2017-03-31
|
||||
byte[] val = tmp_bfr.To_bry_and_clear();
|
||||
byte[] key = ctx.Wiki().Parser_mgr().Uniq_mgr().Add(Bool_.Y, tag_name, val);
|
||||
bfr.Add(key);
|
||||
}
|
||||
finally {tmp_bfr.Mkr_rls();}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pfunc_tag_kvp_wtr {
|
||||
private int key_bgn, key_end;
|
||||
private int val_bgn, val_end;
|
||||
public void Write_as_html_atr(Bry_bfr tmp, byte[] kvp_bry) {
|
||||
Parse(kvp_bry);
|
||||
|
||||
// write as html
|
||||
if (val_bgn == -1) return; // ignore atrs with empty vals: EX:{{#tag:ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич DATE:2014-07-03
|
||||
if (key_bgn != -1)
|
||||
tmp.Add(Bry_.Mid(kvp_bry, key_bgn, key_end));
|
||||
if (val_bgn != -1) {
|
||||
if (key_bgn != -1)
|
||||
tmp.Add_byte(Byte_ascii.Eq);
|
||||
tmp.Add_byte(Byte_ascii.Quote);
|
||||
// gplx.langs.htmls.encoders.Gfo_url_encoder_.Id.Encode(tmp, kvp_bry, val_bgn, val_end);// PURPOSE: escape html in atrs; PAGE:fr.w:France; DATE:2017-06-01
|
||||
gplx.langs.htmls.Gfh_utl.Escape_html_to_bfr(tmp, kvp_bry, val_bgn, val_end, true, true, true, true, true);
|
||||
tmp.Add_byte(Byte_ascii.Quote);
|
||||
}
|
||||
}
|
||||
private void Parse(byte[] src) {
|
||||
this.key_bgn = this.key_end = this.val_bgn = this.val_end = -1; // NOTE: must clear; DATE:2014-07-20
|
||||
int itm_bgn = -1, itm_end = -1, src_len = src.length;
|
||||
byte quote_byte = Byte_ascii.Null;
|
||||
boolean mode_is_key = true;
|
||||
for (int i = 0; i < src_len; ++i) {
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Eq:
|
||||
if (mode_is_key) {
|
||||
mode_is_key = false;
|
||||
if (itm_end == -1) itm_end = i;
|
||||
this.key_bgn = itm_bgn;
|
||||
this.key_end = itm_end;
|
||||
itm_bgn = itm_end = -1;
|
||||
}
|
||||
break;
|
||||
// quote-char encountered ...
|
||||
// NOTE: quotes cannot be escaped; also, in case of multiple quotes (a="b"c") regx uses first two quotes; REF:MW:CoreParserFunctions.php|tagObj
|
||||
case Byte_ascii.Quote:
|
||||
case Byte_ascii.Apos:
|
||||
if (itm_bgn == -1) { // ... quote hasn't started; start quote
|
||||
itm_bgn = i + 1;
|
||||
quote_byte = b;
|
||||
}
|
||||
else if (itm_end == -1 // ... quote has started and quote hasn't ended; note that this ends quote immediately; EX: 'id="a"b"' -> 'id=a' x> 'id=a"b'
|
||||
&& b == quote_byte) // handle alternating quotes; EX: id="a'b" -> id=a'b x> id=a; PAGE:en.s:The_formative_period_in_Colby%27s_history; DATE:2016-06-23
|
||||
itm_end = i;
|
||||
break;
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:// NOTE: do not need to handle ws, b/c argBldr will trim it EX: {{#tag|a| b = c }}; " b " and " c " are automatically trimmed
|
||||
break;
|
||||
default:
|
||||
if (itm_bgn == -1) itm_bgn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itm_end == -1) itm_end = src_len;
|
||||
this.val_bgn = itm_bgn;
|
||||
this.val_end = itm_end;
|
||||
}
|
||||
}
|
103
400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag.java
Normal file
103
400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag.java
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012-2017 gnosygnu@gmail.com
|
||||
|
||||
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
|
||||
or alternatively under the terms of the Apache License Version 2.0.
|
||||
|
||||
You may use XOWA according to either of these licenses as is most appropriate
|
||||
for your project on a case-by-case basis.
|
||||
|
||||
The terms of each license can be found in the source code repository:
|
||||
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.tags; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*;
|
||||
import gplx.xowa.parsers.*; import gplx.xowa.parsers.xndes.*; import gplx.xowa.parsers.tmpls.*;
|
||||
public class Pfunc_tag extends Pf_func_base {// REF:/includes/parser/CoreParserFunctions.php|tagObj
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_misc_tag;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_tag().Name_(name);}
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
|
||||
// make <xnde> based on {{#tag}}; EX: {{#tag:ref|a|name=1}} -> <ref name='1'>a</ref>
|
||||
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
|
||||
// get tag_name
|
||||
byte[] tag_name = Eval_argx(ctx, src, caller, self);
|
||||
if (tag_name.length == 0) return; // EX: {{#tag}}
|
||||
|
||||
// get html_mkr; similar to MW "call_user_func_array"
|
||||
Tag_html_mkr html_mkr = null;
|
||||
Xop_xnde_tag xnde_tkn = ctx.Xnde_tag_regy().Get_tag_in_tmpl(tag_name);
|
||||
if (xnde_tkn != null) html_mkr = xnde_tkn.Html_mkr();
|
||||
if (html_mkr == null) html_mkr = Tag_html_mkr_.Basic(true);
|
||||
|
||||
// build html
|
||||
Xowe_wiki wiki = ctx.Wiki();
|
||||
Tag_html_wkr html_wkr = html_mkr.Tag__create(wiki, ctx);
|
||||
try {
|
||||
// process name
|
||||
html_wkr.Tag__process_name(tag_name);
|
||||
|
||||
// process args; EX: "|a=1|b=2" -> "a='1' b='2'"
|
||||
int args_len = self.Args_len();
|
||||
Eval_attrs(ctx, wiki, caller, self, src, args_len, html_wkr);
|
||||
|
||||
// process body
|
||||
byte[] body = args_len == 0
|
||||
? Bry_.Empty
|
||||
: Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, args_len, 0);
|
||||
html_wkr.Tag__process_body(body);
|
||||
|
||||
// add to UNIQ hash; DATE:2017-03-31
|
||||
byte[] val = html_wkr.Tag__build(ctx.Wiki(), ctx);
|
||||
byte[] key = wiki.Parser_mgr().Uniq_mgr().Add(Bool_.Y, tag_name, val);
|
||||
bfr.Add(key);
|
||||
}
|
||||
finally {
|
||||
html_wkr.Tag__rls();
|
||||
}
|
||||
}
|
||||
private void Eval_attrs(Xop_ctx ctx, Xowe_wiki wiki, Xot_invk caller, Xot_invk self, byte[] src, int args_len, Tag_html_wkr html_wkr) {
|
||||
if (args_len <= 1) return; // NOTE: 1 b/c 0 is innerText
|
||||
Bry_bfr atr_bfr = wiki.Utl__bfr_mkr().Get_b512();
|
||||
try {
|
||||
byte[][] kvp = new byte[2][];
|
||||
for (int i = 1; i < args_len; i++) {
|
||||
// extract kv
|
||||
if (!Pf_func_.Eval_arg_to_kvp(kvp, ctx, src, caller, self, args_len, atr_bfr, i)) // skip empty atrs
|
||||
continue;
|
||||
|
||||
// strip flanking-matching quotes; EX: "'abc'" -> "abc"; REF.MW:preg_match( '/^(?:["\'](.+)["\']|""|\'\')$/s', $value, $m )
|
||||
byte[] atr_val = kvp[1];
|
||||
int atr_len = Bry_.Len(atr_val);
|
||||
if (atr_len > 1) {
|
||||
int atr_bgn = 0;
|
||||
boolean trim_bgn = false, trim_end = false;
|
||||
switch (atr_val[0]) {
|
||||
case Byte_ascii.Quote:
|
||||
case Byte_ascii.Apos:
|
||||
atr_bgn++;
|
||||
trim_bgn = true;
|
||||
break;
|
||||
}
|
||||
int atr_end = atr_len - 1;
|
||||
switch (atr_val[atr_end]) {
|
||||
case Byte_ascii.Quote:
|
||||
case Byte_ascii.Apos:
|
||||
trim_end = true;
|
||||
break;
|
||||
}
|
||||
if (trim_bgn && trim_end)
|
||||
kvp[1] = Bry_.Mid(atr_val, atr_bgn, atr_end);
|
||||
}
|
||||
|
||||
// process attr
|
||||
html_wkr.Tag__process_attr(kvp[0], kvp[1]);
|
||||
}
|
||||
} finally {
|
||||
atr_bfr.Mkr_rls();
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ The terms of each license can be found in the source code repository:
|
||||
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
|
||||
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.strings; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
package gplx.xowa.xtns.pfuncs.tags; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pfunc_tag_tst {
|
||||
@Before public void init() {fxt.Reset();} private final Xop_fxt fxt = new Xop_fxt();
|
||||
@ -22,16 +22,14 @@ public class Pfunc_tag_tst {
|
||||
@Test public void Val_apos() {fxt.Test_html_full_str("{{#tag:pre|a|id='b'}}" , "<pre id=\"b\">a</pre>");}
|
||||
@Test public void Val_quote() {fxt.Test_html_full_str("{{#tag:pre|a|id=\"b\"}}" , "<pre id=\"b\">a</pre>");}
|
||||
@Test public void Val_empty() {fxt.Test_html_full_str("{{#tag:pre|a|id=}}" , "<pre>a</pre>");} // PURPOSE: ignore atrs with no val; EX:{{#ref||group=}} PAGE:ru.w:Колчак,_Александр_Васильевич; DATE:2014-07-03
|
||||
@Test public void Val_multiple() {fxt.Test_html_full_str("{{#tag:pre|c|id='a'b'}}" , "<pre id=\"a.27b\">c</pre>");} // PURPOSE: multiple quotes should use 1st and nth; DATE:2018-12-24
|
||||
@Test public void Val_quote_w_apos() {fxt.Test_html_full_str("{{#tag:pre|c|id=\"a'b\"}}" , "<pre id=\"a.27b\">c</pre>");} // PURPOSE.fix: tag was not handling apos within quotes; PAGE:en.s:The_formative_period_in_Colby%27s_history DATE:2016-06-23
|
||||
@Test public void Val_mismatched() {fxt.Test_html_full_str("{{#tag:pre|c|id=\"a'}}" , "<pre id=\"a\">c</pre>");} // PURPOSE: emulate MW behavior; DATE:2018-12-24
|
||||
@Test public void Tmpl() {fxt.Test_html_full_str("{{#tag:pre|a|{{#switch:a|a=id}}=c}}" , "<pre id=\"c\">a</pre>");} // PURPOSE: args must be evaluated
|
||||
@Test public void Ws_all() {fxt.Test_html_full_str("{{#tag:pre|a| id = b }}" , "<pre id=\"b\">a</pre>");}
|
||||
@Test public void Ws_quoted() {fxt.Test_html_full_str("{{#tag:pre|a| id = ' b ' }}" , "<pre id=\"_b_\">a</pre>");}
|
||||
@Test public void Err_bad_key() {fxt.Test_html_full_str("{{#tag:pre|a|id=val|b}}" , "<pre id=\"val\">a</pre>");} // PURPOSE: b was failing b/c id was larger and key_end set to 4 (whereas b was len=1)
|
||||
@Test public void Html_is_escaped() {fxt.Test_html_full_str("{{#tag:pre|a|id='<br/>'}}" , "<pre id=\".3Cbr.2F.3E\">a</pre>");} // PURPOSE: escape html in atrs; PAGE:fr.w:France; DATE:2017-06-01
|
||||
// @Test public void Missing_val() {fxt.ini_Msg(Mwl_tag_rsc.Instance.Invalid).Test_parse_tmpl_str_test("{{#tag:pre|a|id=}}" , "{{test}}" , "");} // see {{Reflist|colwidth=30em}} -> <ref group=a>a</ref>{{#tag:references||group=}} -> ""
|
||||
// @Test public void Err() {
|
||||
// fxt.Test_parse_tmpl_str_test("{{#tag:ref|George Robertson announced in January 2003 that he would be stepping down in December.<ref> {{cite news|title =NATO Secretary General to Leave His Post in December After 4 Years |first = Craig | last = Smith | work = The New York Times | date = January 23, 2003| url = http://www.nytimes.com/2003/01/23/world/nato-secretary-general-to-leave-his-post-in-december-after-4-years.html?scp=2&sq=lord+robertson&st=nyt|accessdate = 2009-03-29}}</ref> Jaap de Hoop Scheffer was selected as his successor, but could not assume the office until January 2004 because of his commitment in the Dutch Parliament.<ref> {{cite news|title = Jaap de Hoop Scheffer | work = Newsmakers | issue = 1 | publisher = Thomson Gale | date = January 1, 2005}}</ref> Robertson was asked to extend his term until Scheffer was ready, but declined, so Minuto-Rizzo, the Deputy Secretary General, took over in the interim.<ref name =\"ncsd\" /> |group=N|}}"
|
||||
// , "{{test}}" , "<pre id=\" b \">a</pre>");}
|
||||
@Test public void Nested_tmpl() { // PURPOSE: nested template must get re-evaluated; EX:de.wikipedia.org/wiki/Freiburg_im_Breisgau; DATE:2013-12-18;
|
||||
fxt.Init_page_create("Template:!", "|");
|
||||
fxt.Init_page_create("Template:A", "{{#ifeq:{{{1}}}|expd|pass|fail}}");
|
@ -30,7 +30,6 @@ public class Template_styles_nde implements Xox_xnde, Mwh_atr_itm_owner2 {
|
||||
public void Xtn_parse(Xowe_wiki wiki, Xop_ctx ctx, Xop_root_tkn root, byte[] src, Xop_xnde_tkn xnde) {
|
||||
ctx.Para().Process_block__xnde(xnde.Tag(), Xop_xnde_tag.Block_bgn);
|
||||
Xox_xnde_.Parse_xatrs(wiki, this, xatrs_hash, src, xnde);
|
||||
|
||||
// get css_ttl
|
||||
css_ttl = wiki.Ttl_parse(css_ttl_bry);
|
||||
if (css_ttl == null) {
|
||||
|
@ -43,6 +43,13 @@ public class Template_styles_nde_tst {
|
||||
, Style_red
|
||||
);
|
||||
}
|
||||
@Test public void Tag() { // PURPOSE: {{#tag}}
|
||||
fxt.Init__page("Module:A/Test.css", Css_red);
|
||||
fxt.Test__parse
|
||||
( "{{#tag:templatestyles||src='Module:A/Test.css'}}"
|
||||
, Style_red
|
||||
);
|
||||
}
|
||||
@Test public void Error__invalid_title() {
|
||||
fxt.Test__parse
|
||||
( "<templatestyles src='A|b.css'/>"
|
||||
|
Loading…
Reference in New Issue
Block a user