selma 0.0.2-x86_64-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +173 -0
 - data/ext/selma/Cargo.toml +14 -0
 - data/ext/selma/_util.rb +102 -0
 - data/ext/selma/extconf.rb +6 -0
 - data/ext/selma/src/html/element.rs +195 -0
 - data/ext/selma/src/html/end_tag.rs +35 -0
 - data/ext/selma/src/html.rs +17 -0
 - data/ext/selma/src/lib.rs +23 -0
 - data/ext/selma/src/native_ref_wrap.rs +79 -0
 - data/ext/selma/src/rewriter.rs +441 -0
 - data/ext/selma/src/sanitizer.rs +578 -0
 - data/ext/selma/src/selector.rs +115 -0
 - data/ext/selma/src/tags.rs +1133 -0
 - data/ext/selma/src/wrapped_struct.rs +92 -0
 - data/lib/selma/3.1/selma.bundle +0 -0
 - data/lib/selma/extension.rb +14 -0
 - data/lib/selma/html.rb +6 -0
 - data/lib/selma/rewriter.rb +6 -0
 - data/lib/selma/sanitizer/config/basic.rb +27 -0
 - data/lib/selma/sanitizer/config/default.rb +42 -0
 - data/lib/selma/sanitizer/config/relaxed.rb +37 -0
 - data/lib/selma/sanitizer/config/restricted.rb +13 -0
 - data/lib/selma/sanitizer/config.rb +67 -0
 - data/lib/selma/sanitizer.rb +85 -0
 - data/lib/selma/selector.rb +6 -0
 - data/lib/selma/version.rb +5 -0
 - data/lib/selma.rb +13 -0
 - data/selma.gemspec +41 -0
 - metadata +136 -0
 
| 
         @@ -0,0 +1,92 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            use magnus::{error::Error, exception, gc, value::Value, RTypedData, TryConvert, TypedData};
         
     | 
| 
      
 2 
     | 
    
         
            +
            use std::{marker::PhantomData, ops::Deref};
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            // NOTE: My Rust isn't good enough to know what any of this does,
         
     | 
| 
      
 5 
     | 
    
         
            +
            // but it was taken from https://cs.github.com/bytecodealliance/wasmtime-rb/blob/a843e4b4582a945f2c881b8bd3e2b87688ab5509/ext/src/helpers/wrapped_struct.rs#L4
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            /// A small wrapper for `RTypedData` that keeps track of the concrete struct
         
     | 
| 
      
 8 
     | 
    
         
            +
            /// type, and the underlying [`Value`] for GC purposes.
         
     | 
| 
      
 9 
     | 
    
         
            +
            #[derive(Debug)]
         
     | 
| 
      
 10 
     | 
    
         
            +
            #[repr(transparent)]
         
     | 
| 
      
 11 
     | 
    
         
            +
            pub struct WrappedStruct<T: TypedData> {
         
     | 
| 
      
 12 
     | 
    
         
            +
                inner: RTypedData,
         
     | 
| 
      
 13 
     | 
    
         
            +
                phantom: PhantomData<T>,
         
     | 
| 
      
 14 
     | 
    
         
            +
            }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            impl<T: TypedData> Clone for WrappedStruct<T> {
         
     | 
| 
      
 17 
     | 
    
         
            +
                fn clone(&self) -> Self {
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Self {
         
     | 
| 
      
 19 
     | 
    
         
            +
                        inner: self.inner,
         
     | 
| 
      
 20 
     | 
    
         
            +
                        phantom: PhantomData,
         
     | 
| 
      
 21 
     | 
    
         
            +
                    }
         
     | 
| 
      
 22 
     | 
    
         
            +
                }
         
     | 
| 
      
 23 
     | 
    
         
            +
            }
         
     | 
