enwrite 0.2.0
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/.document +5 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +69 -0
- data/LICENSE +22 -0
- data/LICENSE.txt +20 -0
- data/README.md +90 -0
- data/Rakefile +56 -0
- data/bin/enwrite +11 -0
- data/lib/enml-utils.rb +196 -0
- data/lib/enwrite.rb +299 -0
- data/lib/evernote-utils.rb +234 -0
- data/lib/filters.rb +64 -0
- data/lib/output.rb +9 -0
- data/lib/output/hugo.rb +236 -0
- data/lib/util.rb +44 -0
- data/test/helper.rb +34 -0
- data/test/test_enwrite.rb +7 -0
- metadata +179 -0
data/lib/filters.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'htmlentities'
|
3
|
+
|
4
|
+
module Filters
|
5
|
+
|
6
|
+
def run_filters(text)
|
7
|
+
newtext = text
|
8
|
+
text.scan(/(\[(\w+)([^\]]*)\])/) do |m|
|
9
|
+
match = m[0]
|
10
|
+
debug "match = #{match}"
|
11
|
+
filter = m[1]
|
12
|
+
args = m[2]
|
13
|
+
if Filters.method_defined?("filter_#{filter}")
|
14
|
+
fn=Filters.method("filter_#{filter}")
|
15
|
+
arg = {}
|
16
|
+
args = HTMLEntities.new.decode(args)
|
17
|
+
debug "args = #{args}"
|
18
|
+
args.scan(/\b(\w+)=["“]([^"]*)["”]/) { |a|
|
19
|
+
arg[a[0]] = a[1]
|
20
|
+
}
|
21
|
+
verbose "Calling filter_#{filter} with args #{arg}"
|
22
|
+
result = fn.(arg)
|
23
|
+
if not result.nil?
|
24
|
+
newtext = newtext.gsub(match, result)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
# We only produce this message in verbose mode because it gets triggered
|
28
|
+
# every time [some text in brackets] is used
|
29
|
+
warn("Warning: nonexistent filter #{filter} used, leaving text as is") if $enwrite_verbose
|
30
|
+
end
|
31
|
+
end
|
32
|
+
debug "After running filters:"
|
33
|
+
debug newtext
|
34
|
+
return newtext
|
35
|
+
end
|
36
|
+
|
37
|
+
def filter_youtube(args)
|
38
|
+
if args.include?('url')
|
39
|
+
args['src'] = args['url']
|
40
|
+
args.delete('url')
|
41
|
+
elsif args.include?('id')
|
42
|
+
args['src'] = "https://www.youtube.com/embed/#{args['id']}"
|
43
|
+
end
|
44
|
+
if args['src'].nil?
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
args['src'].gsub!(/\/watch\?v=/, "/embed/")
|
48
|
+
return "<iframe "+args.each.map{ |k,v| "#{k}=\"#{v}\"" }.join(" ")+"></iframe>"
|
49
|
+
end
|
50
|
+
|
51
|
+
def filter_gist(args)
|
52
|
+
if args.include?('url')
|
53
|
+
args['src'] = args['url']
|
54
|
+
args.delete('url')
|
55
|
+
end
|
56
|
+
if args['src'].nil?
|
57
|
+
return nil
|
58
|
+
end
|
59
|
+
if not args['src'] =~ /\.js$/
|
60
|
+
args['src'] += ".js"
|
61
|
+
end
|
62
|
+
return "<script "+args.each.map{ |k,v| "#{k}=\"#{v}\"" }.join(" ")+"></script>"
|
63
|
+
end
|
64
|
+
end
|
data/lib/output.rb
ADDED
data/lib/output/hugo.rb
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
#
|
2
|
+
# Output class for Hugo
|
3
|
+
#
|
4
|
+
# Diego Zamboni, March 2015
|
5
|
+
# Time-stamp: <2015-04-30 12:40:31 diego>
|
6
|
+
|
7
|
+
require 'output'
|
8
|
+
require 'filters'
|
9
|
+
require 'enml-utils'
|
10
|
+
require 'fileutils'
|
11
|
+
require 'yaml/store'
|
12
|
+
require 'digest'
|
13
|
+
|
14
|
+
include Filters
|
15
|
+
|
16
|
+
class Hugo < Output
|
17
|
+
def initialize(opts = {})
|
18
|
+
@opts = opts
|
19
|
+
@base_dir = opts['base_dir']
|
20
|
+
unless @base_dir
|
21
|
+
error "The 'base_dir' option of the Hugo plugin must be set!"
|
22
|
+
end
|
23
|
+
@use_filters = opts['use_filters'] || true
|
24
|
+
@rebuild_all = opts['rebuild_all'] || false
|
25
|
+
|
26
|
+
# Persistent store for this base_dir
|
27
|
+
datadir = "#{@base_dir}/data"
|
28
|
+
FileUtils.mkdir_p datadir
|
29
|
+
@config_store = YAML::Store.new("#{datadir}/enwrite_data.yaml")
|
30
|
+
|
31
|
+
# Initialize GUID-to-filename map if needed
|
32
|
+
@config_store.transaction { @config_store[:note_files] = {} unless @config_store[:note_files] }
|
33
|
+
|
34
|
+
# These are [ realpath, urlpath ]
|
35
|
+
@static_dir = [ "#{@base_dir}/#{opts['static_subdir'] || 'static' }", opts['static_url'] || "" ]
|
36
|
+
@static_subdirs = { 'image' => opts['image_subdir'] || 'img',
|
37
|
+
'audio' => opts['audio_subdir'] || 'audio',
|
38
|
+
'video' => opts['video_subdir'] || 'video',
|
39
|
+
'files' => opts['files_subdir'] || 'files',
|
40
|
+
}
|
41
|
+
|
42
|
+
# Tag-to-type map
|
43
|
+
@tag_to_type = opts['tag_to_type'] || { "default" => "post/",
|
44
|
+
"post" => "post/",
|
45
|
+
"page" => "" }
|
46
|
+
@tag_to_type_order = opts['tag_to_type_order'] || [ "post", "page", "default" ]
|
47
|
+
|
48
|
+
@tag_to_type_order.each { |type|
|
49
|
+
@tag_to_type[type] = "" unless @tag_to_type.include?(type)
|
50
|
+
@tag_to_type[type] = "" if @tag_to_type[type].nil?
|
51
|
+
}
|
52
|
+
|
53
|
+
# Markdown tag
|
54
|
+
@markdown_tag = opts['markdown_tag'] || "markdown"
|
55
|
+
|
56
|
+
# Command to run hugo
|
57
|
+
@hugo_cmd = opts['hugo_cmd'] || "hugo"
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_static_dirs(note)
|
61
|
+
@static_dirs = {}
|
62
|
+
@static_dirs['note'] = [ "#{@static_dir[0]}/note/#{note.guid}",
|
63
|
+
"#{@static_dir[1]}/note/#{note.guid}" ]
|
64
|
+
['image', 'audio', 'video', 'files']. each do |type|
|
65
|
+
@static_dirs[type] = [ "#{@static_dirs['note'][0]}/#{@static_subdirs[type]}", # full path
|
66
|
+
"#{@static_dirs['note'][1]}/#{@static_subdirs[type]}" ]; # url path
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_note(note, fname)
|
71
|
+
set_static_dirs(note)
|
72
|
+
|
73
|
+
if File.exist?(fname)
|
74
|
+
msg " This note has been deleted from Evernote, deleting its file #{fname}"
|
75
|
+
File.delete(fname)
|
76
|
+
end
|
77
|
+
if Dir.exist?(@static_dirs['note'][0])
|
78
|
+
msg " Deleting static files for deleted note #{@static_dirs['note'][0]}"
|
79
|
+
FileUtils.rmtree(@static_dirs['note'][0])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def output_note(note)
|
84
|
+
set_static_dirs(note)
|
85
|
+
|
86
|
+
msg "Found note '#{note.title}'"
|
87
|
+
verbose "Created: #{Time.at(note.created/1000)}" if note.created
|
88
|
+
verbose "Deleted: #{Time.at(note.deleted/1000)}" if note.deleted
|
89
|
+
verbose "Content length: #{note.contentLength}" if note.contentLength
|
90
|
+
verbose "Clipped from: #{note.attributes.sourceURL}" if note.attributes.sourceURL
|
91
|
+
|
92
|
+
markdown = note.tagNames.include?(@markdown_tag)
|
93
|
+
if markdown
|
94
|
+
msg " It has the '#{ @markdown_tag }' tag, so I will interpret it as markdown"
|
95
|
+
note.tagNames -= [ @markdown_tag ]
|
96
|
+
end
|
97
|
+
|
98
|
+
type = nil
|
99
|
+
# Detect the type of post according to its tags
|
100
|
+
@tag_to_type_order.each do |tag|
|
101
|
+
if note.tagNames.include?(tag) or tag == "default"
|
102
|
+
type = @tag_to_type[tag]
|
103
|
+
break
|
104
|
+
end
|
105
|
+
end
|
106
|
+
if type.nil?
|
107
|
+
error " ### I couldn't determine the type for this post - skipping it"
|
108
|
+
return
|
109
|
+
end
|
110
|
+
|
111
|
+
# Determine if we should include the page in the main menu
|
112
|
+
inmainmenu = note.tagNames.include?('_mainmenu')
|
113
|
+
if inmainmenu
|
114
|
+
note.tagNames -= [ '_mainmenu' ]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Determine if we should use a custom slug
|
118
|
+
slug = nil
|
119
|
+
note.tagNames.grep(/^_slug=(\S+)/) do |slugtag|
|
120
|
+
slug = $1
|
121
|
+
note.tagNames -= [ slugtag ]
|
122
|
+
verbose " Will use custom slug for this post: #{slug}"
|
123
|
+
end
|
124
|
+
|
125
|
+
# Get our note GUID-to-filename map
|
126
|
+
note_files = config(:note_files, {}, @config_store)
|
127
|
+
|
128
|
+
# Determine the name I would assign to this note when published to Hugo
|
129
|
+
date = Time.at(note.created/1000).strftime('%F')
|
130
|
+
post_filename = "#{type}#{date}-#{note.title}.#{markdown ? 'md' : 'html'}"
|
131
|
+
# Do we already have a post for this note (by GUID)? If so, we remove the
|
132
|
+
# old file since it will be regenerated anyway, which also takes care of the
|
133
|
+
# case when the note was renamed and the filename will change, to avoid
|
134
|
+
# post duplication. If the note has been deleted, we just delete the
|
135
|
+
# old filename and stop here.
|
136
|
+
oldfile = note_files[note.guid]
|
137
|
+
if oldfile
|
138
|
+
verbose " I already had a file for note #{note.guid}, removing #{oldfile}"
|
139
|
+
File.delete(oldfile) if File.exist?(oldfile)
|
140
|
+
note_files.delete(note.guid)
|
141
|
+
setconfig(:note_files, note_files, @config_store)
|
142
|
+
if note.deleted
|
143
|
+
delete_note(note, oldfile)
|
144
|
+
return
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Run hugo to create the file, then read it back it to update the front matter
|
149
|
+
# with our tags.
|
150
|
+
# We run "hugo new" also for deleted notes so that hugo gives us the filename
|
151
|
+
# to delete.
|
152
|
+
fname = nil
|
153
|
+
frontmatter = nil
|
154
|
+
Dir.chdir(@base_dir) do
|
155
|
+
# Force -f yaml because it's so much easier to process
|
156
|
+
while true
|
157
|
+
post_filename.gsub!(/"/, '\"')
|
158
|
+
cmd = %Q(#{@hugo_cmd} new -f yaml "#{post_filename}" 2>&1)
|
159
|
+
debug "Executing: #{cmd}"
|
160
|
+
output = %x(#{cmd})
|
161
|
+
if output =~ /^(.+) created$/
|
162
|
+
# Get the full filename as reported by Hugo
|
163
|
+
fname = $1
|
164
|
+
if note.deleted
|
165
|
+
delete_note(note, fname)
|
166
|
+
return
|
167
|
+
end
|
168
|
+
# Load the frontmatter
|
169
|
+
frontmatter = YAML.load_file(fname)
|
170
|
+
# Update title because Hugo gets it wrong sometimes depending on the characters in the title, and to get rid of the date we put in the filename
|
171
|
+
frontmatter['title'] = note.title
|
172
|
+
# Fix the date to the date when the note was created
|
173
|
+
frontmatter['date'] = date
|
174
|
+
# Update tags, for now set categories to the same
|
175
|
+
frontmatter['tags'] = note.tagNames
|
176
|
+
frontmatter['categories'] = note.tagNames
|
177
|
+
# Set slug to work around https://github.com/spf13/hugo/issues/1017
|
178
|
+
frontmatter['slug'] = slug ? slug : note.title.downcase.gsub(/\W+/, "-").gsub(/^-+/, "").gsub(/-+$/, "")
|
179
|
+
# Set main menu tag if needed
|
180
|
+
frontmatter['menu'] = 'main' if inmainmenu
|
181
|
+
break
|
182
|
+
elsif output =~ /ERROR: \S+ (.+) already exists/
|
183
|
+
# Get the full filename as reported by Hugo
|
184
|
+
fname = $1
|
185
|
+
# If the file existed already, remove it and regenerate it
|
186
|
+
File.delete(fname)
|
187
|
+
if note.deleted
|
188
|
+
delete_note(note, fname)
|
189
|
+
return
|
190
|
+
end
|
191
|
+
# This shouldn't happen due to the index check above
|
192
|
+
unless @rebuild_all
|
193
|
+
error " I found a file that should not be there (#{fname}). This might indicate"
|
194
|
+
error " an inconsistency in my internal note-to-file map. Please re-run with"
|
195
|
+
error " --rebuild-all to regenerate it. I am deleting the file and continuing"
|
196
|
+
error " for now, but please review the results carefully."
|
197
|
+
end
|
198
|
+
redo
|
199
|
+
else
|
200
|
+
error " Hugo returned unknown output when trying to create this post - skipping it: #{output}"
|
201
|
+
return
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
debug "Updated frontmatter: #{frontmatter.to_s}"
|
207
|
+
|
208
|
+
File.open(fname, "w") do |f|
|
209
|
+
f.write(frontmatter.to_yaml)
|
210
|
+
f.puts("---")
|
211
|
+
f.puts
|
212
|
+
enml = ENML_utils.new(note.content, note.resources, @static_dirs, note.guid)
|
213
|
+
output = markdown ? enml.to_text : enml.to_html
|
214
|
+
if @use_filters
|
215
|
+
verbose "Running filters on text"
|
216
|
+
output = run_filters(output)
|
217
|
+
end
|
218
|
+
if note.attributes.sourceURL
|
219
|
+
f.puts(%(<p class="clip-attribute">via <a href="#{note.attributes.sourceURL}">#{note.attributes.sourceURL}</a></p>))
|
220
|
+
end
|
221
|
+
f.puts(output)
|
222
|
+
enml.resource_files.each do |resfile|
|
223
|
+
FileUtils.mkdir_p File.dirname(resfile[:fname])
|
224
|
+
File.open(resfile[:fname], "w") do |r|
|
225
|
+
r.write(resfile[:data])
|
226
|
+
end
|
227
|
+
verbose "Wrote file #{resfile[:fname]}"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
verbose "Wrote file #{fname}"
|
232
|
+
note_files[note.guid] = fname
|
233
|
+
setconfig(:note_files, note_files, @config_store)
|
234
|
+
|
235
|
+
end
|
236
|
+
end
|
data/lib/util.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'yaml/store'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
# Message output
|
5
|
+
|
6
|
+
def verbose(msg)
|
7
|
+
puts ("Enwrite [VERBOSE]: " + msg).blue if $enwrite_verbose
|
8
|
+
end
|
9
|
+
|
10
|
+
def debug(msg)
|
11
|
+
puts ("Enwrite [DEBUG]: " + msg) if $enwrite_debug
|
12
|
+
end
|
13
|
+
|
14
|
+
def error(msg)
|
15
|
+
$stderr.puts ("Enwrite [ERROR]: " + msg).red
|
16
|
+
end
|
17
|
+
|
18
|
+
def msg(msg)
|
19
|
+
puts ("Enwrite [INFO]: " + msg).green
|
20
|
+
end
|
21
|
+
|
22
|
+
def warn(msg)
|
23
|
+
$stderr.puts ("Enwrite [WARN]: " + msg).light_yellow
|
24
|
+
end
|
25
|
+
|
26
|
+
# Config file storage
|
27
|
+
|
28
|
+
def config_file
|
29
|
+
return "#{ENV['HOME']}/.enwrite.config"
|
30
|
+
end
|
31
|
+
|
32
|
+
def config_store
|
33
|
+
return YAML::Store.new(config_file())
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get a persistent config value
|
37
|
+
def config(key, defval=nil, store=config_store)
|
38
|
+
return store.transaction { store.fetch(key, defval) }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Set a persistent config value
|
42
|
+
def setconfig(key, val, store=config_store)
|
43
|
+
return store.transaction { store[key] = val }
|
44
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
|
3
|
+
module SimpleCov::Configuration
|
4
|
+
def clean_filters
|
5
|
+
@filters = []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
SimpleCov.configure do
|
10
|
+
clean_filters
|
11
|
+
load_adapter 'test_frameworks'
|
12
|
+
end
|
13
|
+
|
14
|
+
ENV["COVERAGE"] && SimpleCov.start do
|
15
|
+
add_filter "/.rvm/"
|
16
|
+
end
|
17
|
+
require 'rubygems'
|
18
|
+
require 'bundler'
|
19
|
+
begin
|
20
|
+
Bundler.setup(:default, :development)
|
21
|
+
rescue Bundler::BundlerError => e
|
22
|
+
$stderr.puts e.message
|
23
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
24
|
+
exit e.status_code
|
25
|
+
end
|
26
|
+
require 'test/unit'
|
27
|
+
require 'shoulda'
|
28
|
+
|
29
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
30
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
31
|
+
require 'enwrite'
|
32
|
+
|
33
|
+
class Test::Unit::TestCase
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: enwrite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Diego Zamboni
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: deep_merge
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: evernote-thrift
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.25'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.25'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: evernote_oauth
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: htmlentities
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.3'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rdoc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: bundler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: jeweler
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.0'
|
125
|
+
description: |-
|
126
|
+
Enwrite allows you to generate a website from contents stored in Evernote.
|
127
|
+
At the moment only Hugo (http://gohugo.io) is supported as an output format,
|
128
|
+
but others can be added through plugins.
|
129
|
+
email: diego@zzamboni.org
|
130
|
+
executables:
|
131
|
+
- enwrite
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files:
|
134
|
+
- LICENSE
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
files:
|
138
|
+
- ".document"
|
139
|
+
- Gemfile
|
140
|
+
- Gemfile.lock
|
141
|
+
- LICENSE
|
142
|
+
- LICENSE.txt
|
143
|
+
- README.md
|
144
|
+
- Rakefile
|
145
|
+
- bin/enwrite
|
146
|
+
- lib/enml-utils.rb
|
147
|
+
- lib/enwrite.rb
|
148
|
+
- lib/evernote-utils.rb
|
149
|
+
- lib/filters.rb
|
150
|
+
- lib/output.rb
|
151
|
+
- lib/output/hugo.rb
|
152
|
+
- lib/util.rb
|
153
|
+
- test/helper.rb
|
154
|
+
- test/test_enwrite.rb
|
155
|
+
homepage: http://github.com/zzamboni/enwrite
|
156
|
+
licenses:
|
157
|
+
- MIT
|
158
|
+
metadata: {}
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
requirements: []
|
174
|
+
rubyforge_project:
|
175
|
+
rubygems_version: 2.4.5
|
176
|
+
signing_key:
|
177
|
+
specification_version: 4
|
178
|
+
summary: 'Enwrite: Power a web site using Evernote'
|
179
|
+
test_files: []
|