\ProvidesExplPackage{luaxml}{2024-11-14}{v0.2b}{LuaXML package}
% \ProvidesPackage{luaxml}[2024-11-14 LuaXML package]

\RequirePackage{luacode}

% ToDo: add support for use of  transformation rules for other XML syntaxes -- using LaTeX command?


\begin{luacode*}
luaxml_sty = require "luaxml-sty"
\end{luacode*}


\ExplSyntaxOn

% package options
\bool_new:N\l_luaxml_use_defaults
\keys_define:nn {luaxml}{
  default .bool_set:N = \l_luaxml_use_defaults,
  default .initial:n = false
}
\ProcessKeyOptions

% options used in \LXMLRule
\bool_new:N\l_luaxml_verbatim
\tl_new:N \l_luaxml_transformer

\keys_define:nn{luaxmlrule}{
  verbatim .bool_set:N = \l_luaxml_verbatim ,
  verbatim .initial:n = false,
  unknown .code:n = \tl_set_eq:NN\l_luaxml_transformer\l_keys_key_str,
  transformer .tl_set:N = \l_luaxml_transformer,
}


% select current transformer object
\NewDocumentCommand\LXMLUseTransformer{m}{
  \directlua{
luaxml_sty.current.transformation = "#1",
}}

% declare new transformer object
\NewDocumentCommand\LXMLDeclareTransformer{m}{
  \directlua{
    % luaxml_sty.transformations["#1"] = luaxml_sty.packages.transform.new()
    luaxml_sty.declare_transformer("#1")
  }
}

% add transformer rule
% #1 options (verbatim, transformer, unknown key = transformer)
% #2 CSS selector 
% #3 transformer rule
\NewDocumentCommand\LXMLRule{O{} m +v}{
  % handle keyval options
  \group_begin:
  \keys_set:nn {luaxmlrule} { #1 }
  \directlua{luaxml_sty.current.parameters = {}}
  \bool_if:NT \l_luaxml_verbatim {\directlua{luaxml_sty.current.parameters.verbatim = true}}
  \directlua{
    luaxml_sty.add_rule("\l_luaxml_transformer", "#2", "\luaescapestring{#3}")
  }
  \group_end:
}


% Transform code snippet
% \LXMLSnippet* - parse using XML parser
% \LXMLSnippet  - parse using HTML parser
% #2 transformer object name -- empty = default
% #3 XML string
\NewDocumentCommand\LXMLSnippet{s O{} m}{
  \IfBooleanTF{#1}{
    \directlua{luaxml_sty.set_html()}
  }{
    \directlua{luaxml_sty.set_xml()}
  }
  \directlua{
    luaxml_sty.parse_snippet("\luaescapestring{#2}", [[\detokenize{#3}]])
  }
}

% Transform file
% \LXMLInputFile* - parse using XML parser
% \LXMLInputFile  - parse using HTML parser
% #2 transformer object name -- empty = default
% #3 XML string
\NewDocumentCommand\LXMLInputFile{s O{} m}{
  \IfBooleanTF{#1}{
    \directlua{luaxml_sty.set_html()}
  }{
    \directlua{luaxml_sty.set_xml()}
  }
  \directlua{
    luaxml_sty.parse_file("\luaescapestring{#2}", "\luaescapestring{#3}")
  }
}


% Transform XML contained in the environment
% #1 transformer object name -- empty = default
\newenvironment{LXMLCode}[1]{
  \directlua{
    luaxml_sty.set_xml()
    luaxml_sty.register_verbatim("LXMLCode")
  }
  \tl_set:Nn\l_luaxml_transformer{#1}
}{
  \directlua{
    luaxml_sty.print_verbatim("\l_luaxml_transformer")
  }
}

% Transform HTML contained in the environment
% #1 transformer object name -- empty = default
%
% I couldn't process the first line in the environment using the Lua callback with \NewDocumentEnvironment,
% so \newenvironment is used instead.
\newenvironment{LXMLCode*}[1]{
  \directlua{
    luaxml_sty.set_html()
    luaxml_sty.register_verbatim("LXMLCode*")
  }
  \tl_set:Nn\l_luaxml_transformer{#1}
}{
  \directlua{
    luaxml_sty.print_verbatim("\l_luaxml_transformer")
  }
}

% load default transformation rules
\NewDocumentCommand\LXMLLoadDefaults{}{
  \directlua{require "luaxml-htmltemplates"}
}

\AtBeginDocument{
  \bool_if:NT \l_luaxml_use_defaults {\LXMLLoadDefaults}
}


\ExplSyntaxOff
\endinput