| 
      
 24 
     | 
    
         
            +
            impl<T: TypedData> Copy for WrappedStruct<T> {}
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            impl<T: TypedData> WrappedStruct<T> {
         
     | 
| 
      
 27 
     | 
    
         
            +
                /// Gets the underlying struct.
         
     | 
| 
      
 28 
     | 
    
         
            +
                pub fn get(&self) -> Result<&T, Error> {
         
     | 
| 
      
 29 
     | 
    
         
            +
                    self.inner.try_convert()
         
     | 
| 
      
 30 
     | 
    
         
            +
                }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                /// Gets the underlying struct with a `'static` lifetime.
         
     | 
| 
      
 33 
     | 
    
         
            +
                pub fn get_static(&self) -> Result<&'static T, Error> {
         
     | 
| 
      
 34 
     | 
    
         
            +
                    self.inner.try_convert()
         
     | 
| 
      
 35 
     | 
    
         
            +
                }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                /// Get the Ruby [`Value`] for this struct.
         
     | 
| 
      
 38 
     | 
    
         
            +
                pub fn to_value(self) -> Value {
         
     | 
| 
      
 39 
     | 
    
         
            +
                    self.inner.into()
         
     | 
| 
      
 40 
     | 
    
         
            +
                }
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                /// Marks the Ruby [`Value`] for GC.
         
     | 
| 
      
 43 
     | 
    
         
            +
                pub fn mark(&self) {
         
     | 
| 
      
 44 
     | 
    
         
            +
                    gc::mark(&self.inner.into());
         
     | 
| 
      
 45 
     | 
    
         
            +
                }
         
     | 
| 
      
 46 
     | 
    
         
            +
            }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            impl<T: TypedData> From<WrappedStruct<T>> for Value {
         
     | 
| 
      
 49 
     | 
    
         
            +
                fn from(wrapped_struct: WrappedStruct<T>) -> Self {
         
     | 
| 
      
 50 
     | 
    
         
            +
                    wrapped_struct.to_value()
         
     | 
| 
      
 51 
     | 
    
         
            +
                }
         
     | 
| 
      
 52 
     | 
    
         
            +
            }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            impl<T: TypedData> Deref for WrappedStruct<T> {
         
     | 
| 
      
 55 
     | 
    
         
            +
                type Target = RTypedData;
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                fn deref(&self) -> &Self::Target {
         
     | 
| 
      
 58 
     | 
    
         
            +
                    &self.inner
         
     | 
| 
      
 59 
     | 
    
         
            +
                }
         
     | 
| 
      
 60 
     | 
    
         
            +
            }
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            impl<T: TypedData> From<T> for WrappedStruct<T> {
         
     | 
| 
      
 63 
     | 
    
         
            +
                fn from(t: T) -> Self {
         
     | 
| 
      
 64 
     | 
    
         
            +
                    Self {
         
     | 
| 
      
 65 
     | 
    
         
            +
                        inner: RTypedData::wrap(t),
         
     | 
| 
      
 66 
     | 
    
         
            +
                        phantom: PhantomData,
         
     | 
| 
      
 67 
     | 
    
         
            +
                    }
         
     | 
| 
      
 68 
     | 
    
         
            +
                }
         
     | 
| 
      
 69 
     | 
    
         
            +
            }
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            impl<T> TryConvert for WrappedStruct<T>
         
     | 
| 
      
 72 
     | 
    
         
            +
            where
         
     | 
| 
      
 73 
     | 
    
         
            +
                T: TypedData,
         
     | 
| 
      
 74 
     | 
    
         
            +
            {
         
     | 
| 
      
 75 
     | 
    
         
            +
                fn try_convert(val: Value) -> Result<Self, Error> {
         
     | 
| 
      
 76 
     | 
    
         
            +
                    let inner = RTypedData::from_value(val).ok_or_else(|| {
         
     | 
| 
      
 77 
     | 
    
         
            +
                        Error::new(
         
     | 
| 
      
 78 
     | 
    
         
            +
                            exception::type_error(),
         
     | 
| 
      
 79 
     | 
    
         
            +
                            format!(
         
     | 
| 
      
 80 
     | 
    
         
            +
                                "no implicit conversion of {} into {}",
         
     | 
| 
      
 81 
     | 
    
         
            +
                                unsafe { val.classname() },
         
     | 
| 
      
 82 
     | 
    
         
            +
                                T::class()
         
     | 
| 
      
 83 
     | 
    
         
            +
                            ),
         
     | 
| 
      
 84 
     | 
    
         
            +
                        )
         
     | 
| 
      
 85 
     | 
    
         
            +
                    })?;
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    Ok(Self {
         
     | 
| 
      
 88 
     | 
    
         
            +
                        inner,
         
     | 
| 
      
 89 
     | 
    
         
            +
                        phantom: PhantomData,
         
     | 
| 
      
 90 
     | 
    
         
            +
                    })
         
     | 
| 
      
 91 
     | 
    
         
            +
                }
         
     | 
| 
      
 92 
     | 
    
         
            +
            }
         
     | 
