resulang 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/.gitignore +14 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +145 -0
- data/Rakefile +2 -0
- data/bin/resulang +6 -0
- data/examples/my_resume/assets/css/style.css +11 -0
- data/examples/my_resume/data/resume.rb +25 -0
- data/examples/my_resume/data/sections/background.rb +4 -0
- data/examples/my_resume/data/sections/hobbies.rb +3 -0
- data/examples/my_resume/data/sections/personal.rb +5 -0
- data/examples/my_resume/data/sections/skills.rb +3 -0
- data/examples/my_resume/resume.html +38 -0
- data/examples/my_resume/server.ru +2 -0
- data/examples/my_resume/templates/_background.html.erb +1 -0
- data/examples/my_resume/templates/_hobbies.html.erb +6 -0
- data/examples/my_resume/templates/_personal.html.erb +4 -0
- data/examples/my_resume/templates/_skills.html.erb +1 -0
- data/examples/my_resume/templates/resume.html.erb +21 -0
- data/lib/resulang/app.rb +75 -0
- data/lib/resulang/dsl.rb +31 -0
- data/lib/resulang/exec.rb +58 -0
- data/lib/resulang/fields.rb +80 -0
- data/lib/resulang/rendering.rb +21 -0
- data/lib/resulang/resume.rb +8 -0
- data/lib/resulang/section.rb +20 -0
- data/lib/resulang/server.rb +52 -0
- data/lib/resulang/template.rb +24 -0
- data/lib/resulang/version.rb +3 -0
- data/lib/resulang.rb +11 -0
- data/resulang.gemspec +28 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 43e5309b3fb143c9d6dbc47417efabb904a54ce9
|
4
|
+
data.tar.gz: a738b02d97b10e1e74dc94f38139e2f059122335
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 53aacfcf4ae1f75cf20aae825d0bce7a7318ab441f8d62d1554a88e05d05800a5cfab938793aa3397c68837504c9f8cd18c460c31ae765da2368b9300496b8bc
|
7
|
+
data.tar.gz: a6421c95e18c72ce1823425c706c82cf3ac20962f370facfc8cbf6fbae94d7a5469ed990f04dbd5b2fcb3289441a8c77bbc538455f080eac96dbce35c4a0a51a
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
resulang
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.2.1
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Peter Brindisi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# Resulang
|
2
|
+
|
3
|
+
Resulang is a simple DSL to help create html resumes. It can also be used to
|
4
|
+
create other kinds of documents with structured data. It works by separating
|
5
|
+
the data from the html template, which means the data could theoretically be
|
6
|
+
used to generate other kinds of output in the future, not just html.
|
7
|
+
|
8
|
+
## TODO: write tests and publish gem
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
$ gem install resulang
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
Once resulang is installed, create a new resulang app with:
|
17
|
+
```sh
|
18
|
+
resulang new my_resume
|
19
|
+
```
|
20
|
+
|
21
|
+
This will generate the basic structure of a resulang app as well as a few key files:
|
22
|
+
|
23
|
+
* `my_resume/data/resume.rb`
|
24
|
+
|
25
|
+
This is where you define your resume.
|
26
|
+
|
27
|
+
* `my_resume/templates/resume.html.erb`
|
28
|
+
|
29
|
+
This is where you write your resume html which has access to the data in my_resume/data/resume.rb
|
30
|
+
|
31
|
+
|
32
|
+
A resume is broken into named sections. For example:
|
33
|
+
```ruby
|
34
|
+
personal do
|
35
|
+
name 'Peter Brindisi'
|
36
|
+
phone '555-555-5555'
|
37
|
+
email 'superduperprivate@example.com'
|
38
|
+
github 'https://github.com/npj'
|
39
|
+
end
|
40
|
+
|
41
|
+
background do
|
42
|
+
description <<-DESCRIPTION
|
43
|
+
I am a guy that does things. Things are awesome and they are also cool.
|
44
|
+
DESCRIPTION
|
45
|
+
end
|
46
|
+
|
47
|
+
skills do
|
48
|
+
things %{foo bar baz qux}
|
49
|
+
end
|
50
|
+
|
51
|
+
hobbies do
|
52
|
+
info do
|
53
|
+
point 'Reading about Haskell'
|
54
|
+
point 'Evangelizing monads'
|
55
|
+
point 'Making beer'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
A template for the above data might look like this:
|
61
|
+
|
62
|
+
```html
|
63
|
+
<html>
|
64
|
+
<head>
|
65
|
+
<title><%= sections[:personal].name %></title>
|
66
|
+
<link rel="stylesheet" href="assets/css/style.css" />
|
67
|
+
</head>
|
68
|
+
<body>
|
69
|
+
<div class="section">
|
70
|
+
<%= render_section(:personal) %>
|
71
|
+
</div>
|
72
|
+
<div class="section">
|
73
|
+
<%= render_section(:background) %>
|
74
|
+
</div>
|
75
|
+
<div class="section">
|
76
|
+
<%= render_section(:skills) %>
|
77
|
+
</div>
|
78
|
+
<div class="section">
|
79
|
+
<%= render_section(:hobbies) %>
|
80
|
+
</div>
|
81
|
+
</body>
|
82
|
+
</html>
|
83
|
+
```
|
84
|
+
|
85
|
+
`render_section(:section_name)` looks for a template partial named
|
86
|
+
`my_resume/templates/_section_name.html.erb`. A partial has direct access to
|
87
|
+
the data within the data section. For example, the partial for the "personal" and "hobbies" sections might look like:
|
88
|
+
|
89
|
+
```html
|
90
|
+
<!-- my_resume/templates/_personal.html.erb -->
|
91
|
+
<div>Name: <%= name %></div>
|
92
|
+
<div>Phone: <%= phone %></div>
|
93
|
+
<div>Email: <%= email %></div>
|
94
|
+
<div><a href="<%= github %>" target="_blank"><%= github %></a></div>
|
95
|
+
```
|
96
|
+
|
97
|
+
```html
|
98
|
+
<!-- my_resume/templates/_hobbies.html.erb -->
|
99
|
+
<ul>
|
100
|
+
<% info.points.each do |point| %>
|
101
|
+
<li><%= point %></li>
|
102
|
+
<% end %>
|
103
|
+
</ul>
|
104
|
+
```
|
105
|
+
|
106
|
+
The data in `resume.rb` needs to be defined, which is what the
|
107
|
+
`my_resume/data/sections` directory is for. Each section is a class that
|
108
|
+
inherits from `Resulang::Section`. A section class declares the fields a
|
109
|
+
section can have as well as their types. The `Personal` and `Hobbies` sections
|
110
|
+
would look like this:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
# my_resume/data/sections/personal.rb
|
114
|
+
class Personal < Resulang::Section
|
115
|
+
string :name, :phone
|
116
|
+
email :email
|
117
|
+
link :github
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
# my_resume/data/sections/hobbies.rb
|
123
|
+
class Hobbies < Resulang::Section
|
124
|
+
pointlist :info
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
To easily view changes to the resume as you make them, you can run a local server with:
|
129
|
+
```sh
|
130
|
+
resulang server
|
131
|
+
```
|
132
|
+
|
133
|
+
However, if you make any changes to the classes in `my_resume/data/sections` you must restart the server.
|
134
|
+
|
135
|
+
You can put assets like images and stylesheets in directories off `my_resume`, like `css` and `images` or `assets/css` and `assets/images'. These can be referenced in `resume.html.erb`.
|
136
|
+
|
137
|
+
To generate a static html page, run:
|
138
|
+
```sh
|
139
|
+
resulang make
|
140
|
+
```
|
141
|
+
|
142
|
+
This will output `./resume.html`
|
143
|
+
|
144
|
+
Please see the `exmaples` directory of this project for a working example.
|
145
|
+
|
data/Rakefile
ADDED
data/bin/resulang
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
personal do
|
2
|
+
name 'Peter Brindisi'
|
3
|
+
phone '555-555-5555'
|
4
|
+
email 'superduperprivate@example.com'
|
5
|
+
github 'https://github.com/npj'
|
6
|
+
end
|
7
|
+
|
8
|
+
background do
|
9
|
+
description <<-DESCRIPTION
|
10
|
+
I am a guy that does things. Things are awesome and they are also cool.
|
11
|
+
DESCRIPTION
|
12
|
+
end
|
13
|
+
|
14
|
+
skills do
|
15
|
+
things %{foo bar baz qux}
|
16
|
+
end
|
17
|
+
|
18
|
+
hobbies do
|
19
|
+
info do
|
20
|
+
point 'Reading about Haskell'
|
21
|
+
point 'Evangelizing monads'
|
22
|
+
point 'Making beer'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Peter Brindisi</title>
|
4
|
+
<link rel="stylesheet" href="assets/css/style.css" />
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<div class="section">
|
8
|
+
<div>Name: Peter Brindisi</div>
|
9
|
+
<div>Phone: 555-555-5555</div>
|
10
|
+
<div>Email: superduperprivate@example.com</div>
|
11
|
+
<div><a href="https://github.com/npj" target="_blank">https://github.com/npj</a></div>
|
12
|
+
|
13
|
+
</div>
|
14
|
+
<div class="section">
|
15
|
+
<div> I am a guy that does things. Things are awesome and they are also cool.
|
16
|
+
</div>
|
17
|
+
|
18
|
+
</div>
|
19
|
+
<div class="section">
|
20
|
+
<div>foo bar baz qux</div>
|
21
|
+
|
22
|
+
</div>
|
23
|
+
<div class="section">
|
24
|
+
<ul>
|
25
|
+
|
26
|
+
<li>Reading about Haskell</li>
|
27
|
+
|
28
|
+
<li>Evangelizing monads</li>
|
29
|
+
|
30
|
+
<li>Making beer</li>
|
31
|
+
|
32
|
+
</ul>
|
33
|
+
|
34
|
+
|
35
|
+
</div>
|
36
|
+
</body>
|
37
|
+
</html>
|
38
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
<div><%= description %></div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<div><%= things.join(' / ') %></div>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title><%= sections[:personal].name %></title>
|
4
|
+
<link rel="stylesheet" href="assets/css/style.css" />
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<div class="section">
|
8
|
+
<%= render_section(:personal) %>
|
9
|
+
</div>
|
10
|
+
<div class="section">
|
11
|
+
<%= render_section(:background) %>
|
12
|
+
</div>
|
13
|
+
<div class="section">
|
14
|
+
<%= render_section(:skills) %>
|
15
|
+
</div>
|
16
|
+
<div class="section">
|
17
|
+
<%= render_section(:hobbies) %>
|
18
|
+
</div>
|
19
|
+
</body>
|
20
|
+
</html>
|
21
|
+
|
data/lib/resulang/app.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Resulang
|
2
|
+
class App
|
3
|
+
attr_reader :path, :resume
|
4
|
+
|
5
|
+
def initialize(path:)
|
6
|
+
@path = path
|
7
|
+
load_app
|
8
|
+
end
|
9
|
+
|
10
|
+
def template_path
|
11
|
+
File.join(path, 'templates', 'resume.html.erb')
|
12
|
+
end
|
13
|
+
|
14
|
+
def processor(output:, format:)
|
15
|
+
Processor.new(app: self, output: output, format: format)
|
16
|
+
end
|
17
|
+
|
18
|
+
class Processor
|
19
|
+
attr_reader :app, :output, :format
|
20
|
+
|
21
|
+
def initialize(app:, output:, format:)
|
22
|
+
@app = app
|
23
|
+
@output = output
|
24
|
+
@format = format
|
25
|
+
end
|
26
|
+
|
27
|
+
def filename
|
28
|
+
File.extname(output) == ".#{format}" ? output : "#{output}.#{format}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def process
|
32
|
+
case format.to_sym
|
33
|
+
when :html then process_html
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def process_html
|
40
|
+
Resulang::Template.new(resume: app.resume, path: app.template_path).process
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def load_app
|
47
|
+
unless File.directory?('data') && File.directory?('templates')
|
48
|
+
raise "no Resulang app found at #{path.inspect}"
|
49
|
+
end
|
50
|
+
|
51
|
+
load_sections
|
52
|
+
load_resume
|
53
|
+
end
|
54
|
+
|
55
|
+
def load_sections
|
56
|
+
section_paths.each { |section| require section }
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_resume
|
60
|
+
@resume = Resulang::Dsl.new(resume_path).resume
|
61
|
+
end
|
62
|
+
|
63
|
+
def sections_dir
|
64
|
+
File.join(path, 'data', 'sections')
|
65
|
+
end
|
66
|
+
|
67
|
+
def section_paths
|
68
|
+
Dir[File.join(sections_dir, '**', '*.rb')]
|
69
|
+
end
|
70
|
+
|
71
|
+
def resume_path
|
72
|
+
File.join(path, 'data', 'resume.rb')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/resulang/dsl.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Resulang
|
2
|
+
class Dsl
|
3
|
+
attr_reader :path
|
4
|
+
|
5
|
+
def self.register_section!(section, klass)
|
6
|
+
define_section_method(section, klass)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
@resume = Resume.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def resume
|
15
|
+
unless @evaluated
|
16
|
+
instance_eval(File.read(path))
|
17
|
+
@evaluated = true
|
18
|
+
end
|
19
|
+
|
20
|
+
@resume
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def self.define_section_method(section, klass)
|
26
|
+
define_method(section) do |&block|
|
27
|
+
@resume.sections[section.to_sym] = klass.new(&block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
module Resulang
|
5
|
+
class Exec < Thor
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
desc 'new NAME', 'Generate a new Resulang app in directory NAME'
|
9
|
+
option :sections, type: :array, required: false, default: [], desc: 'A list of initial sections to generate'
|
10
|
+
def new(name)
|
11
|
+
empty_directory(name)
|
12
|
+
inside(name) do
|
13
|
+
create_file "server.ru" do
|
14
|
+
<<-SERVER
|
15
|
+
require "resulang/server"
|
16
|
+
run Resulang::Server
|
17
|
+
SERVER
|
18
|
+
end
|
19
|
+
|
20
|
+
empty_directory('data')
|
21
|
+
inside('data') do
|
22
|
+
create_file('resume.rb') do
|
23
|
+
options[:sections].inject([]) { |list, s| list.push("#{s} do\n\nend") }.join("\n\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
empty_directory('sections')
|
27
|
+
inside('sections') do
|
28
|
+
options[:sections].each do |s|
|
29
|
+
create_file("#{s}.rb", "class #{ActiveSupport::Inflector.camelize(s)} < Resulang::Section\n\nend")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
empty_directory 'templates'
|
35
|
+
inside('templates') do
|
36
|
+
create_file('resume.html.erb')
|
37
|
+
options[:sections].each do |s|
|
38
|
+
create_file("_#{s}.html.erb")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'server', 'Start a development server'
|
45
|
+
def server
|
46
|
+
run %{rackup server.ru}
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'make', 'Generate a static HTML file from a Resulang app'
|
50
|
+
option :output, type: :string, default: 'resume', required: false, desc: 'Path to generated HTML'
|
51
|
+
option :force, type: :boolean, default: false, required: false, desc: 'Ask to overwrite files or not'
|
52
|
+
def make
|
53
|
+
app = Resulang::App.new(path: File.expand_path('.'))
|
54
|
+
processor = app.processor(output: options[:output], format: :html)
|
55
|
+
create_file(processor.filename, force: options[:force]) { processor.process }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Resulang
|
2
|
+
module Fields
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
class Email < String
|
8
|
+
end
|
9
|
+
|
10
|
+
class Link < String
|
11
|
+
end
|
12
|
+
|
13
|
+
class PointList
|
14
|
+
attr_reader :points
|
15
|
+
|
16
|
+
def initialize(string: nil, &block)
|
17
|
+
@string = string
|
18
|
+
@points = [ ]
|
19
|
+
instance_eval(&block) if block
|
20
|
+
end
|
21
|
+
|
22
|
+
def point(string, &block)
|
23
|
+
points.push(PointList.new(string: string, &block))
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
@string
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
protected def string(*attrs)
|
33
|
+
fields(*attrs) { |value| value }
|
34
|
+
end
|
35
|
+
|
36
|
+
protected def email(*attrs)
|
37
|
+
fields(*attrs) { |value| Email.new(value) }
|
38
|
+
end
|
39
|
+
|
40
|
+
protected def link(*attrs)
|
41
|
+
fields(*attrs) { |value| Link.new(value) }
|
42
|
+
end
|
43
|
+
|
44
|
+
protected def list(*attrs)
|
45
|
+
fields(*attrs) { |value| Array(value) }
|
46
|
+
end
|
47
|
+
|
48
|
+
protected def range(*attrs)
|
49
|
+
fields(*attrs) { |*values| (values.first..values.last) }
|
50
|
+
end
|
51
|
+
|
52
|
+
protected def pointlist(*attrs)
|
53
|
+
fields(*attrs) { |&block| PointList.new(&block) }
|
54
|
+
end
|
55
|
+
|
56
|
+
private def fields(*names, &block)
|
57
|
+
names.each do |name|
|
58
|
+
define_method(name) do |*args, &b|
|
59
|
+
if args.empty? && b.nil?
|
60
|
+
field_get(name)
|
61
|
+
else
|
62
|
+
field_set(name, block.call(*args, &b))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Instance Methods
|
71
|
+
#
|
72
|
+
private def field_set(attr, value)
|
73
|
+
instance_variable_set("@#{attr}", value)
|
74
|
+
end
|
75
|
+
|
76
|
+
private def field_get(attr)
|
77
|
+
instance_variable_get("@#{attr}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Resulang
|
4
|
+
module Rendering
|
5
|
+
include ActiveSupport::Inflector
|
6
|
+
|
7
|
+
def render_section(section)
|
8
|
+
if s = sections[section.to_sym]
|
9
|
+
ERB.new(File.read(partial(section))).result(s.get_binding)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def html_escape(str)
|
14
|
+
ERB::Util.html_escape(str)
|
15
|
+
end
|
16
|
+
|
17
|
+
def partial(name)
|
18
|
+
File.expand_path("../_#{name}.html.erb", template_path)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Resulang
|
4
|
+
class Section
|
5
|
+
include Fields
|
6
|
+
include Rendering
|
7
|
+
|
8
|
+
def self.inherited(subclass)
|
9
|
+
Resulang::Dsl.register_section!(ActiveSupport::Inflector.underscore(subclass.name), subclass)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(&block)
|
13
|
+
instance_eval(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_binding
|
17
|
+
binding
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'resulang'
|
2
|
+
require 'rack'
|
3
|
+
require 'mime/types'
|
4
|
+
|
5
|
+
module Resulang
|
6
|
+
class Server
|
7
|
+
def self.escape(html)
|
8
|
+
html.gsub(/\</, '<').gsub(/\>/, '>').gsub(/\"/, '"')
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mime_type(filename)
|
12
|
+
if (types = MIME::Types.type_for(filename)).empty?
|
13
|
+
'text/plain'
|
14
|
+
else
|
15
|
+
types.first.content_type
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.app
|
20
|
+
Resulang::App.new(path: File.expand_path('.'))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.serve_html
|
24
|
+
html = app.processor(output: nil, format: :html).process
|
25
|
+
headers = {
|
26
|
+
'Content-Type' => 'text/html'
|
27
|
+
}
|
28
|
+
[200, headers, [html]]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.serve_file(path)
|
32
|
+
fullpath = File.expand_path("./#{path}")
|
33
|
+
if File.file?(fullpath)
|
34
|
+
data = File.read(fullpath)
|
35
|
+
headers = {
|
36
|
+
'Content-Type' => mime_type(File.basename(path))
|
37
|
+
}
|
38
|
+
[200, headers, [data]]
|
39
|
+
else
|
40
|
+
[404, { 'Content-Type' => 'text/html' }, ['Not Found']]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.call(env)
|
45
|
+
if env['PATH_INFO'] == '/'
|
46
|
+
serve_html
|
47
|
+
else
|
48
|
+
serve_file(env['PATH_INFO'])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Resulang
|
4
|
+
class Template < SimpleDelegator
|
5
|
+
include Rendering
|
6
|
+
|
7
|
+
# Any 'attr_reader' attributes defined here will be
|
8
|
+
# available in the template.
|
9
|
+
attr_reader :template_path
|
10
|
+
|
11
|
+
def initialize(resume:, path:)
|
12
|
+
@template_path = path
|
13
|
+
|
14
|
+
# Delegate everything else to resume allows code within the template to
|
15
|
+
# do things like <%= personal.name %> which is the equivalent of
|
16
|
+
# <%= resume.personal.name %>.
|
17
|
+
super(resume)
|
18
|
+
end
|
19
|
+
|
20
|
+
def process
|
21
|
+
ERB.new(File.read(template_path)).result(binding)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/resulang.rb
ADDED
data/resulang.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'resulang/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "resulang"
|
8
|
+
spec.version = Resulang::VERSION
|
9
|
+
spec.authors = ["Peter Brindisi"]
|
10
|
+
spec.email = ["peter.brindisi+resulang@gmail.com"]
|
11
|
+
spec.summary = %q{Resulang is a simple DSL to help create html resumes.}
|
12
|
+
spec.homepage = "https://github.com/npj/resulang"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "thor", "~> 0.19.1"
|
21
|
+
spec.add_dependency "activesupport", "~> 4.2.6"
|
22
|
+
spec.add_dependency "rack", "~> 1.6.4"
|
23
|
+
spec.add_dependency "mime-types", "~> 3.0"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.4.0"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: resulang
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Brindisi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.19.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.19.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.2.6
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.2.6
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.6.4
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.6.4
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mime-types
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.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.4.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.4.0
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- peter.brindisi+resulang@gmail.com
|
114
|
+
executables:
|
115
|
+
- resulang
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".ruby-gemset"
|
121
|
+
- ".ruby-version"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- bin/resulang
|
127
|
+
- examples/my_resume/assets/css/style.css
|
128
|
+
- examples/my_resume/data/resume.rb
|
129
|
+
- examples/my_resume/data/sections/background.rb
|
130
|
+
- examples/my_resume/data/sections/hobbies.rb
|
131
|
+
- examples/my_resume/data/sections/personal.rb
|
132
|
+
- examples/my_resume/data/sections/skills.rb
|
133
|
+
- examples/my_resume/resume.html
|
134
|
+
- examples/my_resume/server.ru
|
135
|
+
- examples/my_resume/templates/_background.html.erb
|
136
|
+
- examples/my_resume/templates/_hobbies.html.erb
|
137
|
+
- examples/my_resume/templates/_personal.html.erb
|
138
|
+
- examples/my_resume/templates/_skills.html.erb
|
139
|
+
- examples/my_resume/templates/resume.html.erb
|
140
|
+
- lib/resulang.rb
|
141
|
+
- lib/resulang/app.rb
|
142
|
+
- lib/resulang/dsl.rb
|
143
|
+
- lib/resulang/exec.rb
|
144
|
+
- lib/resulang/fields.rb
|
145
|
+
- lib/resulang/rendering.rb
|
146
|
+
- lib/resulang/resume.rb
|
147
|
+
- lib/resulang/section.rb
|
148
|
+
- lib/resulang/server.rb
|
149
|
+
- lib/resulang/template.rb
|
150
|
+
- lib/resulang/version.rb
|
151
|
+
- resulang.gemspec
|
152
|
+
homepage: https://github.com/npj/resulang
|
153
|
+
licenses:
|
154
|
+
- MIT
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.4.6
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: Resulang is a simple DSL to help create html resumes.
|
176
|
+
test_files: []
|