# frozen_string_literal: true require_relative 'boilerplate' require_relative "statosio/version" require 'puppeteer' module Statosio class Error < StandardError; end class Generate < Boilerplate def svg( dataset: nil, x: nil, y: nil, options: nil, silent: false ) valid = values_validation( dataset: dataset, x: x, y: y, options: options, allow_list: @options_allow_list, silent: silent ) if valid values = {} values[:dataset] = dataset values[:x] = x values[:y] = y values[:options] = options render_svg( values ) end end def get_options_allow_list @options_allow_list end def render_prepare( values ) values[:y].class.to_s == 'String' ? values[:y] = [ values[:y] ] : '' self.set_markers_value( values ) self.set_boilerplate html = self.get_boilerplate end def render_svg( values ) html = self.render_prepare( values ) g = {} id = 'd3_statosio' g[:start] = '
' g[:end] = '
' svg = Puppeteer.launch do | browser | page = browser.pages.last || browser.new_page page.set_content( html ) html = page.evaluate( 'document.body.innerHTML' ) tmp = html[ html.index( g[:start] ) + g[:start].length, html.length] tmp = tmp[ 0, tmp.index( g[:end] ) ] end return svg end def values_validation( dataset: nil, x: nil, y: nil, options: nil, allow_list: nil, silent: false ) def check_dataset( dataset, messages, errors ) if !dataset.nil? if dataset.class.to_s == 'Array' if dataset[ 0 ].class.to_s == 'Hash' or dataset[ 0 ].class.to_s == 'ActiveSupport::HashWithIndifferentAccess' if dataset[ 0 ].keys.length > 1 search = dataset[ 0 ].keys keys = dataset .map { | a | a.keys } .flatten .to_set .to_a if keys.eql? search else errors.push( messages[:dataset][ 4 ] ) end else errors.push( messages[:dataset][ 3 ] ) end else errors.push( messages[:dataset][ 2 ] ) end else errors.push( messages[:dataset][ 1 ] ) end else errors.push( messages[:dataset][ 0 ] ) end return errors end def check_x( x, messages, errors ) if !x.nil? if x.class.to_s == 'String' else errors.push( messages[:x][ 1 ] ) end else errors.push( messages[:x][ 0 ] ) end return errors end def check_y( y, messages, errors ) if !y.nil? if y.class.to_s == 'String' or y.class.to_s == 'Array' else errors.push( messages[:y][ 1 ] ) end else errors.push( messages[:y][ 0 ] ) end return errors end def check_options( options, messages, allow_list, errors ) def str_difference( a, b ) a = a.to_s.downcase.split( '_' ).join( '' ) b = b.to_s.downcase.split( '_' ).join( '' ) longer = [ a.size, b.size ].max same = a .each_char .zip( b.each_char ) .select { | a, b | a == b } .size ( longer - same ) / a.size.to_f end if !options.nil? if options.class.to_s == 'Hash' options.keys.each do | key | if allow_list.include?( key.to_s ) else tmp = messages[:options][ 2 ][ 0 ] tmp = tmp.gsub( '<--key-->', key.to_s) nearest = allow_list .map { | word | { score: str_difference( key, word ), word: word } } .min_by { | item | item[:score] } tmp = tmp.gsub( '<--similar-->', nearest[:word] ) errors.push( [ tmp, messages[:options][ 2 ][ 1 ] ] ) end end else errors.push( messages[:options][ 1 ] ) end else errors.push( messages[:options][ 0 ] ) end return errors end def check_silent( silent, messages, errors ) value = silent.class.to_s if value == 'FalseClass' or value == 'TrueClass' else errors.push( messages[:silent][ 0 ] ) end return errors end messages = { dataset: [ [ "dataset:\t is empty. Expect: \"Array\" [{},{}]", :d0 ], [ "dataset:\t is not class \"Array\"", :d1 ], [ "dataset:\t is not class \"Hash\"", :d2 ], [ "dataset:\t \"Hash\" has less then 2 keys", :d3 ], [ "dataset:\t have diffrent keys", :d4 ] ], x: [ [ "x:\t\t is empty. Expect: \"String\"", :x0 ], [ "x:\t\t is not Class \"String\"", :x1 ] ], y: [ [ "y:\t\t is empty. Expect: \"String\"", :y0 ], [ "y:\t\t is not Class \"String\"", :y1 ] ], options: [ [ "options:\t is empty. Expect: \"Hash\"", :p0 ], [ "options:\t is not Class \"Hash\"", :p1 ], [ "options:\t key: \"<--key-->\" is not a valid parameter, did you mean: \"<--similar-->\"? For more Information visit: https://docs.statosio.com/options/<--similar-->", :p2 ] ], silent: [ [ "silent:\t is not Class \"Hash\"", :s0 ] ] } errors = [] errors = check_dataset( dataset, messages, errors ) errors = check_y( y, messages, errors ) errors = check_x( x, messages, errors ) errors = check_options( options, messages, allow_list, errors ) errors = check_silent( silent, messages, errors ) if silent == false if errors.length != 0 puts errors.length.to_s + ' Errors found: ' errors.each { | error | puts( ' - ' + error[ 0 ] ) } end end return errors.length == 0 end end end