diff --git a/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr.java b/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr.java
new file mode 100644
index 000000000..0e7709660
--- /dev/null
+++ b/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr.java
@@ -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);
+ }
+}
diff --git a/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr_.java b/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr_.java
new file mode 100644
index 000000000..145c6c436
--- /dev/null
+++ b/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_mkr_.java
@@ -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='
'}} 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);
+ }
+}
diff --git a/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_wkr.java b/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_wkr.java
new file mode 100644
index 000000000..03df14683
--- /dev/null
+++ b/400_xowa/src/gplx/xowa/parsers/xndes/Tag_html_wkr.java
@@ -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: "
[ 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: "]"
+ }
+ 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();
+ }
+}
diff --git a/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag.java b/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag.java
index ab8eafa1d..4de1024ec 100644
--- a/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag.java
+++ b/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag.java
@@ -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) {
diff --git a/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_.java b/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_.java
index 047f600f9..0857a27d6 100644
--- a/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_.java
+++ b/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_.java
@@ -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))
;
}
diff --git a/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_regy.java b/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_regy.java
index d29ba563b..f2be5bcc8 100644
--- a/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_regy.java
+++ b/400_xowa/src/gplx/xowa/parsers/xndes/Xop_xnde_tag_regy.java
@@ -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
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 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:
+ 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:
Add_itm(trie, xnde);
}
- if (is_tmpl) { // is_tmpl also has , , ,
+ if (is_tmpl) { // is_tmpl also has , , ,
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: not
&& !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 and ; 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: ; DATE:2014-07-18
diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java
index c8d341484..6fef9eac0 100644
--- a/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java
+++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/Pf_func_.java
@@ -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);
diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag.java
deleted file mode 100644
index 8aca3ed8a..000000000
--- a/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag.java
+++ /dev/null
@@ -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 based on {{#tag}}; EX: {{#tag:ref|a|name=1}} -> [a]
- 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: "[ "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}}" -> "]"
- 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: ""
-
- // 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();}
- }
-}
diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag_kvp_wtr.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag_kvp_wtr.java
deleted file mode 100644
index 78c6fb344..000000000
--- a/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag_kvp_wtr.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag.java
new file mode 100644
index 000000000..c616d8172
--- /dev/null
+++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag.java
@@ -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 based on {{#tag}}; EX: {{#tag:ref|a|name=1}} -> [a]
+ @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();
+ }
+ }
+}
diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag_tst.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag_tst.java
similarity index 75%
rename from 400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag_tst.java
rename to 400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag_tst.java
index a3960d2a4..4ff98dc87 100644
--- a/400_xowa/src/gplx/xowa/xtns/pfuncs/strings/Pfunc_tag_tst.java
+++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/tags/Pfunc_tag_tst.java
@@ -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'}}" , "a
");}
@Test public void Val_quote() {fxt.Test_html_full_str("{{#tag:pre|a|id=\"b\"}}" , "a
");}
@Test public void Val_empty() {fxt.Test_html_full_str("{{#tag:pre|a|id=}}" , "a
");} // 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'}}" , "c
");} // 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\"}}" , "c
");} // 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'}}" , "c
");} // 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}}" , "a
");} // PURPOSE: args must be evaluated
@Test public void Ws_all() {fxt.Test_html_full_str("{{#tag:pre|a| id = b }}" , "a
");}
@Test public void Ws_quoted() {fxt.Test_html_full_str("{{#tag:pre|a| id = ' b ' }}" , "a
");}
@Test public void Err_bad_key() {fxt.Test_html_full_str("{{#tag:pre|a|id=val|b}}" , "a
");} // 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='
'}}" , "a
");} // 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}} -> [a]{{#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.[ {{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}}] 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.[ {{cite news|title = Jaap de Hoop Scheffer | work = Newsmakers | issue = 1 | publisher = Thomson Gale | date = January 1, 2005}}] 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. |group=N|}}"
-// , "{{test}}" , "a
");}
@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}}");
diff --git a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java
index 2669fd9b5..d7cc8f466 100644
--- a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java
+++ b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde.java
@@ -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) {
diff --git a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java
index 6dcfea95c..b0e4b3a48 100644
--- a/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java
+++ b/400_xowa/src/gplx/xowa/xtns/template_styles/Template_styles_nde_tst.java
@@ -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
( ""