Module: Relaton::Bib::Sanitizer

Defined in:
lib/relaton/bib/sanitizer.rb

Overview

Strips inline markup not in the basicdoc PureTextElement set (plus

, , , , ) from raw marked-up content strings. Disallowed elements are unwrapped: tags removed, inner text kept.

is admitted because basicdoc expresses external hyperlinks as ; without it a from_xml -> to_xml round-trip drops the tag and its target URL, keeping only the link text (see #122, which broke metanorma amend()).

is admitted beyond strict PureTextElement because bibliographic titles in real Metanorma input routinely carry footnotes (e.g. ISO standards titles with a disclaimer footnote), and downstream consumers — notably relaton-render's own inline-tag allow-list — already accept as a legitimate child of . Stripping it here would break the round-trip.</p> <p>OPAQUE elements (currently <stem>) are also allowed, but the sanitiser does not descend into them: their contents are out-of-band inline notation (MathML, AsciiMath, LaTeX) rather than basicdoc markup, and must be preserved verbatim. Without the opaque-skip, the recursive walk would unwrap MathML / AsciiMath elements down to bare text nodes — see #116 for the round-trip-loss symptom.</p> </div> </div> <div class="tags"> </div> <h2> Constant Summary <small><a href="#" class="constants_summary_toggle">collapse</a></small> </h2> <dl class="constants"> <dt id="ALLOWED-constant" class="">ALLOWED = </dt> <dd><pre class="code"><span class='dstring node'>%w[ em strong sub sup tt underline strike smallcap br stem p eref xref fn link ]</span><span class='dot token'>.</span><span class='rubyid_freeze identifier id'>freeze</span> </pre></dd> <dt id="OPAQUE-constant" class="">OPAQUE = <div class="docstring"> <div class="discussion"> <p>Elements whose children are non-basicdoc inline notation (MathML, AsciiMath, LaTeX, …) and must be preserved verbatim rather than sanitised against ALLOWED.</p> </div> </div> <div class="tags"> </div> </dt> <dd><pre class="code"><span class='dstring node'>%w[stem]</span><span class='dot token'>.</span><span class='rubyid_freeze identifier id'>freeze</span> </pre></dd> <dt id="RENAME-constant" class="">RENAME = </dt> <dd><pre class="code"><span class='lbrace token'>{</span> <span class='string val'>"italic"</span> <span class='assign token'>=</span><span class='gt op'>></span> <span class='string val'>"em"</span><span class='comma token'>,</span> <span class='rbrace token'>}</span><span class='dot token'>.</span><span class='rubyid_freeze identifier id'>freeze</span> </pre></dd> <dt id="TAG_RX-constant" class="">TAG_RX = </dt> <dd><pre class="code"><span class='regexp val'>%r{<[a-zA-Z/!?]}</span> </pre></dd> <dt id="NS_PREFIX_RX-constant" class="">NS_PREFIX_RX = <div class="docstring"> <div class="discussion"> <p>Captures a namespace prefix, on a tag or on an attribute: the "jats" of <a href="jats:p">jats:p</a> and </jats:italic>, and the "xlink" of xlink:href.</p> </div> </div> <div class="tags"> </div> </dt> <dd><pre class="code"><span class='regexp val'>%r{(?:</?|\s)([A-Za-z_][\w.-]*):(?=[A-Za-z_])}</span> </pre></dd> <dt id="NS_PLACEHOLDER-constant" class="">NS_PLACEHOLDER = <div class="docstring"> <div class="discussion"> <p>Namespace that declares a prefix which the content leaves undeclared. The sanitiser removes it again before it serialises.</p> </div> </div> <div class="tags"> </div> </dt> <dd><pre class="code"><span class='string val'>"urn:x-relaton-undeclared:%s"</span><span class='dot token'>.</span><span class='rubyid_freeze identifier id'>freeze</span> </pre></dd> <dt id="NS_WRAPPER-constant" class="">NS_WRAPPER = <div class="docstring"> <div class="discussion"> <p>Element that carries the placeholder declarations. Its children are the sanitised content, so the element itself never reaches the output.</p> </div> </div> <div class="tags"> </div> </dt> <dd><pre class="code"><span class='string val'>"relaton-sanitizer-root"</span><span class='dot token'>.</span><span class='rubyid_freeze identifier id'>freeze</span> </pre></dd> <dt id="NS_RESERVED-constant" class="">NS_RESERVED = <div class="docstring"> <div class="discussion"> <p>Reserved prefixes. XML declares both, so the content must not.</p> </div> </div> <div class="tags"> </div> </dt> <dd><pre class="code"><span class='dstring node'>%w[xml xmlns]</span><span class='dot token'>.</span><span class='rubyid_freeze identifier id'>freeze</span> </pre></dd> <dt id="SAVE_OPTS-constant" class="">SAVE_OPTS = <div class="docstring"> <div class="discussion"> <p>Serialise without the FORMAT option, so the sanitiser keeps the shape of element-only content instead of adding newlines and indent.</p> </div> </div> <div class="tags"> </div> </dt> <dd><pre class="code"><span class='rubyid_Nokogiri constant id'>Nokogiri</span><span class='colon2 op'>::</span><span class='rubyid_XML constant id'>XML</span><span class='colon2 op'>::</span><span class='rubyid_Node constant id'>Node</span><span class='colon2 op'>::</span><span class='rubyid_SaveOptions constant id'>SaveOptions</span><span class='colon2 op'>::</span><span class='rubyid_AS_XML constant id'>AS_XML</span> </pre></dd> </dl> <h2> Class Method Summary <small><a href="#" class="summary_toggle">collapse</a></small> </h2> <ul class="summary"> <li class="public "> <span class="summary_signature"> <a href="/gems/relaton-bib/Relaton/Bib/Sanitizer#sanitize-class_method" title="sanitize (class method)">.<strong>sanitize</strong>(content) ⇒ Object </a> </span> <span class="summary_desc"><div class='inline'></div></span> </li> </ul> <div id="class_method_details" class="method_details_list"> <h2>Class Method Details</h2> <div class="method_details first"> <h3 class="signature first" id="sanitize-class_method"> .<strong>sanitize</strong>(content) ⇒ <tt>Object</tt> </h3><script> document.getElementById("sanitize-class_method").insertAdjacentHTML( "afterbegin", '<a class="permalink" href="/gems/relaton-bib/Relaton%2FBib%2FSanitizer%2Esanitize">permalink</a>' ); </script> <table class="source_code"> <tr> <td> <pre class="lines"> 67 68 69 70 71 72 73 74 75 76 77</pre> </td> <td> <pre class="code"><span class="info file"># File 'lib/relaton/bib/sanitizer.rb', line 67</span> <span class='rubyid_def def kw'>def</span> <span class='rubyid_self self kw'>self</span><span class='dot token'>.</span><span class='rubyid_sanitize identifier id'>sanitize</span><span class='lparen token'>(</span><span class='rubyid_content identifier id'>content</span><span class='rparen token'>)</span> <span class='rubyid_return return kw'>return</span> <span class='rubyid_content identifier id'>content</span> <span class='rubyid_unless unless_mod kw'>unless</span> <span class='rubyid_sanitizable? fid id'>sanitizable?</span><span class='lparen token'>(</span><span class='rubyid_content identifier id'>content</span><span class='rparen token'>)</span> <span class='rubyid_node identifier id'>node</span> <span class='assign token'>=</span> <span class='rubyid_parse identifier id'>parse</span><span class='lparen token'>(</span><span class='rubyid_content identifier id'>content</span><span class='rparen token'>)</span> <span class='rubyid_return return kw'>return</span> <span class='rubyid_content identifier id'>content</span> <span class='rubyid_if if_mod kw'>if</span> <span class='rubyid_node identifier id'>node</span><span class='dot token'>.</span><span class='rubyid_nil? fid id'>nil?</span> <span class='rubyid_sanitize_children identifier id'>sanitize_children</span><span class='lparen token'>(</span><span class='rubyid_node identifier id'>node</span><span class='rparen token'>)</span> <span class='rubyid_node identifier id'>node</span><span class='dot token'>.</span><span class='rubyid_children identifier id'>children</span><span class='dot token'>.</span><span class='rubyid_map identifier id'>map</span> <span class='rubyid_do do kw'>do</span> <span class='bitor op'>|</span><span class='rubyid_c identifier id'>c</span><span class='bitor op'>|</span> <span class='rubyid_c identifier id'>c</span><span class='dot token'>.</span><span class='rubyid_to_xml identifier id'>to_xml</span><span class='lparen token'>(</span><span class='label val'>encoding:</span> <span class='string val'>"UTF-8"</span><span class='comma token'>,</span> <span class='label val'>save_with:</span> <span class='rubyid_SAVE_OPTS constant id'>SAVE_OPTS</span><span class='rparen token'>)</span> <span class='rubyid_end end kw'>end</span><span class='dot token'>.</span><span class='rubyid_join identifier id'>join</span> <span class='rubyid_end end kw'>end</span> </pre> </td> </tr> </table> </div> </div> </div> <div id="footer"> Generated on Sun Sep 27 08:44:54 2026 by <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a> 0.9.45 (ruby-4.0.7). </div> </div> </body> </html>