docwatch-bin 1.0.8
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/docwatch +136 -0
- data/lib/docwatch/connection.rb +24 -0
- data/lib/docwatch/logger.rb +11 -0
- data/lib/docwatch/renderer/html.rb +17 -0
- data/lib/docwatch/renderer/markdown.rb +27 -0
- data/lib/docwatch/renderer.rb +53 -0
- data/lib/docwatch/session.rb +54 -0
- data/lib/docwatch/version.rb +3 -0
- data/lib/docwatch/watcher.rb +16 -0
- data/lib/docwatch.rb +16 -0
- data/res/inject.js +10 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e525886a59746464f8ba5986e89bdcb343acbd1a96378bb56521f8e20bcf0288
|
4
|
+
data.tar.gz: a6829868d17db749392a11db8418519298e80bbfa386add54e2258bf72e59079
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e7e12d6b4188d3d29964d9c842bad38454c383aec54b2a55d38fe8ace8de68a21065abb7f1ade4cabe5ec88263d4790d1d3a8e63bccb40bd3bc4ee22f7095172
|
7
|
+
data.tar.gz: 270e381c2bbf7f2b28ecfbfccc407050a6aab5ed2c44342ba0f60a2c16d0227f00d33d8ba14be11e4820e27b60c085af83e039be2cd777fd7c54e9fb3bed641f
|
data/bin/docwatch
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/docwatch'
|
3
|
+
include Docwatch
|
4
|
+
|
5
|
+
DOCS = <<~EOF
|
6
|
+
#{'Usage:'.bold}
|
7
|
+
#{File.basename($0)} [options] [<file-path>]
|
8
|
+
|
9
|
+
#{'Options:'.bold}
|
10
|
+
-p, --port=VALUE Listen port [default: 8888]
|
11
|
+
-v, --verbose Verbose
|
12
|
+
-h, --help Help
|
13
|
+
-V, --version Version
|
14
|
+
|
15
|
+
#{'Renderers:'.bold}
|
16
|
+
markdown (.md)
|
17
|
+
html (.html)
|
18
|
+
|
19
|
+
If #{'--port'.bold} is #{'random'.bold} a random port will be chosen, otherwise
|
20
|
+
the specified one will be used. The default is 8888.
|
21
|
+
|
22
|
+
In #{'--verbose'.bold} mode, incoming HTTP requests and file change event
|
23
|
+
notifications will be printed to standard output.
|
24
|
+
EOF
|
25
|
+
|
26
|
+
class App
|
27
|
+
def initialize(opts)
|
28
|
+
@opts = opts
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.run(opts)
|
32
|
+
new(opts).run
|
33
|
+
end
|
34
|
+
|
35
|
+
def params
|
36
|
+
@params ||= OpenStruct.new({
|
37
|
+
verbose: @opts['--verbose'],
|
38
|
+
version: @opts['--version'],
|
39
|
+
help: @opts['--help'],
|
40
|
+
file_path: @opts['<file-path>']
|
41
|
+
})
|
42
|
+
end
|
43
|
+
|
44
|
+
def port
|
45
|
+
@port ||= if @opts['--port'] == 'random'
|
46
|
+
# TODO: check if this port is in use
|
47
|
+
10000 + Random.random_number(50000)
|
48
|
+
else
|
49
|
+
@opts['--port']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def url
|
54
|
+
'http://localhost:%s' % port
|
55
|
+
end
|
56
|
+
|
57
|
+
def port_valid
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def exit_usage
|
62
|
+
puts DOCS
|
63
|
+
exit 0
|
64
|
+
end
|
65
|
+
|
66
|
+
def exit_version
|
67
|
+
puts Docwatch::VERSION
|
68
|
+
exit 0
|
69
|
+
end
|
70
|
+
|
71
|
+
def exit_invalid_arguments
|
72
|
+
puts 'Invalid arguments'.red
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def exit_invalid_file
|
77
|
+
puts 'File does not exist: %s'.red % params.file_path
|
78
|
+
exit 2
|
79
|
+
end
|
80
|
+
|
81
|
+
def exit_unknown_renderer
|
82
|
+
puts 'No suitable renderer found for %s'.red % params.file_path
|
83
|
+
exit 3
|
84
|
+
end
|
85
|
+
|
86
|
+
def exit_invalid_port
|
87
|
+
puts 'Invalid port %s'.red % port
|
88
|
+
end
|
89
|
+
|
90
|
+
def run
|
91
|
+
exit_version if params.version
|
92
|
+
exit_usage if params.help
|
93
|
+
exit_invalid_arguments unless params.file_path
|
94
|
+
exit_invalid_file unless File.exist?(params.file_path)
|
95
|
+
exit_invalid_port unless port_valid
|
96
|
+
|
97
|
+
renderer = Renderer.by_filetype(params.file_path)
|
98
|
+
exit_unknown_renderer if renderer.nil?
|
99
|
+
|
100
|
+
server = TCPServer.new(port)
|
101
|
+
logger = Logger.new(params.verbose)
|
102
|
+
watcher = Watcher.new(params.file_path)
|
103
|
+
|
104
|
+
Thread.new do
|
105
|
+
while socket = server.accept
|
106
|
+
Thread.new do
|
107
|
+
Connection.handle(
|
108
|
+
renderer,
|
109
|
+
watcher,
|
110
|
+
logger,
|
111
|
+
Session.new(socket, logger)
|
112
|
+
)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
puts ('Started server on %s, renderer %s' % [url, renderer.class]).yellow
|
118
|
+
puts 'Press enter to open page in the default handler (xdg-open)'.green
|
119
|
+
|
120
|
+
begin
|
121
|
+
while STDIN.gets
|
122
|
+
system('xdg-open %s' % url)
|
123
|
+
end
|
124
|
+
rescue Interrupt => e
|
125
|
+
puts
|
126
|
+
puts 'Bye'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
begin
|
132
|
+
App.run(Docopt::docopt(DOCS, help: false))
|
133
|
+
rescue Docopt::Exit => e
|
134
|
+
puts 'Invalid arguments.'.red
|
135
|
+
exit 1
|
136
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Docwatch
|
2
|
+
class Connection
|
3
|
+
def initialize(renderer, watcher, logger, session)
|
4
|
+
@renderer = renderer
|
5
|
+
@watcher = watcher
|
6
|
+
@logger = logger
|
7
|
+
@session = session
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.handle(*opts)
|
11
|
+
new(*opts).handle
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle
|
15
|
+
case @session.path
|
16
|
+
when '/'
|
17
|
+
@session.respond_with_html @renderer.to_html
|
18
|
+
when '/wait'
|
19
|
+
@watcher.wait
|
20
|
+
@session.respond_with_text 'OK'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Docwatch
|
2
|
+
class MarkdownRenderer < Renderer
|
3
|
+
extension :md
|
4
|
+
|
5
|
+
def head
|
6
|
+
return <<~EOF
|
7
|
+
<title>#{file_path} - docwatch</title>
|
8
|
+
<style>
|
9
|
+
body {
|
10
|
+
font-family: Ubuntu;
|
11
|
+
font-size: 15px;
|
12
|
+
}
|
13
|
+
</style>
|
14
|
+
EOF
|
15
|
+
end
|
16
|
+
|
17
|
+
def body
|
18
|
+
Redcarpet::Markdown.new(
|
19
|
+
Redcarpet::Render::HTML,
|
20
|
+
fenced_code_blocks: true,
|
21
|
+
autolink: true,
|
22
|
+
tables: true,
|
23
|
+
footnotes: true,
|
24
|
+
).render(contents)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Docwatch
|
2
|
+
class Renderer
|
3
|
+
@@extensions = {}
|
4
|
+
|
5
|
+
# Set an extension (by symbol) as being supported by this class.
|
6
|
+
def self.extension(sym)
|
7
|
+
(@@extensions[sym] ||= []) << self
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.by_filetype(file_path)
|
11
|
+
extname = File.extname(file_path)[1..]
|
12
|
+
return if extname.length == 0
|
13
|
+
@@extensions[extname.to_sym].first.new(file_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(file_path)
|
17
|
+
@file_path = file_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def js
|
21
|
+
File.read(Docwatch.root + '/res/inject.js')
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_html
|
25
|
+
return <<~EOF
|
26
|
+
<!doctype html>
|
27
|
+
<html>
|
28
|
+
<head>
|
29
|
+
#{head}
|
30
|
+
</head>
|
31
|
+
<body>
|
32
|
+
#{body}
|
33
|
+
<script>
|
34
|
+
(function() {
|
35
|
+
#{js}
|
36
|
+
})()
|
37
|
+
</script>
|
38
|
+
</body>
|
39
|
+
</html>
|
40
|
+
EOF
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def file_path
|
46
|
+
@file_path
|
47
|
+
end
|
48
|
+
|
49
|
+
def contents
|
50
|
+
File.read(@file_path)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Docwatch
|
2
|
+
class Session
|
3
|
+
def initialize(socket, logger)
|
4
|
+
@socket = socket
|
5
|
+
@logger = logger
|
6
|
+
|
7
|
+
logger.log first_request_line
|
8
|
+
end
|
9
|
+
|
10
|
+
def close
|
11
|
+
@socket.close
|
12
|
+
end
|
13
|
+
|
14
|
+
def path
|
15
|
+
first_request_line.split(' ')[1]
|
16
|
+
end
|
17
|
+
|
18
|
+
def respond_with_text(str)
|
19
|
+
respond_with(str, 'text/plain')
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_with_html(str)
|
23
|
+
respond_with(str, 'text/html')
|
24
|
+
end
|
25
|
+
|
26
|
+
def respond_with(str, content_type)
|
27
|
+
println 'HTTP/1.1 200'
|
28
|
+
println 'Content-Type: %s; charset=utf8' % content_type
|
29
|
+
# println 'Connection: close'
|
30
|
+
println
|
31
|
+
println str
|
32
|
+
|
33
|
+
close
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def input_lines
|
39
|
+
@input_lines ||= @socket.recvmsg[0].lines rescue []
|
40
|
+
end
|
41
|
+
|
42
|
+
def first_request_line
|
43
|
+
input_lines.first.chomp
|
44
|
+
end
|
45
|
+
|
46
|
+
def print(msg)
|
47
|
+
@socket.print msg rescue nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def println(msg = '')
|
51
|
+
print msg + "\r\n"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/docwatch.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'require_all'
|
2
|
+
require 'colorize'
|
3
|
+
require 'docopt'
|
4
|
+
require 'redcarpet'
|
5
|
+
require 'nokogiri'
|
6
|
+
|
7
|
+
require 'socket'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
require_rel 'docwatch'
|
11
|
+
|
12
|
+
module Docwatch
|
13
|
+
def self.root
|
14
|
+
File.expand_path('../..', __FILE__)
|
15
|
+
end
|
16
|
+
end
|
data/res/inject.js
ADDED
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docwatch-bin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- crdx
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: require_all
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: colorize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.8.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: docopt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.6.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.6.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: redcarpet
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.5'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.10'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.10'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.17.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.17.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.8'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.8'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '12.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '12.3'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
executables:
|
128
|
+
- docwatch
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- bin/docwatch
|
133
|
+
- lib/docwatch.rb
|
134
|
+
- lib/docwatch/connection.rb
|
135
|
+
- lib/docwatch/logger.rb
|
136
|
+
- lib/docwatch/renderer.rb
|
137
|
+
- lib/docwatch/renderer/html.rb
|
138
|
+
- lib/docwatch/renderer/markdown.rb
|
139
|
+
- lib/docwatch/session.rb
|
140
|
+
- lib/docwatch/version.rb
|
141
|
+
- lib/docwatch/watcher.rb
|
142
|
+
- res/inject.js
|
143
|
+
homepage: https://github.com/crdx/docwatch
|
144
|
+
licenses:
|
145
|
+
- MIT
|
146
|
+
metadata: {}
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
requirements: []
|
162
|
+
rubygems_version: 3.0.6
|
163
|
+
signing_key:
|
164
|
+
specification_version: 4
|
165
|
+
summary: preview markdown documents in the browser with reload on change
|
166
|
+
test_files: []
|