commonmarker 0.23.10 → 1.0.0
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 +4 -4
- data/Cargo.lock +1049 -0
- data/Cargo.toml +6 -0
- data/README.md +144 -203
- data/ext/commonmarker/Cargo.toml +13 -0
- data/ext/commonmarker/extconf.rb +3 -6
- data/ext/commonmarker/src/lib.rs +153 -0
- data/ext/commonmarker/src/options.rs +140 -0
- data/ext/commonmarker/src/plugins/syntax_highlighting.rs +74 -0
- data/ext/commonmarker/src/plugins.rs +3 -0
- data/ext/commonmarker/src/utils.rs +8 -0
- data/lib/commonmarker/config.rb +84 -40
- data/lib/commonmarker/constants.rb +7 -0
- data/lib/commonmarker/extension.rb +14 -0
- data/lib/commonmarker/renderer.rb +1 -127
- data/lib/commonmarker/utils.rb +22 -0
- data/lib/commonmarker/version.rb +2 -2
- data/lib/commonmarker.rb +14 -29
- metadata +36 -188
- data/Rakefile +0 -109
- data/bin/commonmarker +0 -118
- data/commonmarker.gemspec +0 -38
- data/ext/commonmarker/arena.c +0 -104
- data/ext/commonmarker/autolink.c +0 -508
- data/ext/commonmarker/autolink.h +0 -8
- data/ext/commonmarker/blocks.c +0 -1622
- data/ext/commonmarker/buffer.c +0 -278
- data/ext/commonmarker/buffer.h +0 -116
- data/ext/commonmarker/case_fold_switch.inc +0 -4327
- data/ext/commonmarker/chunk.h +0 -135
- data/ext/commonmarker/cmark-gfm-core-extensions.h +0 -54
- data/ext/commonmarker/cmark-gfm-extension_api.h +0 -737
- data/ext/commonmarker/cmark-gfm-extensions_export.h +0 -42
- data/ext/commonmarker/cmark-gfm.h +0 -833
- data/ext/commonmarker/cmark-gfm_export.h +0 -42
- data/ext/commonmarker/cmark-gfm_version.h +0 -7
- data/ext/commonmarker/cmark.c +0 -55
- data/ext/commonmarker/cmark_ctype.c +0 -44
- data/ext/commonmarker/cmark_ctype.h +0 -33
- data/ext/commonmarker/commonmark.c +0 -514
- data/ext/commonmarker/commonmarker.c +0 -1308
- data/ext/commonmarker/commonmarker.h +0 -16
- data/ext/commonmarker/config.h +0 -76
- data/ext/commonmarker/core-extensions.c +0 -27
- data/ext/commonmarker/entities.inc +0 -2138
- data/ext/commonmarker/ext_scanners.c +0 -879
- data/ext/commonmarker/ext_scanners.h +0 -24
- data/ext/commonmarker/footnotes.c +0 -63
- data/ext/commonmarker/footnotes.h +0 -27
- data/ext/commonmarker/houdini.h +0 -57
- data/ext/commonmarker/houdini_href_e.c +0 -100
- data/ext/commonmarker/houdini_html_e.c +0 -66
- data/ext/commonmarker/houdini_html_u.c +0 -149
- data/ext/commonmarker/html.c +0 -502
- data/ext/commonmarker/html.h +0 -27
- data/ext/commonmarker/inlines.c +0 -1788
- data/ext/commonmarker/inlines.h +0 -29
- data/ext/commonmarker/iterator.c +0 -159
- data/ext/commonmarker/iterator.h +0 -26
- data/ext/commonmarker/latex.c +0 -468
- data/ext/commonmarker/linked_list.c +0 -37
- data/ext/commonmarker/man.c +0 -274
- data/ext/commonmarker/map.c +0 -129
- data/ext/commonmarker/map.h +0 -44
- data/ext/commonmarker/node.c +0 -1045
- data/ext/commonmarker/node.h +0 -167
- data/ext/commonmarker/parser.h +0 -59
- data/ext/commonmarker/plaintext.c +0 -218
- data/ext/commonmarker/plugin.c +0 -36
- data/ext/commonmarker/plugin.h +0 -34
- data/ext/commonmarker/references.c +0 -43
- data/ext/commonmarker/references.h +0 -26
- data/ext/commonmarker/registry.c +0 -63
- data/ext/commonmarker/registry.h +0 -24
- data/ext/commonmarker/render.c +0 -213
- data/ext/commonmarker/render.h +0 -62
- data/ext/commonmarker/scanners.c +0 -14056
- data/ext/commonmarker/scanners.h +0 -70
- data/ext/commonmarker/scanners.re +0 -341
- data/ext/commonmarker/strikethrough.c +0 -167
- data/ext/commonmarker/strikethrough.h +0 -9
- data/ext/commonmarker/syntax_extension.c +0 -149
- data/ext/commonmarker/syntax_extension.h +0 -34
- data/ext/commonmarker/table.c +0 -917
- data/ext/commonmarker/table.h +0 -12
- data/ext/commonmarker/tagfilter.c +0 -60
- data/ext/commonmarker/tagfilter.h +0 -8
- data/ext/commonmarker/tasklist.c +0 -156
- data/ext/commonmarker/tasklist.h +0 -8
- data/ext/commonmarker/utf8.c +0 -317
- data/ext/commonmarker/utf8.h +0 -35
- data/ext/commonmarker/xml.c +0 -182
- data/lib/commonmarker/node/inspect.rb +0 -47
- data/lib/commonmarker/node.rb +0 -83
- data/lib/commonmarker/renderer/html_renderer.rb +0 -256
| @@ -0,0 +1,140 @@ | |
| 1 | 
            +
            use std::borrow::Cow;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            use comrak::ComrakOptions;
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            use magnus::value::ReprValue;
         | 
