synful 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +66 -0
- data/bin/synful +291 -0
- data/synful.gemspec +16 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e868e7d2521446e9bee4d813d8e15580b5ccfb58f71c0b7fad2459d212585a13
|
4
|
+
data.tar.gz: 1b2b05e76f6718625c94b77fa43e55c3d808a2c3c22ded2a83c9f4a24d8d99e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f7c6834c135e52ed6aa55f5ea9422a566957a3b046f02a94ff9a32391c34f927513801a866f8d2ec919fc7b721dddc7ef80d9e314b4977d0bb971ef54fed7287
|
7
|
+
data.tar.gz: 50d63b3c5b7af27adbc8b4e38765a8c60d183d1cc2c413e3e1edf5a4982184dad28f090e9518ddcc5b46c26641d1be042f11197d83eb0728d0f628207158f87b
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Steve Shreeve
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# synful
|
2
|
+
|
3
|
+
Ruby utility that shows syntax highlighted code in your browser
|
4
|
+
|
5
|
+
## Goals
|
6
|
+
|
7
|
+
1. Provide an easy way to view and print syntax highlighted source code
|
8
|
+
2. Enable file selection or rejection in an intuitive way
|
9
|
+
|
10
|
+
## Overview
|
11
|
+
|
12
|
+
Synful is a command line utility that will render syntax highlighted
|
13
|
+
source code in your browser. Simply indicate the file or directory
|
14
|
+
path names with optional file extensions to include or exclude. Synful
|
15
|
+
will generate a nice index and an entry for each file and it will
|
16
|
+
serve up the content and launch you web browser to view it. Once the
|
17
|
+
request has been served, the server will close down and exit. If you'd
|
18
|
+
like to keep the server running so that you can make changes and hit
|
19
|
+
refresh, there is an option to do that also. All syntax highlighting
|
20
|
+
is made possible by the amazing Rouge library.
|
21
|
+
|
22
|
+
## Examples
|
23
|
+
|
24
|
+
```
|
25
|
+
$ synful winr/bin/winr censive/lib/censive.rb
|
26
|
+
```
|
27
|
+
|
28
|
+
A more complicated example is:
|
29
|
+
|
30
|
+
```
|
31
|
+
synful -f -x spec,ru lib test /tmp/example.rb -- -test/boring-results.txt
|
32
|
+
```
|
33
|
+
|
34
|
+
This will keep `synful` in the foreground (the `-f` option) and will
|
35
|
+
exclude all files with the `.spec` or `.ru` extensions. It will also
|
36
|
+
include files from the `lib/` and `test/` directories as well as the
|
37
|
+
`/tmp/example.rb` file. Even though the `test/boring-results.txt` file
|
38
|
+
should be rendered, we have disabled it via the `-` (minus sign or dash)
|
39
|
+
in front of it's filename. Note that to use this type of negation, we
|
40
|
+
need to precede it with a "double-dash" `--` to tell `synful` that we
|
41
|
+
are done with the normal command options.
|
42
|
+
|
43
|
+
## Install
|
44
|
+
|
45
|
+
Install via `rubygems` with:
|
46
|
+
|
47
|
+
```
|
48
|
+
gem install synful
|
49
|
+
```
|
50
|
+
|
51
|
+
## Options
|
52
|
+
|
53
|
+
```
|
54
|
+
$ synful -h
|
55
|
+
|
56
|
+
usage: synful [options] <paths ...> [--] <-paths_to_skip ...>
|
57
|
+
-b, --bypass Bypass (skip over) top comments (begin with "#") in files
|
58
|
+
-f, --foreground Stay in the foreground, allows more requests
|
59
|
+
-h, --help Show help and command usage
|
60
|
+
-i, --include <exts> Comma list of extensions to include (incompatible with -x)
|
61
|
+
-x, --exclude <exts> Comma list of extensions to exclude (incompatible with -i)
|
62
|
+
```
|
63
|
+
|
64
|
+
## License
|
65
|
+
|
66
|
+
This software is licensed under terms of the MIT License.
|
data/bin/synful
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# ============================================================================
|
4
|
+
# synful - Ruby utility that shows syntax highlighted code in your browser
|
5
|
+
#
|
6
|
+
# Author: Steve Shreeve (steve.shreeve@gmail.com)
|
7
|
+
# Date: Feb 18, 2023
|
8
|
+
#
|
9
|
+
# Thanks to Julie Evans for creating the amazing rouge library!
|
10
|
+
# ============================================================================
|
11
|
+
# GOALS:
|
12
|
+
# 1. Provide an easy way to view and print syntax highlighted source code
|
13
|
+
# 2. Enable file selection or rejection in an intuitive way
|
14
|
+
# ============================================================================
|
15
|
+
# TODO:
|
16
|
+
# 1. Ensure there is a section for a file, even when it has a bad encoding
|
17
|
+
# ============================================================================
|
18
|
+
|
19
|
+
require "optparse"
|
20
|
+
|
21
|
+
OptionParser.new.instance_eval do
|
22
|
+
@banner = "usage: #{program_name} [options] <paths ...> [--] <-paths_to_skip ...>"
|
23
|
+
|
24
|
+
on '-b' , '--bypass' , 'Bypass (skip over) top comments (begin with "#") in files'
|
25
|
+
on '-f' , '--foreground', 'Stay in the foreground, allows more requests'
|
26
|
+
on '-h' , '--help' , 'Show help and command usage' do Kernel.abort to_s; end
|
27
|
+
on '-i <exts>' , '--include' , 'Comma list of extensions to include (incompatible with -x)', Array
|
28
|
+
on '-x <exts>' , '--exclude' , 'Comma list of extensions to exclude (incompatible with -i)', Array
|
29
|
+
|
30
|
+
self
|
31
|
+
end.parse!(into: opts={}) rescue abort($!.message)
|
32
|
+
|
33
|
+
skip, want = ARGV.map(&:dup).partition {|item| item.delete_prefix!("-") }; ARGV.clear
|
34
|
+
want << "." if want.empty?
|
35
|
+
skip = skip.empty? ? nil : Set.new(skip)
|
36
|
+
|
37
|
+
nuke = opts[:bypass ]
|
38
|
+
fore = opts[:foreground]
|
39
|
+
keep = opts[:include ] # will become a Set or nil
|
40
|
+
deny = opts[:exclude ] # will become a Set or nil
|
41
|
+
|
42
|
+
if keep && deny
|
43
|
+
abort "#{File.basename $0}: include and exclude cannot be used together"
|
44
|
+
elsif keep
|
45
|
+
keep = Set.new(keep.map(&:downcase))
|
46
|
+
deny = nil
|
47
|
+
else
|
48
|
+
keep = nil
|
49
|
+
deny = Set.new(((deny || []) + %w[
|
50
|
+
ico jpg jpeg otf png pdf gif css svg eot ttf woff woff2 o a dylib
|
51
|
+
gem gz zip sqlite3 DS_Store
|
52
|
+
]).map(&:downcase))
|
53
|
+
end
|
54
|
+
|
55
|
+
$skip, $want, $fore, $keep, $deny, $nuke = [skip, want, fore, keep, deny, nuke]
|
56
|
+
|
57
|
+
# ============================================================================
|
58
|
+
|
59
|
+
require "rouge"
|
60
|
+
|
61
|
+
$show = Rouge::Formatters::HTMLLegacy.new(line_numbers: true)
|
62
|
+
|
63
|
+
Rouge::Lexers::Ruby.filenames "*.rbx", "*.ru", "*.imba"
|
64
|
+
Rouge::Lexers::Sass.filenames "*.styl"
|
65
|
+
Rouge::Lexers::ERB.filenames "*.eco"
|
66
|
+
|
67
|
+
# ============================================================================
|
68
|
+
|
69
|
+
require "find"
|
70
|
+
require "set"
|
71
|
+
require "sinatra"
|
72
|
+
|
73
|
+
$stderr = $stderr.dup.reopen File.new("/dev/null", "w") # turn off logger
|
74
|
+
|
75
|
+
set :server, "webrick"
|
76
|
+
|
77
|
+
get "*" do
|
78
|
+
skip, want, fore, keep, deny = [$skip, $want, $fore, $keep, $deny]
|
79
|
+
|
80
|
+
init = Time.now.to_f
|
81
|
+
|
82
|
+
@list = want.inject([]) do |list, path|
|
83
|
+
if !File.readable?(path)
|
84
|
+
warn "unreadable '#{path}'"
|
85
|
+
elsif File.directory?(path)
|
86
|
+
Find.find(path) do |path|
|
87
|
+
path.delete_prefix!("./") #!# TODO: is this working as expected?
|
88
|
+
if !File.readable?(path) || path == "."
|
89
|
+
next
|
90
|
+
elsif File.directory?(path)
|
91
|
+
Find.prune if File.basename(path).start_with?(".") or skip&.include?(path)
|
92
|
+
elsif File.file?(path)
|
93
|
+
next if skip&.include?(path)
|
94
|
+
type = path[/(?<=\.)[^.\/]+\z/].to_s.downcase
|
95
|
+
list << path if keep ? keep.include?(type) : !deny.include?(type)
|
96
|
+
else
|
97
|
+
warn "unknown '#{path}'"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
elsif File.file?(path)
|
101
|
+
list << path # requested explicitly
|
102
|
+
end
|
103
|
+
list
|
104
|
+
end.sort.uniq
|
105
|
+
|
106
|
+
# show filenames
|
107
|
+
time = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
108
|
+
STDERR.puts "\n[#{time}]\n\n", @list.map {|item| " • #{item}"}
|
109
|
+
|
110
|
+
# generate content and generation time
|
111
|
+
$err = false
|
112
|
+
body = erb :page
|
113
|
+
wait = Time.now.to_f - init
|
114
|
+
STDERR.puts "\nTime elapsed: %.2f" % wait
|
115
|
+
|
116
|
+
# send response
|
117
|
+
$fore or Thread.new { sleep wait; exit! } # how can we know when the request is "done?"
|
118
|
+
headers "Connection" => "close"
|
119
|
+
body
|
120
|
+
end
|
121
|
+
|
122
|
+
Thread.new do
|
123
|
+
sleep 0.1 until settings.running?
|
124
|
+
fork or exec "open 'http://localhost:#{settings.port}/'"
|
125
|
+
end
|
126
|
+
|
127
|
+
__END__
|
128
|
+
|
129
|
+
@@ layout
|
130
|
+
<!DOCTYPE html>
|
131
|
+
<html lang="en">
|
132
|
+
<head>
|
133
|
+
<meta charset="utf-8">
|
134
|
+
<title>Synful</title>
|
135
|
+
<link rel="icon" href="data:,">
|
136
|
+
<style type="text/css">
|
137
|
+
html body { font-size: 14px; }
|
138
|
+
body { font-family: Verdana; padding: 5px; }
|
139
|
+
a { text-decoration: none; }
|
140
|
+
h4 a { color: #fff; font-weight: bold; margin: 0; border: none; }
|
141
|
+
h4 a:hover { background: #333; }
|
142
|
+
h4 { background: black; color: white; padding: 5px; margin: 0; border: none; }
|
143
|
+
li a { color: #000; }
|
144
|
+
li a:hover { text-decoration: underline; color: #666; }
|
145
|
+
pre { margin: 0; font-family: Consolas, Menlo, monospace; }
|
146
|
+
|
147
|
+
.rouge-table { padding: 0; border-collapse: collapse; }
|
148
|
+
.rouge-table td { padding: 0; vertical-align: top; }
|
149
|
+
.rouge-table td:first-child { text-align: right; }
|
150
|
+
.rouge-table pre { padding: 0.7em; }
|
151
|
+
|
152
|
+
.codehilite { margin: 0; background: #fff; white-space: pre; overflow-x: hidden; }
|
153
|
+
.codehilite .lineno { margin: 0; color: #ddd; background: #f4f4f4; }
|
154
|
+
.codehilite .hll { background-color: #ffffcc }
|
155
|
+
.codehilite .c { color: #888888 } /* Comment */
|
156
|
+
.codehilite .k { color: #008800; font-weight: bold } /* Keyword */
|
157
|
+
.codehilite .o { color: #333333 } /* Operator */
|
158
|
+
.codehilite .cm { color: #888888 } /* Comment.Multiline */
|
159
|
+
.codehilite .cp { color: #557799 } /* Comment.Preproc */
|
160
|
+
.codehilite .c1 { color: #888888 } /* Comment.Single */
|
161
|
+
.codehilite .cs { color: #cc0000; font-weight: bold } /* Comment.Special */
|
162
|
+
.codehilite .gd { color: #a00000 } /* Generic.Deleted */
|
163
|
+
.codehilite .ge { font-style: italic } /* Generic.Emph */
|
164
|
+
.codehilite .gr { color: #ff0000 } /* Generic.Error */
|
165
|
+
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
166
|
+
.codehilite .gi { color: #00a000 } /* Generic.Inserted */
|
167
|
+
.codehilite .go { color: #888888 } /* Generic.Output */
|
168
|
+
.codehilite .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
169
|
+
.codehilite .gs { font-weight: bold } /* Generic.Strong */
|
170
|
+
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
171
|
+
.codehilite .gt { color: #0044dd } /* Generic.Traceback */
|
172
|
+
.codehilite .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
|
173
|
+
.codehilite .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
|
174
|
+
.codehilite .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
|
175
|
+
.codehilite .kp { color: #003388; font-weight: bold } /* Keyword.Pseudo */
|
176
|
+
.codehilite .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
|
177
|
+
.codehilite .kt { color: #333399; font-weight: bold } /* Keyword.Type */
|
178
|
+
.codehilite .m { color: #6600ee; font-weight: bold } /* Literal.Number */
|
179
|
+
.codehilite .n { color: #933 } /* name? */
|
180
|
+
.codehilite .s { } /* Literal.String */
|
181
|
+
.codehilite .na { color: #0000cc } /* Name.Attribute */
|
182
|
+
.codehilite .nb { color: #007020 } /* Name.Builtin */
|
183
|
+
.codehilite .nc { color: #bb0066; font-weight: bold } /* Name.Class */
|
184
|
+
.codehilite .no { color: #003366; font-weight: bold } /* Name.Constant */
|
185
|
+
.codehilite .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
186
|
+
.codehilite .ni { color: #880000; font-weight: bold } /* Name.Entity */
|
187
|
+
.codehilite .ne { color: #ff0000; font-weight: bold } /* Name.Exception */
|
188
|
+
.codehilite .nf { color: #0066bb; font-weight: bold } /* Name.Function */
|
189
|
+
.codehilite .nl { color: #997700; font-weight: bold } /* Name.Label */
|
190
|
+
.codehilite .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
191
|
+
.codehilite .nt { color: #007700 } /* Name.Tag */
|
192
|
+
.codehilite .nv { color: #996633 } /* Name.Variable */
|
193
|
+
.codehilite .ow { color: #000000; font-weight: bold } /* Operator.Word */
|
194
|
+
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
|
195
|
+
.codehilite .mf { color: #6600ee; font-weight: bold } /* Literal.Number.Float */
|
196
|
+
.codehilite .mh { color: #005588; font-weight: bold } /* Literal.Number.Hex */
|
197
|
+
.codehilite .mi { color: #0000dd; font-weight: bold } /* Literal.Number.Integer */
|
198
|
+
.codehilite .mo { color: #4400ee; font-weight: bold } /* Literal.Number.Oct */
|
199
|
+
.codehilite .sb { } /* Literal.String.Backtick */
|
200
|
+
.codehilite .sc { color: #0044dd } /* Literal.String.Char */
|
201
|
+
.codehilite .sd { color: #dd4422 } /* Literal.String.Doc */
|
202
|
+
.codehilite .s2 { } /* Literal.String.Double */
|
203
|
+
.codehilite .se { color: #666666; font-weight: bold; } /* Literal.String.Escape */
|
204
|
+
.codehilite .sh { } /* Literal.String.Heredoc */
|
205
|
+
.codehilite .si { } /* Literal.String.Interpol */
|
206
|
+
.codehilite .sx { color: #dd2200; } /* Literal.String.Other */
|
207
|
+
.codehilite .sr { color: #000000; } /* Literal.String.Regex */
|
208
|
+
.codehilite .s1 { } /* Literal.String.Single */
|
209
|
+
.codehilite .ss { color: #aa6600 } /* Literal.String.Symbol */
|
210
|
+
.codehilite .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
211
|
+
.codehilite .vc { color: #336699 } /* Name.Variable.Class */
|
212
|
+
.codehilite .vg { color: #dd7700; font-weight: bold } /* Name.Variable.Global */
|
213
|
+
.codehilite .vi { color: #3333bb } /* Name.Variable.Instance */
|
214
|
+
.codehilite .il { color: #0000dd; font-weight: bold } /* Literal.Number.Integer.Long */
|
215
|
+
</style>
|
216
|
+
</head>
|
217
|
+
<body>
|
218
|
+
<div class="top">
|
219
|
+
|
220
|
+
<%= yield %></div>
|
221
|
+
</body>
|
222
|
+
</html>
|
223
|
+
|
224
|
+
@@ page
|
225
|
+
<%= erb :toc if (count = @list.size) > 1 %><%
|
226
|
+
@list.each_with_index do |file, i|
|
227
|
+
@file = file
|
228
|
+
@prev = @list[(i - 1) % count]
|
229
|
+
@next = @list[(i + 1) % count]
|
230
|
+
@curr = count > 1 ? "#{i + 1}) " : "" %>
|
231
|
+
<%= erb :file %><% end %>
|
232
|
+
|
233
|
+
@@ toc
|
234
|
+
<h4><a name="top">Index</a></h4>
|
235
|
+
|
236
|
+
<ul><% @list.each do |file| %>
|
237
|
+
<li><a href="#<%= file %>"><%= file %></a></li><% end %>
|
238
|
+
</ul>
|
239
|
+
|
240
|
+
@@ file
|
241
|
+
<%
|
242
|
+
begin
|
243
|
+
data = File.read(@file)
|
244
|
+
data.gsub!(/\t/, " ") # replace tab with 2 spaces (make configurable?)
|
245
|
+
data.sub!(/\A.*?(?=^[^#\s])/m, "") if $nuke # nuke top comments (license, etc.)
|
246
|
+
type = Rouge::Lexer.guess(filename:@file, source:data)
|
247
|
+
rescue ArgumentError => e
|
248
|
+
STDERR.puts "\n" unless $err; $err = true
|
249
|
+
STDERR.puts "Invalid byte encoding in '#{@file}'"
|
250
|
+
return "Invalid... something here?"
|
251
|
+
rescue => e
|
252
|
+
if (data =~ /\A[^\n]+ruby/)
|
253
|
+
type = Rouge::Lexer.guess(filename:"foo.rb")
|
254
|
+
else
|
255
|
+
return "<p>Unable to process <b>#{@file.inspect}</b> (#{$!})\n\n"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
if type.tag == "plaintext" || (type.tag == "html" && @file !~ /\.html?$/i)
|
259
|
+
mime = `file -b --mime-type "#{@file}"`.chomp
|
260
|
+
type = (mime =~ %r!\b(?:octet|image|font)\b!) ? nil : Rouge::Lexer.guess(mimetype:mime)
|
261
|
+
end
|
262
|
+
%>
|
263
|
+
|
264
|
+
<h4>
|
265
|
+
<a name="<%= @file %>"><%= @curr %><%= @file %>
|
266
|
+
(<%= data.count("\n") + 1 %> lines)
|
267
|
+
<%= "[" + type.tag + "]" if type %>
|
268
|
+
<%= File.mtime(@file).strftime("on %Y-%m-%d at %-I:%M %P") %>
|
269
|
+
</a>
|
270
|
+
<span style="float: right">
|
271
|
+
<a class="jump" href="#<%= @prev %>"> ↓ </a>
|
272
|
+
<a class="jump" href="#<%= @next %>"> ↑ </a>
|
273
|
+
<a class="jump" href="#top"> ⥣ </a>
|
274
|
+
</span>
|
275
|
+
</h4>
|
276
|
+
|
277
|
+
<%=
|
278
|
+
if type
|
279
|
+
begin
|
280
|
+
html = $show.format(type.lex(data))
|
281
|
+
html[html.rindex("\n"), 1] = ""
|
282
|
+
html
|
283
|
+
rescue
|
284
|
+
type = Rouge::Lexer.guess(filename:"foo.txt")
|
285
|
+
"<p>Unable to parse, showing plaintext instead...</p>" +
|
286
|
+
$show.format(type.lex(data))
|
287
|
+
end
|
288
|
+
else
|
289
|
+
"<p>(binary file)</p>"
|
290
|
+
end
|
291
|
+
%>
|
data/synful.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "synful"
|
5
|
+
s.version = "1.0.0"
|
6
|
+
s.author = "Steve Shreeve"
|
7
|
+
s.email = "steve.shreeve@gmail.com"
|
8
|
+
s.summary =
|
9
|
+
s.description = "Ruby utility that shows syntax highlighted code in your browser"
|
10
|
+
s.homepage = "https://github.com/shreeve/synful"
|
11
|
+
s.license = "MIT"
|
12
|
+
s.files = `git ls-files`.split("\n") - %w[.gitignore]
|
13
|
+
s.executables = `cd bin && git ls-files .`.split("\n")
|
14
|
+
s.add_runtime_dependency "rouge", "~> 4.0"
|
15
|
+
s.add_runtime_dependency "sinatra", "~> 3.0"
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: synful
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steve Shreeve
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-02-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rouge
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
description: Ruby utility that shows syntax highlighted code in your browser
|
42
|
+
email: steve.shreeve@gmail.com
|
43
|
+
executables:
|
44
|
+
- synful
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Gemfile
|
49
|
+
- LICENSE
|
50
|
+
- README.md
|
51
|
+
- bin/synful
|
52
|
+
- synful.gemspec
|
53
|
+
homepage: https://github.com/shreeve/synful
|
54
|
+
licenses:
|
55
|
+
- MIT
|
56
|
+
metadata: {}
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubygems_version: 3.4.6
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Ruby utility that shows syntax highlighted code in your browser
|
76
|
+
test_files: []
|