class Joshua module Doc extend self ICONS = { github: { url: 'https://github.com/dux/joshua', image: '', }, twitter: { url: 'https://twitter.com/@dux', image: '', }, email: { url: 'mailto:reic.dino@gmail.com', image: '', }, error: { image: '' } } def tag HtmlTagBuilder end def misc_file name File.read [__dir__, '../misc/%s' % name].join('/') end # render full page def render mount_on: nil, request: nil, bearer: nil mount_on ||= request.url.split('?').first+'/' mount_on.sub! %r{//$}, '/' tag.html do |n| n.head do |n| n.title 'Joshua Tester' n.link({ href: "https://fonts.googleapis.com/css?family=Inter:300,400,500,600,700,800,900&display=swap", rel:"stylesheet" }) n.link({ rel:"stylesheet", href:"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" }) n.script({ src: 'https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js' }) n.script %[window.api_opts = { mount_on: '#{mount_on}', bearer: '#{bearer}' }] end n.body do |n| n.style { misc_file('doc.css') } n.header({ style: 'border-bottom: 1px solid rgb(228, 228, 228);'}) do |n| n._container do |n| n.push top_icons n.push %[] n.h1({ class: :nav}) { %[Joshua   Docs] } end end n.push modal_dialog n._container do |n| n._row do |n| n._col_3 do |n| n._sticky(style: 'padding-top: 30px;') do |n| n.a({ class: :dark, href: '#top' }) { '

API OBJECTS

' } n.push left_nav n.br n.br n.p 'TOOLS' n.div do |n| n.push %[

Named errors

] n.push %[

Postman import URL

] n.push %[

Raw doc data

] end n.br n.p 'API LIBRARIES' n.div do |n| n.push %[Ruby] n.push %[Javascript] n.push %[Python] n.push %[C#] end n.br n.p 'RESOURCES' n.div do |n| n.push %[Why we only prefer POST?] end end end n._col_9 do |n| n.push index n.push list_errors end end end end end end # anchor link def name_link name, top=nil %[] end # render single icon def icon data, size: 24, color: nil, style: nil %[#{data}] end # top side navigation icons def top_icons tag.div({ style: 'float: right; margin-top: 18px;' }) do |n| for icon in ICONS.values next unless icon[:url] n.push %[#{icon icon[:image]}] end end end # left side navigation def left_nav tag.div do |n| Joshua.documented.each do |name| n.a({ class:'btn btn-outline-info btn-sm', style: '-font-size: 14px; margin-bottom: 10px;', href: '#%s' % name}) do |n| icon = name.opts.dig(:opts, :icon) n.push self.icon icon, size: 20 if icon n.push name.to_s.sub(/Api$/, '') end n.br end end end # render doc for all documented classes def index tag.div do |n| for @klass in Joshua.documented @opts = @klass.opts icon = @opts.dig(:opts, :icon) n._sticky(style: 'background: #f7f7f7; padding-bottom: 5px; padding-top: 30px; margin-top: 2px;') do |n| n.push name_link @klass, 40 n.push self.icon icon, style: 'position: absolute; margin-left: -40px; margin-top: 1px; fill: #777; background: #f7f7f7;' if icon n.h4 { @klass.to_s.sub(/Api$/, '') } end if desc = @opts.dig(:opts, :desc) n.p { desc } end if detail = @opts.dig(:opts, :detail) n.p { detail } end n.push render_type :member n.push render_type :collection n.br n.hr n.br end end end # render members or collection def render_type name base = @opts[name] || return tag.div do |n| n.br n.h5 '%s methods' % name for m_name, member in base n.div do |n| n.push render_method name: name, m_name: m_name, opts: member end end end end # render api method def render_method name:, m_name:, opts: tag._box do |n| # n.push %[] anchor = [@klass, m_name].join('-') n.push name_link anchor n.h5 do |n| n.push "#{m_name}" n.push '   —   %s' % opts[:desc] if opts[:desc] end n.p({style: 'margin: 20px 0 25px 0;'}) do |n| path = @klass.api_path path += '/:id' if name == :member path += "/#{m_name}" n.push %[] end if opts[:detail] n.h6 'Details' n.pre opts[:detail] end if mopts = opts[:params] n.h6 'Params' n.ul do |n| for name, opt in mopts n.li do |n| n.push '%s: ' % name n.push opt[:type] data = [] data.push 'required' if opt[:required] data.push 'default: %s' % opt[:default].to_s unless opt[:default].nil? n.push ' — (%s)' % data.join(', ') if data.length > 0 end end end end end end def list_errors tag.div do |n| n.push name_link :api_errors n.push icon ICONS[:error][:image], style: 'position: absolute; margin-left: -40px; margin-top: 1px; fill: #777;' n.h4 { 'Named errors' } n._box do |n| if RESCUE_FROM.keys.length == 0 n.p 'No named errors defiend via' n.code "rescue from :name, 'Error description'" end n._row({ style: 'margin-bottom: 30px;' }) do |n| for key, desc in RESCUE_FROM next if key == :all next unless key.is_a?(Symbol) && desc.is_a?(String) n._col_4 { "#{key}" } n._col_8 { desc } end end end end end def modal_dialog %[ ] end end end