| 6 | 
            +
            use magnus::TryConvert;
         | 
| 7 | 
            +
            use magnus::{class, r_hash::ForEach, Error, RHash, Symbol, Value};
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            use crate::utils::try_convert_string;
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const PARSE_SMART: &str = "smart";
         | 
| 12 | 
            +
            const PARSE_DEFAULT_INFO_STRING: &str = "default_info_string";
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            fn iterate_parse_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
         | 
| 15 | 
            +
                options_hash
         | 
| 16 | 
            +
                    .foreach(|key: Symbol, value: Value| {
         | 
| 17 | 
            +
                        match key.name() {
         | 
| 18 | 
            +
                            Ok(Cow::Borrowed(PARSE_SMART)) => {
         | 
| 19 | 
            +
                                comrak_options.parse.smart = TryConvert::try_convert(value)?;
         | 
| 20 | 
            +
                            }
         | 
| 21 | 
            +
                            Ok(Cow::Borrowed(PARSE_DEFAULT_INFO_STRING)) => {
         | 
| 22 | 
            +
                                comrak_options.parse.default_info_string = try_convert_string(value);
         | 
| 23 | 
            +
                            }
         | 
| 24 | 
            +
                            _ => {}
         | 
| 25 | 
            +
                        }
         | 
| 26 | 
            +
                        Ok(ForEach::Continue)
         | 
| 27 | 
            +
                    })
         | 
| 28 | 
            +
                    .unwrap();
         | 
| 29 | 
            +
            }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            const RENDER_HARDBREAKS: &str = "hardbreaks";
         | 
| 32 | 
            +
            const RENDER_GITHUB_PRE_LANG: &str = "github_pre_lang";
         | 
| 33 | 
            +
            const RENDER_WIDTH: &str = "width";
         | 
| 34 | 
            +
            const RENDER_UNSAFE: &str = "unsafe";
         | 
| 35 | 
            +
            const RENDER_ESCAPE: &str = "escape";
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            fn iterate_render_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
         | 
| 38 | 
            +
                options_hash
         | 
| 39 | 
            +
                    .foreach(|key: Symbol, value: Value| {
         | 
| 40 | 
            +
                        match key.name() {
         | 
| 41 | 
            +
                            Ok(Cow::Borrowed(RENDER_HARDBREAKS)) => {
         | 
| 42 | 
            +
                                comrak_options.render.hardbreaks = TryConvert::try_convert(value)?;
         | 
| 43 | 
            +
                            }
         | 
| 44 | 
            +
                            Ok(Cow::Borrowed(RENDER_GITHUB_PRE_LANG)) => {
         | 
| 45 | 
            +
                                comrak_options.render.github_pre_lang = TryConvert::try_convert(value)?;
         | 
| 46 | 
            +
                            }
         | 
| 47 | 
            +
                            Ok(Cow::Borrowed(RENDER_WIDTH)) => {
         | 
| 48 | 
            +
                                comrak_options.render.width = TryConvert::try_convert(value)?;
         | 
| 49 | 
            +
                            }
         | 
| 50 | 
            +
                            Ok(Cow::Borrowed(RENDER_UNSAFE)) => {
         | 
| 51 | 
            +
                                comrak_options.render.unsafe_ = TryConvert::try_convert(value)?;
         | 
| 52 | 
            +
                            }
         | 
| 53 | 
            +
                            Ok(Cow::Borrowed(RENDER_ESCAPE)) => {
         | 
| 54 | 
            +
                                comrak_options.render.escape = TryConvert::try_convert(value)?;
         | 
| 55 | 
            +
                            }
         | 
| 56 | 
            +
                            _ => {}
         | 
| 57 | 
            +
                        }
         | 
| 58 | 
            +
                        Ok(ForEach::Continue)
         | 
| 59 | 
            +
                    })
         | 