| 
         Binary file 
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            begin
         
     | 
| 
      
 4 
     | 
    
         
            +
              # native precompiled gems package shared libraries in <gem_dir>/lib/selma/<ruby_version>
         
     | 
| 
      
 5 
     | 
    
         
            +
              # load the precompiled extension file
         
     | 
| 
      
 6 
     | 
    
         
            +
              ruby_version = /\d+\.\d+/.match(RUBY_VERSION)
         
     | 
| 
      
 7 
     | 
    
         
            +
              require_relative "#{ruby_version}/selma"
         
     | 
| 
      
 8 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 9 
     | 
    
         
            +
              # fall back to the extension compiled upon installation.
         
     | 
| 
      
 10 
     | 
    
         
            +
              # use "require" instead of "require_relative" because non-native gems will place C extension files
         
     | 
| 
      
 11 
     | 
    
         
            +
              # in Gem::BasicSpecification#extension_dir after compilation (during normal installation), which
         
     | 
| 
      
 12 
     | 
    
         
            +
              # is in $LOAD_PATH but not necessarily relative to this file (see nokogiri#2300)
         
     | 
| 
      
 13 
     | 
    
         
            +
              require "selma/selma"
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/selma/html.rb
    ADDED
    
    
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Selma
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Sanitizer
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 6 
     | 
    
         
            +
                  BASIC = freeze_config(
         
     | 
| 
      
 7 
     | 
    
         
            +
                    elements: ["a", "abbr", "blockquote", "b", "br", "cite", "code", "dd", "dfn", "dl", "dt", "em", "i", "kbd",
         
     | 
| 
      
 8 
     | 
    
         
            +
                               "li", "mark", "ol", "p", "pre", "q", "s", "samp", "small", "strike", "strong", "sub", "sup", "time", "u", "ul", "var",],
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    attributes: {
         
     | 
| 
      
 11 
     | 
    
         
            +
                      "a" => ["href"],
         
     | 
| 
      
 12 
     | 
    
         
            +
                      "abbr" => ["title"],
         
     | 
| 
      
 13 
     | 
    
         
            +
                      "blockquote" => ["cite"],
         
     | 
| 
      
 14 
     | 
    
         
            +
                      "dfn" => ["title"],
         
     | 
| 
      
 15 
     | 
    
         
            +
                      "q" => ["cite"],
         
     | 
| 
      
 16 
     | 
    
         
            +
                      "time" => ["datetime", "pubdate"],
         
     | 
| 
      
 17 
     | 
    
         
            +
                    },
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    protocols: {
         
     | 
| 
      
 20 
     | 
    
         
            +
                      "a" => { "href" => ["ftp", "http", "https", "mailto", :relative] },
         
     | 
| 
      
 21 
     | 
    
         
            +
                      "blockquote" => { "cite" => ["http", "https", :relative] },
         
     | 
| 
      
 22 
     | 
    
         
            +
                      "q" => { "cite" => ["http", "https", :relative] },
         
     | 
| 
      
 23 
     | 
    
         
            +
                    },
         
     | 
| 
      
 24 
     | 
    
         
            +
                  )
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Selma
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Sanitizer
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 6 
     | 
    
         
            +
                  DEFAULT = freeze_config(
         
     | 
| 
      
 7 
     | 
    
         
            +
                    # Whether or not to allow HTML comments. Allowing comments is strongly
         
     | 
| 
      
 8 
     | 
    
         
            +
                    # discouraged, since IE allows script execution within conditional
         
     | 
| 
      
 9 
     | 
    
         
            +
                    # comments.
         
     | 
| 
      
 10 
     | 
    
         
            +
                    allow_comments: false,
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    # Whether or not to allow well-formed HTML doctype declarations such as
         
     | 
| 
      
 13 
     | 
    
         
            +
                    # "<!DOCTYPE html>" when sanitizing a document.
         
     | 
| 
      
 14 
     | 
    
         
            +
                    allow_doctype: false,
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    # HTML attributes to allow in specific elements. By default, no attributes
         
     | 
| 
      
 17 
     | 
    
         
            +
                    # are allowed. Use the symbol :data to indicate that arbitrary HTML5
         
     | 
| 
      
 18 
     | 
    
         
            +
                    # data-* attributes should be allowed.
         
     | 
| 
      
 19 
     | 
    
         
            +
                    attributes: {},
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    # HTML elements to allow. By default, no elements are allowed (which means
         
     | 
| 
      
 22 
     | 
    
         
            +
                    # that all HTML will be stripped).
         
     | 
| 
      
 23 
     | 
    
         
            +
                    elements: [],
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    # URL handling protocols to allow in specific attributes. By default, no
         
     | 
| 
      
 26 
     | 
    
         
            +
                    # protocols are allowed. Use :relative in place of a protocol if you want
         
     | 
| 
      
 27 
     | 
    
         
            +
                    # to allow relative URLs sans protocol.
         
     | 
| 
      
 28 
     | 
    
         
            +
                    protocols: {},
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    # An Array of element names whose contents will be removed. The contents
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # of all other filtered elements will be left behind.
         
     | 
| 
      
 32 
     | 
    
         
            +
                    remove_contents: ["iframe", "math", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg",
         
     | 
| 
      
 33 
     | 
    
         
            +
                                      "xmp",],
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    # Elements which, when removed, should have their contents surrounded by
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # whitespace.
         
     | 
| 
      
 37 
     | 
    
         
            +
                    whitespace_elements: ["address", "article", "aside", "blockquote", "br", "dd", "div", "dl", "dt", "footer",
         
     | 
| 
      
 38 
     | 
    
         
            +
                                          "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "nav", "ol", "p", "pre", "section", "ul",],
         
     | 
| 
      
 39 
     | 
    
         
            +
                  )
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Selma
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Sanitizer
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 6 
     | 
    
         
            +
                  RELAXED = freeze_config(
         
     | 
| 
      
 7 
     | 
    
         
            +
                    elements: BASIC[:elements] + ["address", "article", "aside", "bdi", "bdo", "body", "caption", "col",
         
     | 
| 
      
 8 
     | 
    
         
            +
                                                  "colgroup", "data", "del", "div", "figcaption", "figure", "footer", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "img", "ins", "main", "nav", "rp", "rt", "ruby", "section", "span", "style", "summary", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "title", "tr", "wbr",],
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    allow_doctype: true,
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    attributes: merge(BASIC[:attributes],
         
     | 
| 
      
 13 
     | 
    
         
            +
                      :all => ["class", "dir", "hidden", "id", "lang", "style", "tabindex", "title", "translate"],
         
     | 
| 
      
 14 
     | 
    
         
            +
                      "a" => ["href", "hreflang", "name", "rel"],
         
     | 
| 
      
 15 
     | 
    
         
            +
                      "col" => ["span", "width"],
         
     | 
| 
      
 16 
     | 
    
         
            +
                      "colgroup" => ["span", "width"],
         
     | 
| 
      
 17 
     | 
    
         
            +
                      "data" => ["value"],
         
     | 
| 
      
 18 
     | 
    
         
            +
                      "del" => ["cite", "datetime"],
         
     | 
| 
      
 19 
     | 
    
         
            +
                      "img" => ["align", "alt", "border", "height", "src", "srcset", "width"],
         
     | 
| 
      
 20 
     | 
    
         
            +
                      "ins" => ["cite", "datetime"],
         
     | 
| 
      
 21 
     | 
    
         
            +
                      "li" => ["value"],
         
     | 
| 
      
 22 
     | 
    
         
            +
                      "ol" => ["reversed", "start", "type"],
         
     | 
| 
      
 23 
     | 
    
         
            +
                      "style" => ["media", "scoped", "type"],
         
     | 
| 
      
 24 
     | 
    
         
            +
                      "table" => ["align", "bgcolor", "border", "cellpadding", "cellspacing", "frame", "rules", "sortable",
         
     | 
| 
      
 25 
     | 
    
         
            +
                                  "summary", "width",],
         
     | 
| 
      
 26 
     | 
    
         
            +
                      "td" => ["abbr", "align", "axis", "colspan", "headers", "rowspan", "valign", "width"],
         
     | 
| 
      
 27 
     | 
    
         
            +
                      "th" => ["abbr", "align", "axis", "colspan", "headers", "rowspan", "scope", "sorted", "valign", "width"],
         
     | 
| 
      
 28 
     | 
    
         
            +
                      "ul" => ["type"]),
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    protocols: merge(BASIC[:protocols],
         
     | 
| 
      
 31 
     | 
    
         
            +
                      "del" => { "cite" => ["http", "https", :relative] },
         
     | 
| 
      
 32 
     | 
    
         
            +
                      "img" => { "src"  => ["http", "https", :relative] },
         
     | 
| 
      
 33 
     | 
    
         
            +
                      "ins" => { "cite" => ["http", "https", :relative] }),
         
     | 
| 
      
 34 
     | 
    
         
            +
                  )
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "set"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Selma
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Sanitizer
         
     | 
| 
      
 7 
     | 
    
         
            +
                module Config
         
     | 
| 
      
 8 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 9 
     | 
    
         
            +
                    # Deeply freezes and returns the given configuration Hash.
         
     | 
| 
      
 10 
     | 
    
         
            +
                    def freeze_config(config)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      case config
         
     | 
| 
      
 12 
     | 
    
         
            +
                      when Hash
         
     | 
| 
      
 13 
     | 
    
         
            +
                        config.each_value { |c| freeze_config(c) }
         
     | 
| 
      
 14 
     | 
    
         
            +
                      when Array, Set
         
     | 
| 
      
 15 
     | 
    
         
            +
                        config.each { |c| freeze_config(c) }
         
     | 
| 
      
 16 
     | 
    
         
            +
                      end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                      config.freeze
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    # Returns a new Hash containing the result of deeply merging *other_config*
         
     | 
| 
      
 22 
     | 
    
         
            +
                    # into *config*. Does not modify *config* or *other_config*.
         
     | 
| 
      
 23 
     | 
    
         
            +
                    #
         
     | 
| 
      
 24 
     | 
    
         
            +
                    # This is the safest way to use a built-in config as the basis for
         
     | 
| 
      
 25 
     | 
    
         
            +
                    # your own custom config.
         
     | 
| 
      
 26 
     | 
    
         
            +
                    def merge(config, other_config = {})
         
     | 
| 
      
 27 
     | 
    
         
            +
                      raise ArgumentError, "config must be a Hash" unless config.is_a?(Hash)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      raise ArgumentError, "other_config must be a Hash" unless other_config.is_a?(Hash)
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                      merged = {}
         
     | 
| 
      
 31 
     | 
    
         
            +
                      keys   = Set.new(config.keys + other_config.keys)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                      keys.each do |key|
         
     | 
| 
      
 34 
     | 
    
         
            +
                        oldval = config[key]
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                        if other_config.key?(key)
         
     | 
| 
      
 37 
     | 
    
         
            +
                          newval = other_config[key]
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                          merged[key] = if oldval.is_a?(Hash) && newval.is_a?(Hash)
         
     | 
| 
      
 40 
     | 
    
         
            +
                            oldval.empty? ? newval.dup : merge(oldval, newval)
         
     | 
| 
      
 41 
     | 
    
         
            +
                          elsif newval.is_a?(Array) && key != :transformers
         
     | 
| 
      
 42 
     | 
    
         
            +
                            Set.new(newval)
         
     | 
| 
      
 43 
     | 
    
         
            +
                          else
         
     | 
| 
      
 44 
     | 
    
         
            +
                            can_dupe?(newval) ? newval.dup : newval
         
     | 
| 
      
 45 
     | 
    
         
            +
                          end
         
     | 
| 
      
 46 
     | 
    
         
            +
                        else
         
     | 
| 
      
 47 
     | 
    
         
            +
                          merged[key] = can_dupe?(oldval) ? oldval.dup : oldval
         
     | 
| 
      
 48 
     | 
    
         
            +
                        end
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                      merged
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # Returns `true` if `dup` may be safely called on _value_, `false`
         
     | 
| 
      
 55 
     | 
    
         
            +
                    # otherwise.
         
     | 
| 
      
 56 
     | 
    
         
            +
                    def can_dupe?(value)
         
     | 
| 
      
 57 
     | 
    
         
            +
                      !(value == true || value == false || value.nil? || value.is_a?(Method) || value.is_a?(Numeric) || value.is_a?(Symbol))
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            require "selma/sanitizer/config/basic"
         
     | 
| 
      
 65 
     | 
    
         
            +
            require "selma/sanitizer/config/default"
         
     | 
| 
      
 66 
     | 
    
         
            +
            require "selma/sanitizer/config/relaxed"
         
     | 
| 
      
 67 
     | 
    
         
            +
            require "selma/sanitizer/config/restricted"
         
     | 
| 
         @@ -0,0 +1,85 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "selma/sanitizer/config"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Selma
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Sanitizer
         
     | 
| 
      
 7 
     | 
    
         
            +
                ALLOW = 1 << 0
         
     | 
| 
      
 8 
     | 
    
         
            +
                ESCAPE_TAGFILTER = (1 << 1)
         
     | 
| 
      
 9 
     | 
    
         
            +
                REMOVE_CONTENTS = (1 << 2)
         
     | 
| 
      
 10 
     | 
    
         
            +
                WRAP_WHITESPACE = (1 << 3)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # initialize is in Rust, this just helps manage config setup in Ruby
         
     | 
| 
      
 13 
     | 
    
         
            +
                # TODO: could this just become initialize?
         
     | 
| 
      
 14 
     | 
    
         
            +
                def setup
         
     | 
| 
      
 15 
     | 
    
         
            +
                  allow_element(config[:elements] || [])
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  (config[:attributes] || {}).each do |element, attrs|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    allow_attribute(element, attrs)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  (config[:protocols] || {}).each do |element, protocols|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    protocols.each do |attribute, pr|
         
     | 
| 
      
 23 
     | 
    
         
            +
                      allow_protocol(element, attribute, pr)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  remove_contents(config[:remove_contents]) if config.include?(:remove_contents)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  wrap_with_whitespace(config[:whitespace_elements]) if config.include?(:whitespace_elements)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  set_escape_tagfilter(config.fetch(:escape_tagfilter, true))
         
     | 
| 
      
 32 
     | 
    
         
            +
                  set_allow_comments(config.fetch(:allow_comments, false))
         
     | 
| 
      
 33 
     | 
    
         
            +
                  set_allow_doctype(config.fetch(:allow_doctype, true))
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def elements
         
     | 
| 
      
 37 
     | 
    
         
            +
                  config[:elements]
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def allow_element(elements)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  elements.flatten.each { |e| set_flag(e, ALLOW, true) }
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def disallow_element(elements)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  elements.flatten.each { |e| set_flag(e, ALLOW, false) }
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def allow_attribute(element, attrs)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  attrs.flatten.each { |attr| set_allowed_attribute(element, attr, true) }
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def require_any_attributes(element, attrs)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  if attr.empty?
         
     | 
| 
      
 54 
     | 
    
         
            +
                    set_required_attribute(element, "*", true)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  else
         
     | 
| 
      
 56 
     | 
    
         
            +
                    attrs.flatten.each { |attr| set_required_attribute(element, attr, true) }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def disallow_attribute(element, attrs)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  attrs.flatten.each { |attr| set_allowed_attribute(element, attr, false) }
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def allow_class(element, *klass)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  klass.flatten.each { |k| set_allowed_class(element, k, true) }
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def allow_protocol(element, attr, protos)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  protos = [protos] unless protos.is_a?(Array)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  set_allowed_protocols(element, attr, protos)
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def remove_contents(elements)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  if elements.is_a?(TrueClass) || elements.is_a?(FalseClass)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    set_all_flags(REMOVE_CONTENTS, elements)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  else
         
     | 
| 
      
 77 
     | 
    
         
            +
                    elements.flatten.each { |e| set_flag(e, REMOVE_CONTENTS, true) }
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def wrap_with_whitespace(elements)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  elements.flatten.each { |e| set_flag(e, WRAP_WHITESPACE, true) }
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/selma.rb
    ADDED
    
    | 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            if ENV.fetch("DEBUG", false)
         
     | 
| 
      
 4 
     | 
    
         
            +
              require "amazing_print"
         
     | 
| 
      
 5 
     | 
    
         
            +
              require "debug"
         
     | 
| 
      
 6 
     | 
    
         
            +
            end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require_relative "selma/extension"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require_relative "selma/sanitizer"
         
     | 
| 
      
 11 
     | 
    
         
            +
            require_relative "selma/html"
         
     | 
| 
      
 12 
     | 
    
         
            +
            require_relative "selma/rewriter"
         
     | 
| 
      
 13 
     | 
    
         
            +
            require_relative "selma/selector"
         
     | 
    
        data/selma.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            lib = File.expand_path("lib", __dir__)
         
     | 
| 
      
 4 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "selma/version"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.name          = "selma"
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.version       = Selma::VERSION
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.authors       = ["Garen J. Torikian"]
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.email         = ["gjtorikian@gmail.com"]
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              spec.summary       = "Selma selects and matches HTML nodes using CSS rules. Backed by Rust's lol_html parser."
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.license       = "MIT"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.required_ruby_version = "~> 3.1"
         
     | 
| 
      
 17 
     | 
    
         
            +
              # https://github.com/rubygems/rubygems/pull/5852#issuecomment-1231118509
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.required_rubygems_version = ">= 3.3.22"
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              spec.files = ["LICENSE.txt", "README.md", "selma.gemspec"]
         
     | 
| 
      
 21 
     | 
    
         
            +
              spec.files += Dir.glob("lib/**/*.rb")
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.files += Dir.glob("ext/**/*.{rs,toml,lock,rb}")
         
     | 
| 
      
 23 
     | 
    
         
            +
              spec.bindir = "exe"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.extensions = ["ext/selma/Cargo.toml"]
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              spec.metadata = {
         
     | 
| 
      
 30 
     | 
    
         
            +
                "allowed_push_host" => "https://rubygems.org",
         
     | 
| 
      
 31 
     | 
    
         
            +
                "funding_uri" => "https://github.com/sponsors/gjtorikian/",
         
     | 
| 
      
 32 
     | 
    
         
            +
                "source_code_uri" => "https://github.com/gjtorikian/selma",
         
     | 
| 
      
 33 
     | 
    
         
            +
                "rubygems_mfa_required" => "true",
         
     | 
| 
      
 34 
     | 
    
         
            +
              }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              spec.add_dependency("rb_sys", "~> 0.9")
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              spec.add_development_dependency("rake", "~> 13.0")
         
     | 
| 
      
 39 
     | 
    
         
            +
              spec.add_development_dependency("rake-compiler", "~> 1.2")
         
     | 
| 
      
 40 
     | 
    
         
            +
              spec.add_development_dependency("rake-compiler-dock", "~> 1.2")
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,136 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: selma
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.2
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: x86_64-darwin
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Garen J. Torikian
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire:
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2022-12-21 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: rb_sys
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0.9'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '0.9'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '13.0'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '13.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rake-compiler
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '1.2'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '1.2'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: rake-compiler-dock
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '1.2'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '1.2'
         
     | 
| 
      
 69 
     | 
    
         
            +
            description:
         
     | 
| 
      
 70 
     | 
    
         
            +
            email:
         
     | 
| 
      
 71 
     | 
    
         
            +
            - gjtorikian@gmail.com
         
     | 
| 
      
 72 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 73 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 74 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 75 
     | 
    
         
            +
            files:
         
     | 
| 
      
 76 
     | 
    
         
            +
            - LICENSE.txt
         
     | 
| 
      
 77 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 78 
     | 
    
         
            +
            - ext/selma/Cargo.toml
         
     | 
| 
      
 79 
     | 
    
         
            +
            - ext/selma/_util.rb
         
     | 
| 
      
 80 
     | 
    
         
            +
            - ext/selma/extconf.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - ext/selma/src/html.rs
         
     | 
| 
      
 82 
     | 
    
         
            +
            - ext/selma/src/html/element.rs
         
     | 
| 
      
 83 
     | 
    
         
            +
            - ext/selma/src/html/end_tag.rs
         
     | 
| 
      
 84 
     | 
    
         
            +
            - ext/selma/src/lib.rs
         
     | 
| 
      
 85 
     | 
    
         
            +
            - ext/selma/src/native_ref_wrap.rs
         
     | 
| 
      
 86 
     | 
    
         
            +
            - ext/selma/src/rewriter.rs
         
     | 
| 
      
 87 
     | 
    
         
            +
            - ext/selma/src/sanitizer.rs
         
     | 
| 
      
 88 
     | 
    
         
            +
            - ext/selma/src/selector.rs
         
     | 
| 
      
 89 
     | 
    
         
            +
            - ext/selma/src/tags.rs
         
     | 
| 
      
 90 
     | 
    
         
            +
            - ext/selma/src/wrapped_struct.rs
         
     | 
| 
      
 91 
     | 
    
         
            +
            - lib/selma.rb
         
     | 
| 
      
 92 
     | 
    
         
            +
            - lib/selma/3.1/selma.bundle
         
     | 
| 
      
 93 
     | 
    
         
            +
            - lib/selma/extension.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - lib/selma/html.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - lib/selma/rewriter.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - lib/selma/sanitizer.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - lib/selma/sanitizer/config.rb
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib/selma/sanitizer/config/basic.rb
         
     | 
| 
      
 99 
     | 
    
         
            +
            - lib/selma/sanitizer/config/default.rb
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib/selma/sanitizer/config/relaxed.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib/selma/sanitizer/config/restricted.rb
         
     | 
| 
      
 102 
     | 
    
         
            +
            - lib/selma/selector.rb
         
     | 
| 
      
 103 
     | 
    
         
            +
            - lib/selma/version.rb
         
     | 
| 
      
 104 
     | 
    
         
            +
            - selma.gemspec
         
     | 
| 
      
 105 
     | 
    
         
            +
            homepage:
         
     | 
| 
      
 106 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 107 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 108 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 109 
     | 
    
         
            +
              allowed_push_host: https://rubygems.org
         
     | 
| 
      
 110 
     | 
    
         
            +
              funding_uri: https://github.com/sponsors/gjtorikian/
         
     | 
| 
      
 111 
     | 
    
         
            +
              source_code_uri: https://github.com/gjtorikian/selma
         
     | 
| 
      
 112 
     | 
    
         
            +
              rubygems_mfa_required: 'true'
         
     | 
| 
      
 113 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
      
 114 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 115 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 116 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 117 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 118 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 119 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 120 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 121 
     | 
    
         
            +
                  version: '3.1'
         
     | 
| 
      
 122 
     | 
    
         
            +
              - - "<"
         
     | 
| 
      
 123 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 124 
     | 
    
         
            +
                  version: 3.2.dev
         
     | 
| 
      
 125 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 126 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 127 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 128 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 129 
     | 
    
         
            +
                  version: 3.3.22
         
     | 
| 
      
 130 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 131 
     | 
    
         
            +
            rubygems_version: 3.3.22
         
     | 
| 
      
 132 
     | 
    
         
            +
            signing_key:
         
     | 
| 
      
 133 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 134 
     | 
    
         
            +
            summary: Selma selects and matches HTML nodes using CSS rules. Backed by Rust's lol_html
         
     | 
| 
      
 135 
     | 
    
         
            +
              parser.
         
     | 
| 
      
 136 
     | 
    
         
            +
            test_files: []
         
     |