From 0b632447a8aecc547ad32b040a07162ba4f4562c Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sun, 23 Feb 2025 03:03:53 +0000 Subject: CTAN sync 202502230303 --- macros/latex/contrib/jsonparse/README.md | 4 +- macros/latex/contrib/jsonparse/jsonparse-doc.pdf | Bin 619738 -> 626933 bytes macros/latex/contrib/jsonparse/jsonparse-doc.tex | 167 +++++++++++++++------ macros/latex/contrib/jsonparse/jsonparse.sty | 177 +++++++++++++---------- 4 files changed, 223 insertions(+), 125 deletions(-) (limited to 'macros/latex/contrib/jsonparse') diff --git a/macros/latex/contrib/jsonparse/README.md b/macros/latex/contrib/jsonparse/README.md index e4e601ebac..83896ac51a 100644 --- a/macros/latex/contrib/jsonparse/README.md +++ b/macros/latex/contrib/jsonparse/README.md @@ -1,4 +1,4 @@ -![Version 1.1.3](https://img.shields.io/badge/version-1.1.3-blue) +![Version 1.2.0](https://img.shields.io/badge/version-1.2.0-blue) ![Jason, the JSON parsing horse](https://github.com/jasperhabicht/jsonparse/assets/6378801/ddfddc70-bf5f-4121-ba45-4b9128875d85) @@ -60,7 +60,7 @@ to plot their values using packages such as PGFPlots. Adding commas between the items of the children array can be done with: ```tex -\JSONParseArrayValues{\myJSONdata}{children}{, } +\JSONParseArrayUse{\myJSONdata}{children}{, } ``` A tabular listing the contact points of above JSON file can be created with: diff --git a/macros/latex/contrib/jsonparse/jsonparse-doc.pdf b/macros/latex/contrib/jsonparse/jsonparse-doc.pdf index 9fe8074b46..da7d5b7461 100644 Binary files a/macros/latex/contrib/jsonparse/jsonparse-doc.pdf and b/macros/latex/contrib/jsonparse/jsonparse-doc.pdf differ diff --git a/macros/latex/contrib/jsonparse/jsonparse-doc.tex b/macros/latex/contrib/jsonparse/jsonparse-doc.tex index 31d847ea00..0382629c63 100644 --- a/macros/latex/contrib/jsonparse/jsonparse-doc.tex +++ b/macros/latex/contrib/jsonparse/jsonparse-doc.tex @@ -11,8 +11,8 @@ % This work has the LPPL maintenance status `maintained'. % \documentclass[a4paper]{article} -\def\jsonparsefileversion{1.1.3} -\def\jsonparsefiledate{13 February 2025} +\def\jsonparsefileversion{1.2.0} +\def\jsonparsefiledate{22 February 2025} \usepackage[T1]{fontenc} \usepackage{Alegreya} @@ -166,6 +166,28 @@ after={\par\smallskip\noindent} } +\NewTCBListing{macrodeprecated}{}{ + listing only, + listing style={jsonparsedocmacro}, + boxrule=0pt, + width={0.5\linewidth-2.5pt}, + box align=top, + after=\hfill, + colframe=black!25!red!10, + colback=black!25!red!10 +} + +\NewTCBListing{macroreplacement}{}{ + listing only, + listing style={jsonparsedocmacro}, + boxrule=0pt, + width={0.5\linewidth-2.5pt}, + box align=top, + before={}, + colframe=black!25!green!10, + colback=black!25!green!10 +} + \NewTotalTCBox{\macro}{ O{} v }{ verbatim, size=tight, @@ -240,6 +262,7 @@ \changes{v1.1.1}{2025/02/03}{Added option to store result of mapped inline function.} \changes{v1.1.2}{2025/02/08}{Added option to store result of array function.} \changes{v1.1.3}{2025/02/13}{Bug fixes.} +\changes{v1.2.0}{2025/02/22}{Unified option to store result.} \begin{document} \vspace*{-1cm} @@ -352,7 +375,7 @@ The first optional argument can be used to pass options to the command that are \end{macrodef} The command \macro{\JSONParseFromFile} is used to parse a JSON file and store the parsed result in a token variable (a property list). It works the same way as \macro{\JSONParse}, but instead of a JSON string, it takes as third argument the path to the JSON file relative to the working directory. -\begin{macrodef} +\begin{macrodef}[macro:parsevalue] |\JSONParseValue|[]{}{} \end{macrodef} The command \macro{\JSONParseValue} is used to select values from the token variable (property list) that has been created using the commands \macro{\JSONParse} or \macro{\JSONParseFromFile}. The second argument takes the token variable that holds the parsed JSON data. The third argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. @@ -367,45 +390,40 @@ When a key is associated with an object or array, the whole object or array is o The command \macro{\JSONParseValue} is not expandable and can therefore not be used as argument of certain other arguments where expansion is needed. In such cases, the expandable command \macro{\JSONParseExpandableValue} should be used. -\begin{macrodef}* -|\JSONParseExpandableValue|{}{} -\end{macrodef} -Whole objects or arrays can be output as JSON string for further use in other macros using the expandable command \macro{\JSONParseExpandableValue}. The value that is returned by this command is typically a string variable where all characters have category code 12 (``other''), except for spaces and (horizontal) tabs that have category code 10 (``space''). This should be kept in mind if string comparisons should be made. A comparison against a token list with the default category codes used by TeX won't work, since letters will have category code 11 (``letter''), but it is possible to use \macro{\detokenize} to set the category codes of the token list in such a way that the comparison works. - -For example, if the JSON string \macro{{ "key" : "value" }} has been parsed into the token variable \macro{\myJSONdata}, the command \macro{\JSONParseExpandableValue{\myJSONdata}{key}} will have the same meaning as \macro{\detokenize{value}} and expand to a token list with all characters having category code 12 (``other''). - \begin{macrodef} -|\JSONParseSetValue|{}{}{} +|store in|={} \end{macrodef} -The command \macro{\JSONParseSetValue} can be used to a select a value from the token variable that stores the parsed JSON data via a key and store this value globally in another token variable. +The command \macro{\JSONParseValue} accepts the key \macro{store in} that can be used to store the return value globally in another token variable. -The first argument denotes the token variable where the value should be stored into. If this token variable has not yet been defined, it will be created by this command. The second argument represents the token variable (property list) that has been created using the commands \macro{\JSONParse} or \macro{\JSONParseFromFile} and that stores the parsed JSON data. The third argument takes the key to select the relevant value. +If the token variable given as option to the \macro{store in} key has not yet been defined, it will be created by this command. The second argument represents the token variable (property list) that has been created using the commands \macro{\JSONParse} or \macro{\JSONParseFromFile} and that stores the parsed JSON data. The third argument takes the key to select the relevant value. The token list returned by this command is a string variable where all characters have category code 12 (``other''), except for spaces and (horizontal) tabs that have category code 10 (``space''). -\begin{macrodef} -|\JSONParseSetRescanValue|{}{}{} -\end{macrodef} -The command \macro{\JSONParseSetRescanValue} works the same way and also takes the same arguments as \macro{\JSONParseSetValue} except that it rescans the return value before storing it globally in the token variable. This means that the value stored in the token list will have the category codes TeX uses per default. Option settings such as the \macro{escape} option are taken into consideration during the rescan process. +The key \macro{store in} can be used together with the key \macro{rescan} to rescans the return value before storing it globally in the token variable. This means that the value stored in the token list will have the category codes TeX uses per default. Option settings such as the \macro{escape} option are taken into consideration during the rescan process. This can, for example, be necessary when numbers stored in the JSON data in scientific format should be formatted using the \macro{siunitx} package. The rescan is needed here, because otherwise the character \macro{e} would have the wrong category code and would hence not be recognised by the formatting parser as exponent marker. Let us assume the key \macro{number} in some JSON source parsed into the token variable \macro{\myJSONnumber} represents the value \macro{-1.1e-1}, then the following could be used to format the output: \JSONParse{\myJSONnumber}{ { "number" : -1.1e-1 } } \begin{codeexamplecolumns} -\JSONParseSetRescanValue{\mynumber} +\JSONParseValue + [rescan, store in=\mynumber] {\myJSONnumber}{number} \num{\mynumber} \end{codeexamplecolumns} -\begin{macrodef} -|\JSONParseKeys|{}{} +\begin{macrodef}* +|\JSONParseExpandableValue|{}{} \end{macrodef} -The command \macro{\JSONParseSetKeys} is used to get all top-level keys of a JSON object as JSON array and return this array as string where all characters (except for spaces and tabs) have category code 12 (``other''). The first argument of the command takes the token variable that holds the parsed JSON data. The second argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. +Whole objects or arrays can be output as JSON string for further use in other macros using the expandable command \macro{\JSONParseExpandableValue}. The value that is returned by this command is typically a string variable where all characters have category code 12 (``other''), except for spaces and (horizontal) tabs that have category code 10 (``space''). This should be kept in mind if string comparisons should be made. A comparison against a token list with the default category codes used by TeX won't work, since letters will have category code 11 (``letter''), but it is possible to use \macro{\detokenize} to set the category codes of the token list in such a way that the comparison works. + +For example, if the JSON string \macro{{ "key" : "value" }} has been parsed into the token variable \macro{\myJSONdata}, the command \macro{\JSONParseExpandableValue{\myJSONdata}{key}} will have the same meaning as \macro{\detokenize{value}} and expand to a token list with all characters having category code 12 (``other''). \begin{macrodef} -|\JSONParseSetKeys|{}{}{} +|\JSONParseKeys|[]{}{} \end{macrodef} -The command \macro{\JSONParseSetKeys} is used to get all top-level keys of a JSON object as JSON array and parse this array into a token variable (a property list). The second argument of the command takes the token variable that holds the parsed JSON data. The third argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. The first argument takes the token variable to hold the JSON array containing the top-level keys of the selected object. The token variable to store the keys as array is created if it does not exist. +The command \macro{\JSONParseKeys} is used to get all top-level keys of a JSON object as JSON array and return this array as string where all characters (except for spaces and tabs) have category code 12 (``other''). The first argument of the command takes the token variable that holds the parsed JSON data. The second argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. + +The command \macro{\JSONParseKeys} accepts as option the key \macro{store in} to get all top-level keys of a JSON object as JSON array and parse this array into a token variable. Note that the return value is stored as property list, not as string. The token variable to store the keys as array is created if it does not exist. \begin{macrodef} |\JSONParseFilter|{}{}{} @@ -422,16 +440,13 @@ The package offers a variety of commands that can be used to process JSON arrays \end{itemize} \begin{macrodef} -|\JSONParseArrayCount|{}{} +|\JSONParseArrayCount|[]{}{} \end{macrodef} The command \macro{\JSONParseArrayCount} takes as first argument a token variable holding a parsed JSON string or JSON file and as second argument a key to select an array in the JSON data. It returns an integer representing the number of items contained in the selected array. -\begin{macrodef} -|\JSONParseSetArrayCount|{}{}{} -\end{macrodef} -The command \macro{\JSONParseSetArrayCount} takes as second argument a token variable holding a parsed JSON string or JSON file and as third argument a key to select an array in the JSON data. It stores the number of items contained in the selected array in the token variable given in the first argument of the command. +The command \macro{\JSONParseArrayCount} accepts the use of the key \macro{store in} to store the number of items contained in the selected array in a token variable. -\begin{macrodef}[macro:arrayuse] +\begin{macrodef} |\JSONParseArrayUse|[]{}{}[]{} \end{macrodef} The command \macro{\JSONParseArrayUse} is used to select all values from an array from a parsed JSON string or JSON file. The second argument takes the token variable that holds the parsed JSON data. The first argument takes the key to select the relevant entry from the parsed JSON data using JavaScript syntax. The third argument is optional and can be used to pass a subkey, i.\,e.\ a key that is used to select a value for every item. The last argument takes a string that is inserted between all values when they are typeset. @@ -458,12 +473,6 @@ When using \macro{\JSONParseArrayUse{\myJSONdata}{array}[key_a]{, }}, `\JSONPars The first optional argument can be used to pass options to the command, such as \macro{escape} or \macro{rescan}, that are then applied locally. -For reasons of backward compatibility , the command \macro{\JSONParseArrayValues} is defined as alias of \macro{\JSONParseArrayUse}. - -\begin{macrodef} -|store in|={} -\end{macrodef} - The command \macro{\JSONParseArrayUse} accepts as option set in the optional argument the key \macro{store in} which takes a token variable into which the result of the command should be stored. Storing the result of the mapped inline function can be helpful if JSON data should be reformatted for use in another function. \begin{codeexamplecolumns} @@ -543,8 +552,6 @@ Typesetting the above example in a tabular way can be achieved as follows: Finally, the first optional argument of the command can be used to pass options to the command, such as \macro{escape} or \macro{rescan}, that are then applied locally. -For reasons of backward compatibility, the command \macro{\JSONParseArrayValuesMap} is defined as alias of \macro{\JSONParseArrayMapFunction}. - \begin{macrodef} |\JSONParseArrayMapInline|[]{}{}{} \end{macrodef} @@ -562,16 +569,18 @@ Using the above example, the mechanism could be implemented as follows: \end{itemize} \end{codeexamplecolumns} -Making use of the commands \macro{\JSONParseSetKeys} and \macro{\JSONParseSetValue}, keys and values can be accessed. Due to the fact that cells create scopes, we need to repeat the part of the code that selects the current key: +Making use of the commands \macro{\JSONParseKeys} and \macro{\JSONParseValue} together with the \macro{store in} option, keys and values can be accessed. Due to the fact that cells create scopes, we need to repeat the part of the code that selects the current key: \begin{codeexamplecolumns} \JSONParseArrayMapInline{\myJSONdata} {array}{ - \JSONParseSetKeys{\mykeys}{\myJSONdata} - {array[#1]} - \JSONParseSetValue{\mykeya} + \JSONParseKeys[store in=\mykeys] + {\myJSONdata}{array[#1]} + \JSONParseValue + [store in=\mykeya, rescan=false] {\mykeys}{[0]} - \JSONParseSetValue{\mykeyb} + \JSONParseValue + [store in=\mykeyb, rescan=false] {\mykeys}{[1]} \emph{\mykeya :} @@ -584,7 +593,7 @@ Making use of the commands \macro{\JSONParseSetKeys} and \macro{\JSONParseSetVal } \end{codeexamplecolumns} -Note that the underscores in the names of the keys can be printed without changing to math mode in the above example because all JSON data is stored as string where all characters (except for spaces and tabs) have category code 12 (``other''). +Note that the underscores in the names of the keys can be printed without changing to math mode in the above example by switching off rescanning via \macro{rescan=false}. This is possible because all JSON data is stored as string where all characters (except for spaces and tabs) have category code 12 (``other''). The command \macro{\JSONParseArrayMapInline} accepts as option set in the optional argument the key \macro{store in} which takes a token variable into which the result of the mapped inline function should be stored. Refer to the relevant explanations to command \macro{\JSONParseArrayUse} \hyperlink{macro:arrayuse}{above} for more information. It is important to note that the inline function needs to be fully expandable. For example, it is not possible to use \macro{\JSONParseValue} in the code of the inline function while \macro{\JSONParseExpandableValue} is allowed. @@ -702,7 +711,7 @@ Some keys that change the typesetting behavior are explained in other parts of t \begin{itemize} \item Information about the keys \macro{escape} and \macro{rescan} can be found above in section \ref{sec:escaping}. -\item Information about the key \macro{store in} can be found above in the description to the commands \macro{\JSONParseArrayUse} and \macro{\JSONParseArrayMapInline} \hyperlink{macro:arrayuse}{above}. +\item Information about the key \macro{store in} can be found above in the description to the command \macro{\JSONParseValue} \hyperlink{macro:parsevalue}{above} as well as the description to the commands \macro{\JSONParseKeys}, \macro{\JSONParseArrayCount}, \macro{\JSONParseArrayUse} and \macro{\JSONParseArrayMapInline} repsectively. \item Information about the keys \macro{code before} and \macro{code after} can be found above in the description to the command \macro{\JSONParseArrayMapFunction} \hyperlink{macro:arraymapfunction}{above}. \end{itemize} @@ -726,6 +735,75 @@ These keys can be used to set the replacement text for the JSON escape sequences These keys can be set using \macro{\JSONParseSet}. They can also be set locally as option to the commands \macro{\JSONParseValue}, \macro{\JSONParseArrayUse} and \macro{\JSONParseArrayMapFunction}. +\section{Deprecated commands} + +The following commands displayed in red boxes on the left have been deprecated and the relevant replacement displayed in green boxes on the right should be used. To simplify the representation of the code and clarify how arguments are supposed to be used, numbers are used to identify the arguments. + +\begin{macrodeprecated} +|\JSONParseSetValue| + {<1>}{<2>}{<3>} +\end{macrodeprecated} +\hfill +\begin{macroreplacement} +|\JSONParseValue|[store in={<1>}, + rescan=false]{<2>}{<3>} +\end{macroreplacement} + +\begin{macrodeprecated} +|\JSONParseSetRescanValue| + {<1>}{<2>}{<3>} +\end{macrodeprecated} +\hfill +\begin{macroreplacement} +|\JSONParseValue|[store in={<1>}, + rescan]{<2>}{<3>} +\end{macroreplacement} + +\begin{macrodeprecated} +|\JSONParseSetKeys| + {<1>}{<2>}{<3>} +\end{macrodeprecated} +\hfill +\begin{macroreplacement} +|\JSONParseKeys| + [store in={<1>}]{<2>}{<3>} +\end{macroreplacement} + +\begin{macrodeprecated} +|\JSONParseSetArrayCount| + {<1>}{<2>}{<3>} +\end{macrodeprecated} +\hfill +\begin{macroreplacement} +|\JSONParseArrayCount| + [store in={<1>}]{<2>}{<3>} +\end{macroreplacement} + +\begin{macrodeprecated} +|\JSONParseArrayValues| + [<1>]{<2>}{<3>}[<4>]{<5>} +\end{macrodeprecated} +\hfill +\begin{macroreplacement} +|\JSONParseArrayUse| + [<1>]{<2>}{<3>}[<4>]{<5>} +\end{macroreplacement} + +\begin{macrodeprecated} +|\JSONParseArrayValuesMap| + [<1>]{<2>}{<3>}[<4>]{<5>} + [<6>][<7>] +\end{macrodeprecated} +\hfill +\begin{macroreplacement} +|\JSONParseArrayMapFunction| + [<1>, code before={<6>}, + code after={<7>}] + {<2>}{<3>}[<4>]{\<5>} +\end{macroreplacement} + +To ensure backward compatibility, the deprecated commands are still supported, but their use is not recommended. + \section{L3 commands} The following commands are provided for defining user functions by package authors. For the conditional functions described above, apart from the variant that provides a true and a false branch, the and variants that only provide an argument for the true or for the false branch respectively are defined as well which is indicated by the letters {\itshape\macro{TF}} printed in italics. @@ -739,6 +817,7 @@ The command \macro{\jsonparse_parse:n} takes as argument a JSON string and popul \begin{macrodef} |\jsonparse_parse_to_prop:Nn| {} +|\jsonparse_parse_to_prop:No| {} |\jsonparse_parse_to_prop:Ne| {} \end{macrodef} The command \macro{\jsonparse_parse_to_prop:Nn} creates the token variable given as the first arguments as property list and, after having called \macro{\jsonparse_parse:n} using the second argument, sets this newly created property list equal to \macro{\g_jsonparse_entries_prop}. If escaping is activated, this command will pre-process the input according to the selected escaping mode before forwarding it to \macro{\jsonparse_parse:n}. See more on escaping above in section \ref{sec:escaping}. diff --git a/macros/latex/contrib/jsonparse/jsonparse.sty b/macros/latex/contrib/jsonparse/jsonparse.sty index 8957ace6eb..e5b59aa45d 100644 --- a/macros/latex/contrib/jsonparse/jsonparse.sty +++ b/macros/latex/contrib/jsonparse/jsonparse.sty @@ -10,7 +10,7 @@ % % This work has the LPPL maintenance status `maintained'. % -\ProvidesExplPackage {jsonparse} {2025-02-13} {1.1.3} +\ProvidesExplPackage {jsonparse} {2025-02-22} {1.2.0} {A handy way to parse, store and access JSON data from files or strings in LaTeX documents} \msg_new:nnn { jsonparse } { old-kernel } { @@ -238,12 +238,15 @@ rescan .bool_set:N = \l__jsonparse_rescan_bool , rescan .default:n = { true } , rescan .initial:n = { true } , - rescan .groups:n = { output } , - code ~ before .tl_set:N = \l__jsonparse_array_map_code_before_tl , - code ~ after .tl_set:N = \l__jsonparse_array_map_code_after_tl + rescan .groups:n = { output } } \keys_define:nn { jsonparse / map } { + code ~ before .tl_set:N = \l__jsonparse_array_map_code_before_tl , + code ~ after .tl_set:N = \l__jsonparse_array_map_code_after_tl , +} + +\keys_define:nn { jsonparse / store ~ in } { store ~ in .tl_set:N = \l__jsonparse_array_map_store_in_tl } @@ -259,17 +262,33 @@ \keys_set_known:nnN { jsonparse / global } {#1} \l__jsonparse_unused_keys_clist \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \keys_set_known:noN { jsonparse / typeset } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist + \keys_set_known:noN { jsonparse / store ~ in } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \keys_set_known:noN { jsonparse / map } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \__jsonparse_warning_unused_keys: } % === -\cs_if_exist:NF \str_casefold:n { - \cs_new_eq:NN \str_casefold:n \str_foldcase:n - \cs_new:Npn \str_foldcase:n { \str_casefold:n } +\bool_new:N \l__jsonparse_compat_bool + +\cs_if_exist:NF \IfExplAtLeastTF { + \cs_new:Npn \IfExplAtLeastTF #1#2#3 { } + \bool_set_true:N \l__jsonparse_compat_bool +} + +\IfExplAtLeastTF { 2024-12-09 } { } { + \bool_set_true:N \l__jsonparse_compat_bool +} + +\bool_if:NT \l__jsonparse_compat_bool { + \cs_if_exist:NF \str_casefold:n { + \cs_new_eq:NN \str_casefold:n \str_foldcase:n + \cs_new:Npn \str_foldcase:n { \str_casefold:n } + } } +% === + \exp_args_generate:n { NeoV } \cs_generate_variant:Nn \file_input:n { e } @@ -313,19 +332,6 @@ % === -\bool_new:N \l__jsonparse_compat_bool - -\cs_if_exist:NF \IfExplAtLeastTF { - \cs_new:Npn \IfExplAtLeastTF #1#2#3 { } - \bool_set_true:N \l__jsonparse_compat_bool -} - -\IfExplAtLeastTF { 2024-12-09 } { } { - \bool_set_true:N \l__jsonparse_compat_bool -} - -% === - \bool_if:NTF \l__jsonparse_compat_bool { \prop_new:N \g_jsonparse_entries_prop \prop_new:N \l__jsonparse_temp_prop @@ -612,7 +618,7 @@ } } } -\cs_generate_variant:Nn \jsonparse_parse_to_prop:Nn { Ne } +\cs_generate_variant:Nn \jsonparse_parse_to_prop:Nn { No , Ne } % === @@ -914,7 +920,7 @@ \prop_set_eq:NN \l__jsonparse_temp_prop #1 \prop_remove:Ne \l__jsonparse_temp_prop { \l__jsonparse_child_sep_str } } { - \prop_map_tokens:Nn #1 { \__jsonparse_filter:nn } + \prop_map_function:NN #1 \__jsonparse_filter:nn } \prop_set_eq:NN #1 \l__jsonparse_temp_prop } @@ -1208,35 +1214,42 @@ \__jsonparse_warning_undefined_prop:N #2 \group_begin: \keys_set_known:nnN { jsonparse / typeset } {#1} \l__jsonparse_unused_keys_clist + \keys_set_known:noN { jsonparse / store ~ in } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \__jsonparse_warning_unused_keys: - \bool_if:NTF \l__jsonparse_rescan_bool { - \jsonparse_rescan:e { \prop_item:Ne #2 {#3} } + \tl_if_empty:NTF \l__jsonparse_array_map_store_in_tl { + \bool_if:NTF \l__jsonparse_rescan_bool { + \jsonparse_rescan:e { \prop_item:Ne #2 {#3} } + } { + \prop_item:Ne #2 {#3} + } } { - \prop_item:Ne #2 {#3} + \exp_last_unbraced:No \tl_if_exist:NF \l__jsonparse_array_map_store_in_tl { + \exp_last_unbraced:No \tl_new:N \l__jsonparse_array_map_store_in_tl + } + \bool_if:NTF \l__jsonparse_rescan_bool { + \exp_last_unbraced:No \jsonparse_gset_rescan:Ne \l__jsonparse_array_map_store_in_tl + { \prop_item:Ne #2 {#3} } + } { + \exp_last_unbraced:No \tl_gset:Ne \l__jsonparse_array_map_store_in_tl + { \prop_item:Ne #2 {#3} } + } } \group_end: } -\NewExpandableDocumentCommand { \JSONParseExpandableValue } { m m } { - \prop_item:Ne #1 {#2} -} - +% backward compatibility \NewDocumentCommand { \JSONParseSetValue } { m m m } { - \__jsonparse_warning_undefined_prop:N #2 - \tl_if_exist:NF #1 { - \tl_new:N #1 - } - \tl_set:Ne #1 { \prop_item:Ne #2 {#3} } + \JSONParseValue [ store ~ in = {#1} , rescan = false ] {#2} {#3} } \NewDocumentCommand { \JSONParseSetRescanValue } { m m m } { - \__jsonparse_warning_undefined_prop:N #2 - \tl_if_exist:NF #1 { - \tl_new:N #1 - } - \jsonparse_gset_rescan:Ne #1 { \prop_item:Ne #2 {#3} } + \JSONParseValue [ store ~ in = {#1} , rescan ] {#2} {#3} } +% === +\NewExpandableDocumentCommand { \JSONParseExpandableValue } { m m } { + \prop_item:Ne #1 {#2} +} \cs_new_protected:Npn \__jsonparse_parse_keys:nn #1#2 { \tl_if_in:nVF {#1} \l__jsonparse_child_sep_str { \bool_if:NTF \l__jsonparse_prop_map_first_bool { @@ -1250,37 +1263,38 @@ \cs_new_protected:Npn \jsonparse_parse_keys:NN #1#2 { \tl_set:Nn \l__jsonparse_keys_array_tl { [ } - \prop_map_tokens:Nn #1 { \__jsonparse_parse_keys:nn } + \prop_map_function:NN #1 \__jsonparse_parse_keys:nn \tl_put_right:Nn \l__jsonparse_keys_array_tl { ] } \tl_set_eq:NN #2 \l__jsonparse_keys_array_tl } -\NewDocumentCommand { \JSONParseKeys } { m m } { - \__jsonparse_warning_undefined_prop:N #1 - \group_begin: - \prop_set_eq:NN \l__jsonparse_temp_copy_prop #1 - \jsonparse_filter:Nn \l__jsonparse_temp_copy_prop {#2} - \bool_set_true:N \l__jsonparse_prop_map_first_bool - \jsonparse_parse_keys:NN \l__jsonparse_temp_prop \l__jsonparse_keys_tl - \tl_use:N \l__jsonparse_keys_tl - \group_end: -} - -\NewDocumentCommand { \JSONParseSetKeys } { m m m } { +\NewDocumentCommand { \JSONParseKeys } { O{} m m } { \__jsonparse_warning_undefined_prop:N #2 - \tl_if_exist:NF #1 { - \tl_new:N #1 - } \group_begin: + \keys_set_known:nnN { jsonparse / store ~ in } {#1} \l__jsonparse_unused_keys_clist + \__jsonparse_warning_unused_keys: \prop_set_eq:NN \l__jsonparse_temp_copy_prop #2 \jsonparse_filter:Nn \l__jsonparse_temp_copy_prop {#3} \bool_set_true:N \l__jsonparse_prop_map_first_bool \jsonparse_parse_keys:NN \l__jsonparse_temp_prop \l__jsonparse_keys_tl - \exp_args:NNNV + \tl_if_empty:NTF \l__jsonparse_array_map_store_in_tl { + \tl_use:N \l__jsonparse_keys_tl + } { + \exp_last_unbraced:No \tl_if_exist:NF \l__jsonparse_array_map_store_in_tl { + \exp_last_unbraced:No \tl_new:N \l__jsonparse_array_map_store_in_tl + } + \exp_last_unbraced:No \jsonparse_parse_to_prop:No \l__jsonparse_array_map_store_in_tl + { \l__jsonparse_keys_tl } + } \group_end: - \jsonparse_parse_to_prop:Nn #1 \l__jsonparse_keys_tl } +% backward compatibility +\NewDocumentCommand { \JSONParseSetKeys } { m m m } { + \JSONParseKeys [ store ~ in = {#1} ] {#2} {#3} +} +% === + \cs_new:Npn \__jsonparse_get_array_index:w [ #1 ] #2 \q_stop { #1 } @@ -1303,34 +1317,36 @@ \cs_new_protected:Npn \jsonparse_array_count:NN #1#2 { \int_zero:N \l__jsonparse_array_count_aux_int \seq_clear:N \l__jsonparse_array_count_last_seq - \prop_map_tokens:Nn #1 { \__jsonparse_array_count:nn } + \prop_map_function:NN #1 \__jsonparse_array_count:nn \int_set_eq:NN #2 \l__jsonparse_array_count_aux_int } -\NewDocumentCommand { \JSONParseArrayCount } { m m } { - \__jsonparse_warning_undefined_prop:N #1 - \group_begin: - \prop_set_eq:NN \l__jsonparse_temp_copy_prop #1 - \jsonparse_filter:Nn \l__jsonparse_temp_copy_prop {#2} - \jsonparse_array_count:NN \l__jsonparse_temp_copy_prop \l__jsonparse_array_count_int - \int_use:N \l__jsonparse_array_count_int - \group_end: -} - -\NewDocumentCommand { \JSONParseSetArrayCount } { m m m } { +\NewDocumentCommand { \JSONParseArrayCount } { O{} m m } { \__jsonparse_warning_undefined_prop:N #2 - \tl_if_exist:NF #1 { - \tl_new:N #1 - } \group_begin: + \keys_set_known:nnN { jsonparse / store ~ in } {#1} \l__jsonparse_unused_keys_clist + \__jsonparse_warning_unused_keys: \prop_set_eq:NN \l__jsonparse_temp_copy_prop #2 \jsonparse_filter:Nn \l__jsonparse_temp_copy_prop {#3} \jsonparse_array_count:NN \l__jsonparse_temp_copy_prop \l__jsonparse_array_count_int - \exp_args:NNNV + \tl_if_empty:NTF \l__jsonparse_array_map_store_in_tl { + \int_use:N \l__jsonparse_array_count_int + } { + \exp_last_unbraced:No \tl_if_exist:NF \l__jsonparse_array_map_store_in_tl { + \exp_last_unbraced:No \tl_new:N \l__jsonparse_array_map_store_in_tl + } + \exp_last_unbraced:No \tl_gset:NV \l__jsonparse_array_map_store_in_tl + \l__jsonparse_array_count_int + } \group_end: - \tl_set:Nn #1 \l__jsonparse_array_count_int } +% backward compatibility +\NewDocumentCommand { \JSONParseSetArrayCount } { m m m } { + \JSONParseArrayCount [ store ~ in = {#1} ] {#2} {#3} +} +% === + \cs_new_protected:Npn \__jsonparse_array_use:n #1 { \bool_if:NTF \l__jsonparse_prop_map_first_bool { \bool_set_false:N \l__jsonparse_prop_map_first_bool @@ -1389,6 +1405,7 @@ \__jsonparse_warning_undefined_prop:N #2 \group_begin: \keys_set_known:nnN { jsonparse / typeset } {#1} \l__jsonparse_unused_keys_clist + \keys_set_known:noN { jsonparse / store ~ in } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \keys_set_known:noN { jsonparse / map } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \__jsonparse_warning_unused_keys: \prop_set_eq:NN \l__jsonparse_temp_copy_prop #2 @@ -1487,8 +1504,8 @@ } } { \int_zero:N \l__jsonparse_array_keys_index_int - \clist_map_tokens:Nn \l__jsonparse_array_map_keys_clist - { \__jsonparse_array_map_function_keys:n } + \clist_map_function:NN \l__jsonparse_array_map_keys_clist + \__jsonparse_array_map_function_keys:n \tl_gset_eq:NN \JSONParseArrayKey \JSONParseArrayKeyI \tl_gset_eq:NN \JSONParseArrayValue \JSONParseArrayValueI } @@ -1516,6 +1533,7 @@ } \group_begin: \keys_set_known:nnN { jsonparse / typeset } {#1} \l__jsonparse_unused_keys_clist + \keys_set_known:noN { jsonparse / map } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \__jsonparse_warning_unused_keys: \prop_set_eq:NN \l__jsonparse_temp_copy_prop #2 \jsonparse_filter:Nn \l__jsonparse_temp_copy_prop {#3} @@ -1524,8 +1542,8 @@ \cs_set_eq:NN \__jsonparse_array_map_function_cs: #5 \clist_if_empty:NF \l__jsonparse_array_map_keys_clist { \int_zero:N \l__jsonparse_array_keys_index_int - \clist_map_tokens:Nn \l__jsonparse_array_map_keys_clist - { \__jsonparse_array_map_function_generate_cs:n } + \clist_map_function:NN \l__jsonparse_array_map_keys_clist + \__jsonparse_array_map_function_generate_cs:n } \l__jsonparse_array_map_code_before_tl \int_step_function:nN { \l__jsonparse_array_count_int } @@ -1569,7 +1587,8 @@ \__jsonparse_warning_undefined_prop:N #2 \cs_gset:Npn \__jsonparse_array_map_inline_code:n ##1 {#4} \group_begin: - \keys_set_known:nnN { jsonparse / map } {#1} \l__jsonparse_unused_keys_clist + \keys_set_known:nnN { jsonparse / store ~ in } {#1} \l__jsonparse_unused_keys_clist + \keys_set_known:noN { jsonparse / map } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist \__jsonparse_warning_unused_keys: \prop_set_eq:NN \l__jsonparse_temp_copy_prop #2 \jsonparse_filter:Nn \l__jsonparse_temp_copy_prop {#3} -- cgit v1.2.3