| 60 | 
            +
                    .unwrap();
         | 
| 61 | 
            +
            }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            const EXTENSION_STRIKETHROUGH: &str = "strikethrough";
         | 
| 64 | 
            +
            const EXTENSION_TAGFILTER: &str = "tagfilter";
         | 
| 65 | 
            +
            const EXTENSION_TABLE: &str = "table";
         | 
| 66 | 
            +
            const EXTENSION_AUTOLINK: &str = "autolink";
         | 
| 67 | 
            +
            const EXTENSION_TASKLIST: &str = "tasklist";
         | 
| 68 | 
            +
            const EXTENSION_SUPERSCRIPT: &str = "superscript";
         | 
| 69 | 
            +
            const EXTENSION_HEADER_IDS: &str = "header_ids";
         | 
| 70 | 
            +
            const EXTENSION_FOOTNOTES: &str = "footnotes";
         | 
| 71 | 
            +
            const EXTENSION_DESCRIPTION_LISTS: &str = "description_lists";
         | 
| 72 | 
            +
            const EXTENSION_FRONT_MATTER_DELIMITER: &str = "front_matter_delimiter";
         | 
| 73 | 
            +
            const EXTENSION_SHORTCODES: &str = "shortcodes";
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            fn iterate_extension_options(comrak_options: &mut ComrakOptions, options_hash: RHash) {
         | 
| 76 | 
            +
                options_hash
         | 
| 77 | 
            +
                    .foreach(|key: Symbol, value: Value| {
         | 
| 78 | 
            +
                        match key.name() {
         | 
| 79 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_STRIKETHROUGH)) => {
         | 
| 80 | 
            +
                                comrak_options.extension.strikethrough = TryConvert::try_convert(value)?;
         | 
| 81 | 
            +
                            }
         | 
| 82 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_TAGFILTER)) => {
         | 
| 83 | 
            +
                                comrak_options.extension.tagfilter = TryConvert::try_convert(value)?;
         | 
| 84 | 
            +
                            }
         | 
| 85 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_TABLE)) => {
         | 
| 86 | 
            +
                                comrak_options.extension.table = TryConvert::try_convert(value)?;
         | 
| 87 | 
            +
                            }
         | 
| 88 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_AUTOLINK)) => {
         | 
| 89 | 
            +
                                comrak_options.extension.autolink = TryConvert::try_convert(value)?;
         | 
| 90 | 
            +
                            }
         | 
| 91 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_TASKLIST)) => {
         | 
| 92 | 
            +
                                comrak_options.extension.tasklist = TryConvert::try_convert(value)?;
         | 
| 93 | 
            +
                            }
         | 
| 94 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_SUPERSCRIPT)) => {
         | 
| 95 | 
            +
                                comrak_options.extension.superscript = TryConvert::try_convert(value)?;
         | 
| 96 | 
            +
                            }
         | 
| 97 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_HEADER_IDS)) => {
         | 
| 98 | 
            +
                                comrak_options.extension.header_ids = try_convert_string(value);
         | 
| 99 | 
            +
                            }
         | 
| 100 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_FOOTNOTES)) => {
         | 
| 101 | 
            +
                                comrak_options.extension.footnotes = TryConvert::try_convert(value)?;
         | 
| 102 | 
            +
                            }
         | 
| 103 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_DESCRIPTION_LISTS)) => {
         | 
| 104 | 
            +
                                comrak_options.extension.description_lists = TryConvert::try_convert(value)?;
         | 
| 105 | 
            +
                            }
         | 
| 106 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_FRONT_MATTER_DELIMITER)) => {
         | 
| 107 | 
            +
                                if let Some(option) = try_convert_string(value) {
         | 
| 108 | 
            +
                                    if !option.is_empty() {
         | 
| 109 | 
            +
                                        comrak_options.extension.front_matter_delimiter = Some(option);
         | 
| 110 | 
            +
                                    }
         | 
| 111 | 
            +
                                }
         | 
| 112 | 
            +
                            }
         | 
| 113 | 
            +
                            Ok(Cow::Borrowed(EXTENSION_SHORTCODES)) => {
         | 
| 114 | 
            +
                                comrak_options.extension.shortcodes = TryConvert::try_convert(value)?;
         | 
| 115 | 
            +
                            }
         | 
| 116 | 
            +
                            _ => {}
         | 
| 117 | 
            +
                        }
         | 
| 118 | 
            +
                        Ok(ForEach::Continue)
         | 
| 119 | 
            +
                    })
         | 
| 120 | 
            +
                    .unwrap();
         | 
