├── .gitignore ├── lib ├── romantic_text │ ├── version.rb │ ├── html_node.rb │ ├── utils.rb │ └── element.rb └── romantic_text.rb ├── bin ├── setup └── console ├── test ├── test_helper.rb ├── utils_test.rb └── romantic_text_test.rb ├── Gemfile ├── Rakefile ├── .rubocop.yml ├── Gemfile.lock ├── LICENSE.txt ├── romantic_text.gemspec └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | -------------------------------------------------------------------------------- /lib/romantic_text/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module RomanticText 4 | VERSION = '0.2.0' 5 | end 6 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test/unit' 4 | require 'test/unit/rr' 5 | 6 | $LOAD_PATH.unshift File.expand_path('../lib', __dir__) 7 | require 'romantic_text' 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } 6 | 7 | # Specify your gem's dependencies in romantic_text.gemspec 8 | gemspec 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'rake/testtask' 5 | 6 | Rake::TestTask.new(:test) do |t| 7 | t.libs << 'test' 8 | t.libs << 'lib' 9 | t.test_files = FileList['test/**/*_test.rb'] 10 | end 11 | 12 | task default: :test 13 | -------------------------------------------------------------------------------- /lib/romantic_text/html_node.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'delegate' 4 | 5 | module RomanticText 6 | class HTMLNode < SimpleDelegator 7 | def initialize(text) 8 | super(text) 9 | @parent = nil 10 | end 11 | attr_accessor :parent 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/romantic_text.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'romantic_text/version' 4 | require 'romantic_text/utils' 5 | require 'romantic_text/html_node' 6 | require 'romantic_text/element' 7 | 8 | module RomanticText 9 | class << self 10 | def markup(&block) 11 | Element.new.render(&block) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/romantic_text/utils.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'cgi/escape' 4 | 5 | module RomanticText 6 | module Utils 7 | class << self 8 | def html_safe?(text) 9 | text.respond_to?(:html_safe?) ? text.html_safe? : false 10 | end 11 | 12 | def escape(text) 13 | html_safe?(text) ? text.to_s : CGI.escapeHTML(text.to_s) 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'bundler/setup' 5 | require 'romantic_text' 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | # (If you use this, don't forget to add pry to your Gemfile!) 11 | # require "pry" 12 | # Pry.start 13 | 14 | require 'irb' 15 | IRB.start(__FILE__) 16 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | Exclude: 3 | - tmp/**/* 4 | - vendor/**/* 5 | TargetRubyVersion: 2.5 6 | DisplayCopNames: true 7 | 8 | # no romantic :( 9 | Style/Alias: 10 | Enabled: false 11 | 12 | # no document 13 | Style/Documentation: 14 | Enabled: false 15 | 16 | # incompatible DSL 17 | Layout/EmptyLinesAroundArguments: 18 | Enabled: false 19 | 20 | # incompatible DSL 21 | Metrics/BlockLength: 22 | Enabled: false 23 | 24 | # incompatible DSL 25 | Metrics/ClassLength: 26 | Exclude: 27 | - test/**/* 28 | 29 | # my preference :) 30 | Metrics/LineLength: 31 | Max: 120 32 | 33 | # my preference :( 34 | Metrics/MethodLength: 35 | Max: 20 36 | 37 | # bye :) 38 | Naming/BinaryOperatorParameterName: 39 | Enabled: false 40 | Lint/MultipleCompare: 41 | Enabled: false 42 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | romantic_text (0.2.0) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | ast (2.4.0) 10 | jaro_winkler (1.5.3) 11 | parallel (1.17.0) 12 | parser (2.6.3.0) 13 | ast (~> 2.4.0) 14 | power_assert (1.1.4) 15 | rainbow (3.0.0) 16 | rake (10.5.0) 17 | rr (1.2.1) 18 | rubocop (0.72.0) 19 | jaro_winkler (~> 1.5.1) 20 | parallel (~> 1.10) 21 | parser (>= 2.6) 22 | rainbow (>= 2.2.2, < 4.0) 23 | ruby-progressbar (~> 1.7) 24 | unicode-display_width (>= 1.4.0, < 1.7) 25 | ruby-progressbar (1.10.1) 26 | test-unit (3.3.3) 27 | power_assert 28 | test-unit-rr (1.0.5) 29 | rr (>= 1.1.1) 30 | test-unit (>= 2.5.2) 31 | unicode-display_width (1.6.0) 32 | 33 | PLATFORMS 34 | ruby 35 | 36 | DEPENDENCIES 37 | bundler (~> 1.17) 38 | rake (~> 10.0) 39 | romantic_text! 40 | rubocop (= 0.72.0) 41 | test-unit (~> 3.3) 42 | test-unit-rr (~> 1.0) 43 | 44 | BUNDLED WITH 45 | 1.17.2 46 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 ru_shalm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /romantic_text.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path('lib', __dir__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'romantic_text/version' 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = 'romantic_text' 9 | spec.version = RomanticText::VERSION 10 | spec.authors = ['ru_shalm'] 11 | spec.email = ['ru_shalm@hazimu.com'] 12 | 13 | spec.summary = 'A romantic DSL for writing HTML.' 14 | spec.homepage = 'https://github.com/rutan/romantic_text' 15 | spec.license = 'MIT' 16 | 17 | spec.files = Dir.chdir(File.expand_path(__dir__)) do 18 | `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 19 | end 20 | spec.bindir = 'exe' 21 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 22 | spec.require_paths = ['lib'] 23 | 24 | spec.required_ruby_version = '>= 2.5.0' 25 | 26 | spec.add_development_dependency 'bundler', '~> 1.17' 27 | spec.add_development_dependency 'rake', '~> 10.0' 28 | spec.add_development_dependency 'rubocop', '0.72.0' 29 | spec.add_development_dependency 'test-unit', '~> 3.3' 30 | spec.add_development_dependency 'test-unit-rr', '~> 1.0' 31 | end 32 | -------------------------------------------------------------------------------- /test/utils_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test_helper' 4 | 5 | class UtilsTest < Test::Unit::TestCase 6 | sub_test_case '.html_safe?' do 7 | test 'normal string is false' do 8 | assert { RomanticText::Utils.html_safe?('text') == false } 9 | end 10 | 11 | test 'has html_safe? method' do 12 | str1 = Object.new 13 | mock(str1).html_safe? { true } 14 | assert { RomanticText::Utils.html_safe?(str1) == true } 15 | 16 | str2 = Object.new 17 | mock(str2).html_safe? { false } 18 | assert { RomanticText::Utils.html_safe?(str2) == false } 19 | end 20 | end 21 | 22 | sub_test_case '.escape' do 23 | test 'normal string' do 24 | assert { RomanticText::Utils.escape('text') == 'text' } 25 | assert { RomanticText::Utils.escape('' 101 | end 102 | end 103 | html.to_s # =>
| item |
Hello, World
Good HTML!
attributes
' \ 110 | 'attributes
' \ 111 | 'Hi!
'] do 119 | `a.title`[href: 'https://example.com?hoge=1'] << '' 120 | `.body`[] do 121 | dangerous_raw_html 'body
' 122 | end 123 | end 124 | end 125 | 126 | html2 = RomanticText.markup do 127 | h('.article', 'data-html': 'Hi!
') do 128 | h('a.title', href: 'https://example.com?hoge=1') << '' 129 | h('.body') do 130 | dangerous_raw_html 'body
' 131 | end 132 | end 133 | end 134 | 135 | result = 136 | 'body
Hello, Syntax