173 lines
4.3 KiB
Ruby
173 lines
4.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'cgi'
|
|
require 'date'
|
|
require 'forwardable'
|
|
require 'open3'
|
|
require 'pathname'
|
|
require 'uri'
|
|
require 'yaml'
|
|
|
|
require 'addressable'
|
|
|
|
require_relative 'repubmark/highlight'
|
|
require_relative 'repubmark/titled_ref'
|
|
|
|
require_relative 'repubmark/config'
|
|
require_relative 'repubmark/config/css_classes'
|
|
|
|
require_relative 'repubmark/references/author'
|
|
require_relative 'repubmark/references/item'
|
|
|
|
require_relative 'repubmark/elems/base'
|
|
|
|
# Top-level element
|
|
require_relative 'repubmark/elems/article'
|
|
|
|
# Always inside Article
|
|
require_relative 'repubmark/elems/annotation'
|
|
require_relative 'repubmark/elems/footnotes_category'
|
|
# Always inside Article, Chapter
|
|
require_relative 'repubmark/elems/chapter'
|
|
# Always inside Annotation, Blockquote, Chapter
|
|
require_relative 'repubmark/elems/canvas'
|
|
|
|
# Always inside Canvas
|
|
require_relative 'repubmark/elems/blockquote'
|
|
require_relative 'repubmark/elems/code_block'
|
|
require_relative 'repubmark/elems/figures'
|
|
require_relative 'repubmark/elems/iframe'
|
|
require_relative 'repubmark/elems/paragraph'
|
|
require_relative 'repubmark/elems/separator'
|
|
|
|
# Always inside Canvas, Figures
|
|
require_relative 'repubmark/elems/figure'
|
|
# Always inside Canvas, ListItem
|
|
require_relative 'repubmark/elems/list'
|
|
# Always inside List
|
|
require_relative 'repubmark/elems/list_item'
|
|
|
|
# Always inside Caption, Quote
|
|
require_relative 'repubmark/elems/joint'
|
|
# Always inside Blockquote, Figure, Footnote, ListItem, Paragraph
|
|
require_relative 'repubmark/elems/caption'
|
|
# Always inside Caption, Joint, Quote
|
|
require_relative 'repubmark/elems/quote'
|
|
|
|
# Always inside Joint
|
|
require_relative 'repubmark/elems/abbrev'
|
|
require_relative 'repubmark/elems/code_inline'
|
|
require_relative 'repubmark/elems/fraction'
|
|
require_relative 'repubmark/elems/note'
|
|
require_relative 'repubmark/elems/section'
|
|
require_relative 'repubmark/elems/special'
|
|
require_relative 'repubmark/elems/text'
|
|
require_relative 'repubmark/elems/link'
|
|
require_relative 'repubmark/elems/power'
|
|
|
|
# Always inside FootnotesCategory
|
|
require_relative 'repubmark/elems/footnote'
|
|
|
|
##
|
|
# A Markdown-inspired markup language that can be compiled into HTML and
|
|
# Gemtext.
|
|
#
|
|
module Repubmark
|
|
FORMATS = %i[chapters gemtext html summary_plain word_count].freeze
|
|
|
|
SLUG_RE = /\A[[:word:]]+(-[[:word:]]+)*\z/
|
|
DOI_RE = %r{\A10(\.\d+)+/\w+(\.\w+)*\z}
|
|
ISBN_RE = /\A[0-9]{13}\z/
|
|
NAME_PART_RE = /\A[[:word:]]+(-[[:word:]]+)*( [[:word:]]+(-[[:word:]]+)*)*\z/
|
|
|
|
UNICODE_SUPS = {
|
|
'0' => '⁰',
|
|
'1' => '¹',
|
|
'2' => '²',
|
|
'3' => '³',
|
|
'4' => '⁴',
|
|
'5' => '⁵',
|
|
'6' => '⁶',
|
|
'7' => '⁷',
|
|
'8' => '⁸',
|
|
'9' => '⁹',
|
|
'+' => '⁺',
|
|
'-' => '⁻',
|
|
'=' => '⁼',
|
|
'(' => '⁽',
|
|
')' => '⁾',
|
|
}.freeze
|
|
|
|
UNICODE_SUBS = {
|
|
'0' => '₀',
|
|
'1' => '₁',
|
|
'2' => '₂',
|
|
'3' => '₃',
|
|
'4' => '₄',
|
|
'5' => '₅',
|
|
'6' => '₆',
|
|
'7' => '₇',
|
|
'8' => '₈',
|
|
'9' => '₉',
|
|
'+' => '₊',
|
|
'-' => '₋',
|
|
'=' => '₌',
|
|
'(' => '₍',
|
|
')' => '₎',
|
|
}.freeze
|
|
|
|
def self.validate_slug!(slug)
|
|
slug = String(slug).freeze
|
|
raise 'Invalid slug' unless SLUG_RE.match? slug
|
|
|
|
slug
|
|
end
|
|
|
|
def self.validate_doi!(doi)
|
|
doi = String(doi).freeze
|
|
raise 'Invalid DOI' unless DOI_RE.match? doi
|
|
|
|
doi
|
|
end
|
|
|
|
def self.validate_isbn!(isbn)
|
|
isbn = String(isbn).freeze
|
|
raise 'Invalid ISBN' unless ISBN_RE.match? isbn
|
|
|
|
isbn
|
|
end
|
|
|
|
def self.validate_name_part!(name_part)
|
|
name_part = String(name_part).freeze
|
|
raise 'Invalid name part' unless NAME_PART_RE.match? name_part
|
|
|
|
name_part
|
|
end
|
|
|
|
def self.validate_text!(str)
|
|
str = String(str).freeze
|
|
raise 'Invalid text' if str.empty? || str != str.strip
|
|
|
|
str
|
|
end
|
|
|
|
def self.validate_absolute_url!(url)
|
|
url = Addressable::URI.parse(url).freeze
|
|
raise 'Invalid URL' unless url.absolute? &&
|
|
url.scheme &&
|
|
!url.scheme.strip.empty? &&
|
|
url.host &&
|
|
!url.host.strip.empty? &&
|
|
url.userinfo.nil?
|
|
|
|
url
|
|
end
|
|
|
|
def self.unicode_sup(val)
|
|
String(val).each_char.map { |chr| UNICODE_SUPS.fetch chr }.join.freeze
|
|
end
|
|
|
|
def self.unicode_sub(val)
|
|
String(val).each_char.map { |chr| UNICODE_SUBS.fetch chr }.join.freeze
|
|
end
|
|
end
|