| 121 | 
            +
            }
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            pub fn iterate_options_hash(
         | 
| 124 | 
            +
                comrak_options: &mut ComrakOptions,
         | 
| 125 | 
            +
                key: Symbol,
         | 
| 126 | 
            +
                value: RHash,
         | 
| 127 | 
            +
            ) -> Result<ForEach, Error> {
         | 
| 128 | 
            +
                assert!(value.is_kind_of(class::hash()));
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                if key.name().unwrap() == "parse" {
         | 
| 131 | 
            +
                    iterate_parse_options(comrak_options, value);
         | 
| 132 | 
            +
                }
         | 
| 133 | 
            +
                if key.name().unwrap() == "render" {
         | 
| 134 | 
            +
                    iterate_render_options(comrak_options, value);
         | 
| 135 | 
            +
                }
         | 
| 136 | 
            +
                if key.name().unwrap() == "extension" {
         | 
| 137 | 
            +
                    iterate_extension_options(comrak_options, value);
         | 
| 138 | 
            +
                }
         | 
| 139 | 
            +
                Ok(ForEach::Continue)
         | 
| 140 | 
            +
            }
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            use std::path::PathBuf;
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            use magnus::value::ReprValue;
         | 
| 4 | 
            +
            use magnus::{RHash, Symbol, TryConvert, Value};
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            use crate::EMPTY_STR;
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            pub const SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY: &str = "theme";
         | 
| 9 | 
            +
            pub const SYNTAX_HIGHLIGHTER_PLUGIN_PATH_KEY: &str = "path";
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            pub fn fetch_syntax_highlighter_theme(value: Value) -> Result<Option<String>, magnus::Error> {
         | 
| 12 | 
            +
                if value.is_nil() {
         | 
| 13 | 
            +
                    // `syntax_highlighter: nil`
         | 
| 14 | 
            +
                    return Ok(None);
         | 
| 15 | 
            +
                }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                let syntax_highlighter_plugin: RHash = match TryConvert::try_convert(value) {
         | 
| 18 | 
            +
                    Ok(plugin) => plugin, // `syntax_highlighter: { theme: "<something>" }`
         | 
| 19 | 
            +
                    Err(e) => {
         | 
| 20 | 
            +
                        // not a hash!
         | 
| 21 | 
            +
                        return Err(e);
         | 
| 22 | 
            +
                    }
         | 
| 23 | 
            +
                };
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                if syntax_highlighter_plugin.is_nil() || syntax_highlighter_plugin.is_empty() {
         | 
| 26 | 
            +
                    return Err(magnus::Error::new(
         | 
| 27 | 
            +
                        magnus::exception::type_error(),
         | 
| 28 | 
            +
                        "theme cannot be blank hash",
         | 
| 29 | 
            +
                    ));
         | 
| 30 | 
            +
                }
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                let theme_key = Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN_THEME_KEY);
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                match syntax_highlighter_plugin.get(theme_key) {
         | 
| 35 | 
            +
                    Some(theme) => {
         | 
| 36 | 
            +
                        if theme.is_nil() {
         | 
| 37 | 
            +
                            return Err(magnus::Error::new(
         | 
| 38 | 
            +
                                magnus::exception::type_error(),
         | 
| 39 | 
            +
                                "theme cannot be nil",
         | 
| 40 | 
            +
                            ));
         | 
| 41 | 
            +
                        }
         | 
| 42 | 
            +
                        Ok(TryConvert::try_convert(theme)?)
         | 
| 43 | 
            +
                    }
         | 
| 44 | 
            +
                    None => {
         | 
| 45 | 
            +
                        // `syntax_highlighter: { theme: nil }`
         | 
| 46 | 
            +
                        Ok(None)
         | 
| 47 | 
            +
                    }
         | 
| 48 | 
            +
                }
         | 
| 49 | 
            +
            }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            pub fn fetch_syntax_highlighter_path(value: Value) -> Result<PathBuf, magnus::Error> {
         | 
| 52 | 
            +
                if value.is_nil() {
         | 
| 53 | 
            +
                    // `syntax_highlighter: nil`
         | 
| 54 | 
            +
                    return Ok(PathBuf::from(EMPTY_STR));
         | 
| 55 | 
            +
                }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                let syntax_highlighter_plugin: RHash = TryConvert::try_convert(value)?;
         | 
| 58 | 
            +
                let path_key = Symbol::new(SYNTAX_HIGHLIGHTER_PLUGIN_PATH_KEY);
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                match syntax_highlighter_plugin.get(path_key) {
         | 
| 61 | 
            +
                    Some(path) => {
         | 
| 62 | 
            +
                        if path.is_nil() {
         | 
| 63 | 
            +
                            // `syntax_highlighter: { path: nil }`
         | 
| 64 | 
            +
                            return Ok(PathBuf::from(EMPTY_STR));
         | 
| 65 | 
            +
                        }
         | 
| 66 | 
            +
                        let val: String = TryConvert::try_convert(path)?;
         | 
| 67 | 
            +
                        Ok(PathBuf::from(val))
         | 
| 68 | 
            +
                    }
         | 
| 69 | 
            +
                    None => {
         | 
| 70 | 
            +
                        // `syntax_highlighter: {  }`
         | 
| 71 | 
            +
                        Ok(PathBuf::from(EMPTY_STR))
         | 
| 72 | 
            +
                    }
         | 
| 73 | 
            +
                }
         | 
| 74 | 
            +
            }
         | 
    
        data/lib/commonmarker/config.rb
    CHANGED
    
    | @@ -1,54 +1,98 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            module  | 
