txt2tags 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/txt2tags-rb +50 -0
- data/lib/txt2tags.rb +160 -0
- data/lib/txt2tags/html5.rb +23 -0
- data/lib/txt2tags/null.rb +29 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fecbe0959b04275d7354f5a2d617310e30a0f7e0
|
4
|
+
data.tar.gz: 0937dcbff35c0858a45706680113af8dafd96e5a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7961821fb564a19e8766a93c25849e65096c5eb7ec5c718afc88649ac4681e0c98d62a798cf6892ccaa9475ccfe1b891723c48d40b508c4ca4c7991c5e00c050
|
7
|
+
data.tar.gz: 3ef986140a6f4103ec696d08e00bf0e95c970a428708a058e8e2f8ea00ada9ce3a3c6893b0e2bec474b0cd9fc79d45a117b2a622adf0346c989f56e3296d5478
|
data/bin/txt2tags-rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'txt2tags'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
optparse = OptionParser.new do |opts|
|
9
|
+
opts.banner = 'Usage: txt2tags [options]'
|
10
|
+
|
11
|
+
options[:input] = nil
|
12
|
+
opts.on('-i', '--input FILENAME') do |file|
|
13
|
+
options[:input] = file
|
14
|
+
end
|
15
|
+
|
16
|
+
options[:output] = nil
|
17
|
+
opts.on('-o', '--output FILENAME') do |file|
|
18
|
+
options[:output] = file
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('-h', '--help', 'Display this screen') do
|
22
|
+
puts opts
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('-l', '--list', 'List available formats') do
|
27
|
+
puts Txt2Tags.new('').formats.join(' ')
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
options[:format] = nil
|
32
|
+
opts.on('-f', '--format FORMAT', 'Use this format for output') do |format|
|
33
|
+
txt2tags = Txt2Tags.new('')
|
34
|
+
abort('Unknown format') unless txt2tags.formats.include?(format)
|
35
|
+
require_relative "../lib/txt2tags/#{format}"
|
36
|
+
options[:format] = Object.const_get(format.capitalize)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
optparse.parse!
|
41
|
+
|
42
|
+
abort('Please, the format (-f/--format option)!') if options[:format].nil?
|
43
|
+
|
44
|
+
input = STDIN unless options[:input]
|
45
|
+
input = File.open(options[:input], 'r') if options[:input]
|
46
|
+
|
47
|
+
output = STDOUT unless options[:output]
|
48
|
+
output = File.open(options[:output], 'w') if options[:output]
|
49
|
+
|
50
|
+
output.write Txt2Tags.new(input).output(options[:format]).to_a.join
|
data/lib/txt2tags.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
# TXT2Tags - Converts t2t files to another formats
|
4
|
+
class Txt2Tags
|
5
|
+
attr_reader :BEAUTIFIERS, :TITLES, :BLOCKS
|
6
|
+
|
7
|
+
# The basic transformations
|
8
|
+
#
|
9
|
+
# One regexp by mark, the content must be in a group: (.*?)
|
10
|
+
BEAUTIFIERS = {
|
11
|
+
monospace: Regexp.new('``(.*?)``'),
|
12
|
+
bold: Regexp.new('\*\*(.*?)\*\*'),
|
13
|
+
italic: Regexp.new('//(.*?)//'),
|
14
|
+
underline: Regexp.new('__(.*?)__'),
|
15
|
+
strike: Regexp.new('--(.*?)--')
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
# Only one linners transformations
|
19
|
+
#
|
20
|
+
# One regexp by mark, the content must be in a group: (.*?)
|
21
|
+
TITLES = {
|
22
|
+
title1: Regexp.new('\A= (.*?) ='),
|
23
|
+
title2: Regexp.new('\A== (.*?) =='),
|
24
|
+
title3: Regexp.new('\A=== (.*?) ===')
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
# Define blocks os lines transformation
|
28
|
+
#
|
29
|
+
# - begin_re -> identify the begin of a blocks
|
30
|
+
# - end_re -> identify the end of a blocks
|
31
|
+
# - apply_inline -> can apply the BEAUTIFIERS and TITLES transformations?
|
32
|
+
# - strip -> can strip spaces from line begin?
|
33
|
+
# - ignore_match_line -> begin and end lines will be discarded?
|
34
|
+
BLOCKS = {
|
35
|
+
quote: {
|
36
|
+
begin_re: Regexp.new('\A\s+'),
|
37
|
+
end_re: Regexp.new('\A\Z'),
|
38
|
+
apply_inline: true,
|
39
|
+
strip: true,
|
40
|
+
ignore_match_line: false
|
41
|
+
},
|
42
|
+
verbatim: {
|
43
|
+
begin_re: Regexp.new('\A```\Z'),
|
44
|
+
end_re: Regexp.new('\A```\Z'),
|
45
|
+
apply_inline: false,
|
46
|
+
strip: false,
|
47
|
+
ignore_match_line: true
|
48
|
+
}
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
# Save input type
|
52
|
+
def initialize(input)
|
53
|
+
if input.respond_to?(:read)
|
54
|
+
@input = input
|
55
|
+
elsif input.respond_to?(:to_s)
|
56
|
+
@input = StringIO.new(input.to_s)
|
57
|
+
else
|
58
|
+
raise 'Cannot read this.'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Process conform 'format' and return a iterator with processed input
|
63
|
+
def output(format)
|
64
|
+
block = nil
|
65
|
+
ignore_line = false
|
66
|
+
|
67
|
+
Enumerator.new do |y|
|
68
|
+
# We can this multiples times
|
69
|
+
begin
|
70
|
+
@input.rewind
|
71
|
+
rescue Errno::ESPIPE
|
72
|
+
end
|
73
|
+
|
74
|
+
# Comments are discarded (lines beginnig with %)
|
75
|
+
@input.readlines.reject { |l| l.start_with?('%') }.each do |line|
|
76
|
+
# right space are discarded (line terminators, tabs and spaces)
|
77
|
+
line.rstrip!
|
78
|
+
|
79
|
+
# We are already inside a block?
|
80
|
+
if !block.nil?
|
81
|
+
# We find the end of a block?
|
82
|
+
if BLOCKS[block][:end_re].match line
|
83
|
+
# Send the end mark for this format
|
84
|
+
y.yield format::BLOCKS[block][:end]
|
85
|
+
|
86
|
+
# We can ignore the actual line?
|
87
|
+
if BLOCKS[block][:ignore_match_line]
|
88
|
+
block = nil
|
89
|
+
next
|
90
|
+
end
|
91
|
+
end
|
92
|
+
else
|
93
|
+
# Searching for a new block...
|
94
|
+
BLOCKS.keys.each do |m|
|
95
|
+
# No...
|
96
|
+
next unless BLOCKS[m][:begin_re].match line
|
97
|
+
|
98
|
+
# Yes!
|
99
|
+
block = m
|
100
|
+
# We can ignore the actual line?
|
101
|
+
ignore_line = BLOCKS[block][:ignore_match_line]
|
102
|
+
|
103
|
+
# Send the begin mark for this format
|
104
|
+
y.yield format::BLOCKS[block][:begin]
|
105
|
+
|
106
|
+
# We already figured out what to do, we do not have to keep looking
|
107
|
+
break
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Ignore this line? The others we'll find out.
|
112
|
+
if ignore_line
|
113
|
+
# The next line we still do not know if we ignore
|
114
|
+
ignore_line = false
|
115
|
+
next
|
116
|
+
end
|
117
|
+
|
118
|
+
# We can strip spaces from the begin of this line?
|
119
|
+
line.strip! if !block.nil? && BLOCKS[block][:strip]
|
120
|
+
|
121
|
+
# an apply the BEAUTIFIERS and TITLES transformations?
|
122
|
+
if block.nil? || (!block.nil? && BLOCKS[block][:apply_inline])
|
123
|
+
apply_marks!(format, line)
|
124
|
+
end
|
125
|
+
|
126
|
+
# More on line!
|
127
|
+
y.yield line
|
128
|
+
end
|
129
|
+
|
130
|
+
# There are a close block pending?
|
131
|
+
y.yield format::BLOCKS[block][:end] unless block.nil?
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Apply the basic conversions (no BLOCKS) to a line
|
136
|
+
def apply_marks!(conversion, line)
|
137
|
+
[:BEAUTIFIERS, :TITLES].each do |type|
|
138
|
+
type_array = Txt2Tags.const_get(type)
|
139
|
+
type_array.keys.each do |rule|
|
140
|
+
line.gsub!(type_array[rule], conversion.const_get(type)[rule])
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Discover available formats
|
146
|
+
def formats
|
147
|
+
format_list = []
|
148
|
+
Dir[File.join(__dir__, 'txt2tags', '*.rb')].each do |format|
|
149
|
+
format_list.push File.basename(format, '.rb')
|
150
|
+
end
|
151
|
+
|
152
|
+
format_list
|
153
|
+
end
|
154
|
+
|
155
|
+
# Require the format using a string as reference
|
156
|
+
def load_format(name)
|
157
|
+
require "txt2tags/#{name}"
|
158
|
+
Object.const_get(File.basename(name, '.rb').capitalize!)
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative '../txt2tags'
|
2
|
+
|
3
|
+
# HTML5 driver
|
4
|
+
class Html5
|
5
|
+
BEAUTIFIERS = {
|
6
|
+
monospace: '<pre>\1</pre>',
|
7
|
+
bold: '<strong>\1</strong>',
|
8
|
+
italic: '<em>\1</em>',
|
9
|
+
underline: '<span style="text-decoration: underline;">\1</span>',
|
10
|
+
strike: '<span style="text-decoration: line-through;">\1</span>'
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
TITLES = {
|
14
|
+
title1: '<h2>\1</h2>',
|
15
|
+
title2: '<h3>\1</h3>',
|
16
|
+
title3: '<h4>\1</h4>'
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
BLOCKS = {
|
20
|
+
quote: { begin: '<blockquote>', end: '</blockquote>' },
|
21
|
+
verbatim: { begin: '<pre>', end: '</pre>' }
|
22
|
+
}.freeze
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../txt2tags'
|
2
|
+
|
3
|
+
# Null format
|
4
|
+
#
|
5
|
+
# This format is a template and base for basic test_files.
|
6
|
+
# Copy and paste this file for a new format.
|
7
|
+
#
|
8
|
+
# This contain the replace part of a regexp
|
9
|
+
# "\1" is the group from the search part og regexps in main class
|
10
|
+
class Null
|
11
|
+
BEAUTIFIERS = {
|
12
|
+
monospace: 'm_\1_m',
|
13
|
+
bold: 'b_\1_b',
|
14
|
+
italic: 'i_\1_i',
|
15
|
+
underline: 'u_\1_u',
|
16
|
+
strike: 's_\1_s'
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
TITLES = {
|
20
|
+
title1: 'T1_\1_T1',
|
21
|
+
title2: 'T2_\1_T2',
|
22
|
+
title3: 'T3_\1_T3'
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
BLOCKS = {
|
26
|
+
quote: { begin: 'BEGIN_QUOTE', end: 'END_QUOTE' },
|
27
|
+
verbatim: { begin: 'BEGIN_VERBATIM', end: 'END_VERBATIM' }
|
28
|
+
}.freeze
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: txt2tags
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Paulo Henrique Rodrigues Pinheiro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: htmlentities
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Converts a text file with minimal markup to various formats
|
42
|
+
email: paulohrpinheiro@gmail.com
|
43
|
+
executables:
|
44
|
+
- txt2tags-rb
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- bin/txt2tags-rb
|
49
|
+
- lib/txt2tags.rb
|
50
|
+
- lib/txt2tags/html5.rb
|
51
|
+
- lib/txt2tags/null.rb
|
52
|
+
homepage: https://github.com/paulohrpinheiro/ruby-txt2tags
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.5.1
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Ruby txt2tags implementation.
|
76
|
+
test_files: []
|