diff options
Diffstat (limited to 'logic')
-rw-r--r-- | logic/cartridge/parser.rb | 84 | ||||
-rw-r--r-- | logic/helpers/hash.rb | 13 |
2 files changed, 90 insertions, 7 deletions
diff --git a/logic/cartridge/parser.rb b/logic/cartridge/parser.rb index 308ca36..f82b968 100644 --- a/logic/cartridge/parser.rb +++ b/logic/cartridge/parser.rb @@ -22,7 +22,50 @@ module NanoBot end def self.markdown(raw) - yaml(Markdown.instance.render(raw)) + yaml_source = [] + + tools = [] + + blocks = Markdown.new.render(raw).blocks + + previous_block_is_tool = false + + blocks.each do |block| + if block[:language] == 'yaml' + parsed = Logic::Helpers::Hash.symbolize_keys( + YAML.safe_load(block[:source], permitted_classes: [Symbol]) + ) + + if parsed.key?(:tools) && parsed[:tools].is_a?(Array) && !parsed[:tools].empty? + previous_block_is_tool = true + + tools.concat(parsed[:tools]) + + parsed.delete(:tools) + + unless parsed.empty? + yaml_source << YAML.dump(Logic::Helpers::Hash.stringify_keys( + parsed + )).gsub(/^---/, '') # TODO: Is this safe enough? + end + else + yaml_source << block[:source] + previous_block_is_tool = false + nil + end + elsif previous_block_is_tool + tools.last[block[:language].to_sym] = block[:source] + previous_block_is_tool = false + end + end + + unless tools.empty? + yaml_source << YAML.dump(Logic::Helpers::Hash.stringify_keys( + { tools: } + )).gsub(/^---/, '') # TODO: Is this safe enough? + end + + yaml(yaml_source.join("\n")) end def self.yaml(raw) @@ -32,24 +75,51 @@ module NanoBot end class Renderer < Redcarpet::Render::Base + LANGUAGES_MAP = { + 'yml' => 'yaml', + 'yaml' => 'yaml', + 'lua' => 'lua', + 'fnl' => 'fennel', + 'fennel' => 'fennel', + 'clj' => 'clojure', + 'clojure' => 'clojure' + }.freeze + + LANGUAGES = LANGUAGES_MAP.keys.freeze + + def initialize(...) + super(...) + @_nano_bots_blocks = [] + end + + attr_reader :_nano_bots_blocks + def block_code(code, language) - return nil unless %w[yml yaml].include?(language.to_s.downcase.strip) + key = language.to_s.downcase.strip - "\n#{code}\n" + return nil unless LANGUAGES.include?(key) + + @_nano_bots_blocks << { language: LANGUAGES_MAP[key], source: code } + + nil end end class Markdown - include Singleton - attr_reader :markdown def initialize - @markdown = Redcarpet::Markdown.new(Renderer, fenced_code_blocks: true) + @renderer = Renderer.new + @markdown = Redcarpet::Markdown.new(@renderer, fenced_code_blocks: true) + end + + def blocks + @renderer._nano_bots_blocks end def render(raw) - @markdown.render(raw) + @markdown.render(raw.gsub(/```\w/, "\n\n\\0")) + self end end end diff --git a/logic/helpers/hash.rb b/logic/helpers/hash.rb index 90432b5..4cb44ac 100644 --- a/logic/helpers/hash.rb +++ b/logic/helpers/hash.rb @@ -17,6 +17,19 @@ module NanoBot end end + def self.stringify_keys(object) + case object + when ::Hash + object.each_with_object({}) do |(key, value), result| + result[key.to_s] = stringify_keys(value) + end + when Array + object.map { |e| stringify_keys(e) } + else + object + end + end + def self.fetch(object, path) node = object |