| 4 | 
            -
              # For Ruby::Enum, these must be classes, not modules
         | 
| 3 | 
            +
            module Commonmarker
         | 
| 5 4 | 
             
              module Config
         | 
| 6 | 
            -
                #  | 
| 7 | 
            -
                 | 
| 5 | 
            +
                # For details, see
         | 
| 6 | 
            +
                # https://github.com/kivikakk/comrak/blob/162ef9354deb2c9b4a4e05be495aa372ba5bb696/src/main.rs#L201
         | 
| 7 | 
            +
                OPTIONS = {
         | 
| 8 8 | 
             
                  parse: {
         | 
| 9 | 
            -
                     | 
| 10 | 
            -
                     | 
| 11 | 
            -
                    UNSAFE: (1 << 17),
         | 
| 12 | 
            -
                    VALIDATE_UTF8: (1 << 9),
         | 
| 13 | 
            -
                    SMART: (1 << 10),
         | 
| 14 | 
            -
                    LIBERAL_HTML_TAG: (1 << 12),
         | 
| 15 | 
            -
                    FOOTNOTES: (1 << 13),
         | 
| 16 | 
            -
                    STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
         | 
| 9 | 
            +
                    smart: false,
         | 
| 10 | 
            +
                    default_info_string: "",
         | 
| 17 11 | 
             
                  }.freeze,
         | 
| 18 12 | 
             
                  render: {
         | 
| 19 | 
            -
                     | 
| 20 | 
            -
                     | 
| 21 | 
            -
                     | 
| 22 | 
            -
                     | 
| 23 | 
            -
                     | 
| 24 | 
            -
                    VALIDATE_UTF8: (1 << 9),
         | 
| 25 | 
            -
                    SMART: (1 << 10),
         | 
| 26 | 
            -
                    GITHUB_PRE_LANG: (1 << 11),
         | 
| 27 | 
            -
                    LIBERAL_HTML_TAG: (1 << 12),
         | 
| 28 | 
            -
                    FOOTNOTES: (1 << 13),
         | 
| 29 | 
            -
                    STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
         | 
| 30 | 
            -
                    TABLE_PREFER_STYLE_ATTRIBUTES: (1 << 15),
         | 
| 31 | 
            -
                    FULL_INFO_STRING: (1 << 16),
         | 
| 13 | 
            +
                    hardbreaks: true,
         | 
| 14 | 
            +
                    github_pre_lang: true,
         | 
| 15 | 
            +
                    width: 80,
         | 
| 16 | 
            +
                    unsafe: false,
         | 
| 17 | 
            +
                    escape: false,
         | 
| 32 18 | 
             
                  }.freeze,
         | 
| 33 | 
            -
                   | 
| 19 | 
            +
                  extension: {
         | 
| 20 | 
            +
                    strikethrough: true,
         | 
| 21 | 
            +
                    tagfilter: true,
         | 
| 22 | 
            +
                    table: true,
         | 
| 23 | 
            +
                    autolink: true,
         | 
| 24 | 
            +
                    tasklist: true,
         | 
| 25 | 
            +
                    superscript: false,
         | 
| 26 | 
            +
                    header_ids: "",
         | 
| 27 | 
            +
                    footnotes: false,
         | 
| 28 | 
            +
                    description_lists: false,
         | 
| 29 | 
            +
                    front_matter_delimiter: "",
         | 
| 30 | 
            +
                    shortcodes: true,
         | 
| 31 | 
            +
                  },
         | 
| 32 | 
            +
                  format: [:html].freeze,
         | 
| 34 33 | 
             
                }.freeze
         | 
| 35 34 |  | 
| 35 | 
            +
                PLUGINS = {
         | 
| 36 | 
            +
                  syntax_highlighter: {
         | 
| 37 | 
            +
                    theme: "base16-ocean.dark",
         | 
| 38 | 
            +
                    path: "",
         | 
| 39 | 
            +
                  },
         | 
| 40 | 
            +
                }
         | 
| 41 | 
            +
             | 
| 36 42 | 
             
                class << self
         | 
| 37 | 
            -
                   | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
                       | 
| 46 | 
            -
             | 
| 47 | 
            -
                       | 
| 43 | 
            +
                  include Commonmarker::Utils
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def merged_with_defaults(options)
         | 
| 46 | 
            +
                    Commonmarker::Config::OPTIONS.merge(process_options(options))
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def process_options(options)
         | 
| 50 | 
            +
                    {
         | 
| 51 | 
            +
                      parse: process_parse_options(options[:parse]),
         | 
| 52 | 
            +
                      render: process_render_options(options[:render]),
         | 
| 53 | 
            +
                      extension: process_extension_options(options[:extension]),
         | 
| 54 | 
            +
                    }
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def process_plugins(plugins)
         | 
| 58 | 
            +
                    {
         | 
| 59 | 
            +
                      syntax_highlighter: process_syntax_highlighter_plugin(plugins&.fetch(:syntax_highlighter, nil)),
         | 
| 60 | 
            +
                    }
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                [:parse, :render, :extension].each do |type|
         | 
| 65 | 
            +
                  define_singleton_method :"process_#{type}_options" do |option|
         | 
| 66 | 
            +
                    Commonmarker::Config::OPTIONS[type].each_with_object({}) do |(key, value), hash|
         | 
| 67 | 
            +
                      if option.nil? # option not provided, go for the default
         | 
| 68 | 
            +
                        hash[key] = value
         | 
| 69 | 
            +
                        next
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                      # option explicitly not included, remove it
         | 
| 73 | 
            +
                      next if option[key].nil?
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      hash[key] = fetch_kv(option, key, value, type)
         | 
| 48 76 | 
             
                    end
         | 
| 49 | 
            -
                  rescue KeyError => e
         | 
| 50 | 
            -
                    raise TypeError, "option ':#{e.key}' does not exist for #{name}::OPTS[:#{type}]"
         | 
| 51 77 | 
             
                  end
         | 
| 52 | 
            -
             | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                [:syntax_highlighter].each do |type|
         | 
| 81 | 
            +
                  define_singleton_method :"process_#{type}_plugin" do |plugin|
         | 
| 82 | 
            +
                    return if plugin.nil? # plugin explicitly nil, remove it
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    Commonmarker::Config::PLUGINS[type].each_with_object({}) do |(key, value), hash|
         | 
| 85 | 
            +
                      if plugin.nil? # option not provided, go for the default
         | 
| 86 | 
            +
                        hash[key] = value
         | 
| 87 | 
            +
                        next
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                      # option explicitly not included, remove it
         | 
| 91 | 
            +
                      next if plugin[key].nil?
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                      hash[key] = fetch_kv(plugin, key, value, type)
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end
         | 
| 53 97 | 
             
              end
         | 
| 54 98 | 
             
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            begin
         | 
| 4 | 
            +
              # native precompiled gems package shared libraries in <gem_dir>/lib/commonmarker/<ruby_version>
         | 
| 5 | 
            +
              # load the precompiled extension file
         | 
| 6 | 
            +
              ruby_version = /\d+\.\d+/.match(RUBY_VERSION)
         | 
| 7 | 
            +
              require_relative "#{ruby_version}/commonmarker"
         | 
| 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 "commonmarker/commonmarker"
         | 
| 14 | 
            +
            end
         | 
| @@ -3,133 +3,7 @@ | |
| 3 3 | 
             
            require "set"
         | 
| 4 4 | 
             
            require "stringio"
         | 
| 5 5 |  | 
| 6 | 
            -
            module  | 
| 6 | 
            +
            module Commonmarker
         | 
| 7 7 | 
             
              class Renderer
         | 
| 8 | 
            -
                attr_accessor :in_tight, :warnings, :in_plain
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                def initialize(options: :DEFAULT, extensions: [])
         | 
| 11 | 
            -
                  @opts = Config.process_options(options, :render)
         | 
| 12 | 
            -
                  @stream = StringIO.new(+"")
         | 
| 13 | 
            -
                  @need_blocksep = false
         | 
| 14 | 
            -
                  @warnings = Set.new([])
         | 
| 15 | 
            -
                  @in_tight = false
         | 
| 16 | 
            -
                  @in_plain = false
         | 
| 17 | 
            -
                  @tagfilter = extensions.include?(:tagfilter)
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                def out(*args)
         | 
| 21 | 
            -
                  args.each do |arg|
         | 
| 22 | 
            -
                    case arg
         | 
| 23 | 
            -
                    when :children
         | 
| 24 | 
            -
                      @node.each { |child| out(child) }
         | 
| 25 | 
            -
                    when Array
         | 
| 26 | 
            -
                      arg.each { |x| render(x) }
         | 
| 27 | 
            -
                    when Node
         | 
| 28 | 
            -
                      render(arg)
         | 
| 29 | 
            -
                    else
         | 
| 30 | 
            -
                      @stream.write(arg)
         | 
| 31 | 
            -
                    end
         | 
| 32 | 
            -
                  end
         | 
| 33 | 
            -
                end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                def render(node)
         | 
| 36 | 
            -
                  @node = node
         | 
| 37 | 
            -
                  if node.type == :document
         | 
| 38 | 
            -
                    document(node)
         | 
| 39 | 
            -
                    @stream.string
         | 
| 40 | 
            -
                  elsif @in_plain && node.type != :text && node.type != :softbreak
         | 
| 41 | 
            -
                    node.each { |child| render(child) }
         | 
| 42 | 
            -
                  else
         | 
| 43 | 
            -
                    begin
         | 
| 44 | 
            -
                      send(node.type, node)
         | 
| 45 | 
            -
                    rescue NoMethodError => e
         | 
| 46 | 
            -
                      @warnings.add("WARNING: #{node.type} not implemented.")
         | 
| 47 | 
            -
                      raise e
         | 
| 48 | 
            -
                    end
         | 
| 49 | 
            -
                  end
         | 
| 50 | 
            -
                end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                def document(_node)
         | 
| 53 | 
            -
                  out(:children)
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                def code_block(node)
         | 
| 57 | 
            -
                  code_block(node)
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                def reference_def(_node); end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                def cr
         | 
| 63 | 
            -
                  return if @stream.string.empty? || @stream.string[-1] == "\n"
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                  out("\n")
         | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                def blocksep
         | 
| 69 | 
            -
                  out("\n")
         | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                def containersep
         | 
| 73 | 
            -
                  cr unless @in_tight
         | 
| 74 | 
            -
                end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                def block
         | 
| 77 | 
            -
                  cr
         | 
| 78 | 
            -
                  yield
         | 
| 79 | 
            -
                  cr
         | 
| 80 | 
            -
                end
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                def container(starter, ender)
         | 
| 83 | 
            -
                  out(starter)
         | 
| 84 | 
            -
                  yield
         | 
| 85 | 
            -
                  out(ender)
         | 
| 86 | 
            -
                end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                def plain
         | 
| 89 | 
            -
                  old_in_plain = @in_plain
         | 
| 90 | 
            -
                  @in_plain = true
         | 
| 91 | 
            -
                  yield
         | 
| 92 | 
            -
                  @in_plain = old_in_plain
         | 
| 93 | 
            -
                end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                private
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                def escape_href(str)
         | 
| 98 | 
            -
                  @node.html_escape_href(str)
         | 
| 99 | 
            -
                end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                def escape_html(str)
         | 
| 102 | 
            -
                  @node.html_escape_html(str)
         | 
| 103 | 
            -
                end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                def tagfilter(str)
         | 
| 106 | 
            -
                  if @tagfilter
         | 
| 107 | 
            -
                    str.gsub(
         | 
| 108 | 
            -
                      %r{
         | 
| 109 | 
            -
                        <
         | 
| 110 | 
            -
                        (
         | 
| 111 | 
            -
                        title|textarea|style|xmp|iframe|
         | 
| 112 | 
            -
                        noembed|noframes|script|plaintext
         | 
| 113 | 
            -
                        )
         | 
| 114 | 
            -
                        (?=\s|>|/>)
         | 
| 115 | 
            -
                      }xi,
         | 
| 116 | 
            -
                      '<\1',
         | 
| 117 | 
            -
                    )
         | 
| 118 | 
            -
                  else
         | 
| 119 | 
            -
                    str
         | 
| 120 | 
            -
                  end
         | 
| 121 | 
            -
                end
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                def sourcepos(node)
         | 
| 124 | 
            -
                  return "" unless option_enabled?(:SOURCEPOS)
         | 
| 125 | 
            -
             | 
| 126 | 
            -
                  s = node.sourcepos
         | 
| 127 | 
            -
                  " data-sourcepos=\"#{s[:start_line]}:#{s[:start_column]}-" \
         | 
| 128 | 
            -
                    "#{s[:end_line]}:#{s[:end_column]}\""
         | 
| 129 | 
            -
                end
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                def option_enabled?(opt)
         | 
| 132 | 
            -
                  (@opts & CommonMarker::Config::OPTS.dig(:render, opt)) != 0
         | 
| 133 | 
            -
                end
         | 
| 134 8 | 
             
              end
         | 
| 135 9 | 
             
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "commonmarker/constants"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Commonmarker
         | 
| 6 | 
            +
              module Utils
         | 
| 7 | 
            +
                include Commonmarker::Constants
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def fetch_kv(option, key, value, type)
         | 
| 10 | 
            +
                  value_klass = value.class
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  if Constants::BOOLS.include?(value) && BOOLS.include?(option[key])
         | 
| 13 | 
            +
                    option[key]
         | 
| 14 | 
            +
                  elsif option[key].is_a?(value_klass)
         | 
| 15 | 
            +
                    option[key]
         | 
| 16 | 
            +
                  else
         | 
| 17 | 
            +
                    expected_type = Constants::BOOLS.include?(value) ? "Boolean" : value_klass.to_s
         | 
| 18 | 
            +
                    raise TypeError, "#{type} option `:#{key}` must be #{expected_type}; got #{option[key].class}"
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
    
        data/lib/commonmarker/version.rb
    CHANGED
    
    
    
        data/lib/commonmarker.rb
    CHANGED
    
    | @@ -1,45 +1,30 @@ | |
| 1 | 
            -
            #!/usr/bin/env ruby
         | 
| 2 1 | 
             
            # frozen_string_literal: true
         | 
| 3 2 |  | 
| 4 | 
            -
             | 
| 3 | 
            +
            require_relative "commonmarker/extension"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "commonmarker/utils"
         | 
| 5 6 | 
             
            require "commonmarker/config"
         | 
| 6 | 
            -
            require "commonmarker/node"
         | 
| 7 7 | 
             
            require "commonmarker/renderer"
         | 
| 8 | 
            -
            require "commonmarker/renderer/html_renderer"
         | 
| 9 8 | 
             
            require "commonmarker/version"
         | 
| 10 9 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
              require "awesome_print"
         | 
| 13 | 
            -
            rescue LoadError; end # rubocop:disable Lint/SuppressedException
         | 
| 14 | 
            -
            module CommonMarker
         | 
| 10 | 
            +
            module Commonmarker
         | 
| 15 11 | 
             
              class << self
         | 
| 16 | 
            -
                # Public: | 
| 12 | 
            +
                # Public: Parses a CommonMark string into an HTML string.
         | 
| 17 13 | 
             
                #
         | 
| 18 14 | 
             
                # text - A {String} of text
         | 
| 19 | 
            -
                #  | 
| 20 | 
            -
                #  | 
| 15 | 
            +
                # options - A {Hash} of render, parse, and extension options to transform the text.
         | 
| 16 | 
            +
                # plugins - A {Hash} of additional plugins.
         | 
| 21 17 | 
             
                #
         | 
| 22 18 | 
             
                # Returns a {String} of converted HTML.
         | 
| 23 | 
            -
                def  | 
| 19 | 
            +
                def to_html(text, options: Commonmarker::Config::OPTIONS, plugins: Commonmarker::Config::PLUGINS)
         | 
| 24 20 | 
             
                  raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
         | 
| 21 | 
            +
                  raise TypeError, "text must be UTF-8 encoded; got #{text.encoding}!" unless text.encoding.name == "UTF-8"
         | 
| 22 | 
            +
                  raise TypeError, "options must be a Hash; got a #{options.class}!" unless options.is_a?(Hash)
         | 
| 25 23 |  | 
| 26 | 
            -
                  opts = Config.process_options(options | 
| 27 | 
            -
                   | 
| 28 | 
            -
                end
         | 
| 24 | 
            +
                  opts = Config.process_options(options)
         | 
| 25 | 
            +
                  plugins = Config.process_plugins(plugins)
         | 
| 29 26 |  | 
| 30 | 
            -
             | 
| 31 | 
            -
                #
         | 
| 32 | 
            -
                # string - {String} to be parsed
         | 
| 33 | 
            -
                # option - A {Symbol} or {Array of Symbol}s indicating the parse options
         | 
| 34 | 
            -
                # extensions - An {Array of Symbol}s indicating the extensions to use
         | 
| 35 | 
            -
                #
         | 
| 36 | 
            -
                # Returns the `document` node.
         | 
| 37 | 
            -
                def render_doc(text, options = :DEFAULT, extensions = [])
         | 
| 38 | 
            -
                  raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                  opts = Config.process_options(options, :parse)
         | 
| 41 | 
            -
                  text = text.encode("UTF-8")
         | 
| 42 | 
            -
                  Node.parse_document(text, text.bytesize, opts, extensions)
         | 
| 27 | 
            +
                  commonmark_to_html(text, options: opts, plugins: plugins)
         | 
| 43 28 | 
             
                end
         | 
| 44 | 
            -
            end
         | 
| 29 | 
            +
              end
         | 
| 45 30 | 
             
            end
         |