joplin 0.5.2 → 1.0.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 +4 -4
- data/Gemfile +0 -6
- data/Gemfile.lock +42 -23
- data/Makefile +6 -6
- data/bin/joplin +70 -45
- data/joplin.gemspec +23 -23
- data/lib/joplin/version.rb +1 -1
- data/lib/joplin.rb +121 -84
- data/{README.md → readme.md} +14 -1
- metadata +34 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74c549d0f51425533265897cf2432dc52bfa866ef89f91bfaeb8565939b6c0ff
|
4
|
+
data.tar.gz: 46b1ee7c947603256778c0df08ba027d964d5451594374323a9a5dd2059f4afa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1c2eefbb3fa1405d54395ab787c9bd69fda22d8f6f84cba0f7efe792f93b70c6a557d09b7059a525e301ef26233cd5dc2d0c0fa4835f400d5b809e06101da95
|
7
|
+
data.tar.gz: 5367467b053246881bc9a4d539641765141984b77de421c7efa31d01509ffe6d7b30c94e2d9d5eabd8962cb5a4ef794dd7433674e20dd9fca4e5c142bf70804b
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,43 +2,62 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
joplin (0.5.2)
|
5
|
-
|
5
|
+
http (~> 5.1.1)
|
6
|
+
sqlite3 (~> 1.6.3)
|
7
|
+
thor (~> 1.2.2)
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
11
|
specs:
|
12
|
+
addressable (2.8.4)
|
13
|
+
public_suffix (>= 2.0.2, < 6.0)
|
10
14
|
diff-lcs (1.5.0)
|
11
|
-
|
12
|
-
|
13
|
-
|
15
|
+
domain_name (0.5.20190701)
|
16
|
+
unf (>= 0.0.5, < 1.0.0)
|
17
|
+
ffi (1.15.5)
|
18
|
+
ffi-compiler (1.0.1)
|
19
|
+
ffi (>= 1.0.0)
|
20
|
+
rake
|
21
|
+
http (5.1.1)
|
22
|
+
addressable (~> 2.8)
|
23
|
+
http-cookie (~> 1.0)
|
24
|
+
http-form_data (~> 2.2)
|
25
|
+
llhttp-ffi (~> 0.4.0)
|
26
|
+
http-cookie (1.0.5)
|
27
|
+
domain_name (~> 0.5)
|
28
|
+
http-form_data (2.3.0)
|
29
|
+
llhttp-ffi (0.4.0)
|
30
|
+
ffi-compiler (~> 1.0)
|
31
|
+
rake (~> 13.0)
|
32
|
+
public_suffix (5.0.1)
|
14
33
|
rake (13.0.6)
|
15
|
-
rspec (3.
|
16
|
-
rspec-core (~> 3.
|
17
|
-
rspec-expectations (~> 3.
|
18
|
-
rspec-mocks (~> 3.
|
19
|
-
rspec-core (3.
|
20
|
-
rspec-support (~> 3.
|
21
|
-
rspec-expectations (3.
|
34
|
+
rspec (3.12.0)
|
35
|
+
rspec-core (~> 3.12.0)
|
36
|
+
rspec-expectations (~> 3.12.0)
|
37
|
+
rspec-mocks (~> 3.12.0)
|
38
|
+
rspec-core (3.12.2)
|
39
|
+
rspec-support (~> 3.12.0)
|
40
|
+
rspec-expectations (3.12.3)
|
22
41
|
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
-
rspec-support (~> 3.
|
24
|
-
rspec-mocks (3.
|
42
|
+
rspec-support (~> 3.12.0)
|
43
|
+
rspec-mocks (3.12.5)
|
25
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
-
rspec-support (~> 3.
|
27
|
-
rspec-support (3.
|
28
|
-
sqlite3 (1.
|
29
|
-
thor (1.2.
|
45
|
+
rspec-support (~> 3.12.0)
|
46
|
+
rspec-support (3.12.1)
|
47
|
+
sqlite3 (1.6.3-arm64-darwin)
|
48
|
+
thor (1.2.2)
|
49
|
+
unf (0.1.4)
|
50
|
+
unf_ext
|
51
|
+
unf_ext (0.0.8.2)
|
30
52
|
|
31
53
|
PLATFORMS
|
32
|
-
|
54
|
+
arm64-darwin-22
|
33
55
|
|
34
56
|
DEPENDENCIES
|
35
57
|
bundler (~> 2.0)
|
36
|
-
faraday (~> 1.0)
|
37
58
|
joplin!
|
38
59
|
rake (~> 13.0)
|
39
|
-
rspec (~> 3.0)
|
40
|
-
sqlite3 (~> 1.4)
|
41
|
-
thor (~> 1.0)
|
60
|
+
rspec (~> 3.12.0)
|
42
61
|
|
43
62
|
BUNDLED WITH
|
44
|
-
2.
|
63
|
+
2.4.10
|
data/Makefile
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
|
1
|
+
test:
|
2
|
+
rake spec
|
3
|
+
|
4
|
+
build:
|
2
5
|
gem build joplin.gemspec
|
3
6
|
|
4
|
-
push: clean
|
7
|
+
push: clean build
|
5
8
|
gem push *gem
|
6
9
|
|
7
10
|
clean:
|
8
11
|
rm -f *gem
|
9
12
|
|
10
|
-
|
11
|
-
rake
|
12
|
-
|
13
|
-
install: clean all
|
13
|
+
install: clean build
|
14
14
|
gem install --local *gem
|
data/bin/joplin
CHANGED
@@ -1,96 +1,121 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$:.unshift File.expand_path(
|
3
|
+
$:.unshift File.expand_path('../lib', __dir__)
|
4
4
|
|
5
|
-
require
|
5
|
+
require 'joplin'
|
6
6
|
require 'thor'
|
7
7
|
|
8
|
-
DIVIDER = %
|
8
|
+
DIVIDER = %(
|
9
9
|
|
10
10
|
<svg height="50" width="460">
|
11
11
|
<style> .line { stroke-width: 1px; fill: black; stroke: black; } </style>
|
12
12
|
<g id="triangle"><path d="M0 30 L200 30 Q 220 25 200 35 Z" class="line" /></g>
|
13
|
-
<use
|
13
|
+
<use href="#triangle" transform="scale(-1 1) translate(-450 0)"/>
|
14
14
|
<circle cx="225" cy="32" r="7" class="line"/>
|
15
15
|
</svg>
|
16
16
|
|
17
17
|
)
|
18
18
|
|
19
|
-
|
20
19
|
class MyCLI < Thor
|
21
|
-
class_option :token, :
|
22
|
-
class_option :help, :
|
23
|
-
class_option :version, :
|
24
|
-
map [
|
25
|
-
map [
|
20
|
+
class_option :token, type: :string # , required: true
|
21
|
+
class_option :help, type: :boolean
|
22
|
+
class_option :version, type: :boolean
|
23
|
+
map ['-v', '--version'] => :version
|
24
|
+
map ['-h', '--help'] => :help
|
26
25
|
option :token
|
27
|
-
option :'dry-run', desc:
|
28
|
-
desc :clean,
|
26
|
+
option :'dry-run', desc: 'dry-run', aliases: '-n'
|
27
|
+
desc :clean, 'clean unused resources'
|
29
28
|
def clean
|
30
|
-
Joplin
|
31
|
-
puts
|
32
|
-
Joplin::Resource.orphaned.map
|
33
|
-
r.delete
|
34
|
-
would =
|
29
|
+
Joplin.token = Joplinl.get_token || options[:token]
|
30
|
+
puts 'Please wait, this can take while.'
|
31
|
+
Joplin::Resource.orphaned.map do |r|
|
32
|
+
r.delete unless options['dry-run']
|
33
|
+
would = 'would have ' if options['dry-run']
|
35
34
|
puts "#{would}deleted #{r.id}"
|
36
|
-
|
35
|
+
end
|
37
36
|
end
|
38
37
|
|
39
|
-
method_options :
|
40
|
-
desc
|
38
|
+
method_options force: :boolean
|
39
|
+
desc 'version', 'get version of program'
|
41
40
|
def version
|
42
41
|
puts Joplin::VERSION
|
43
42
|
end
|
44
43
|
|
45
|
-
desc
|
46
|
-
long_desc
|
44
|
+
desc 'write', 'write a note'
|
45
|
+
long_desc 'This will write a note in the format of "note title/note title.md and put all resources under the folder'
|
46
|
+
def write(id)
|
47
|
+
note = Joplin::Note.new(id:)
|
48
|
+
note.write
|
49
|
+
end
|
50
|
+
|
51
|
+
desc :nb2n, 'concate all notes in a notebook to one note. Possible PDF export'
|
52
|
+
long_desc 'The idea is to make a big note from all the notes in a notebook. PDF export or whatever export can happen from that. The notes are concatenated with a separator.'
|
47
53
|
option :token
|
48
|
-
option :type, :
|
54
|
+
option :type, type: :string
|
49
55
|
def nb2n(query)
|
50
|
-
Joplin
|
56
|
+
Joplin.token = options[:token] || Joplin::Token.get
|
51
57
|
results = Joplin.search(query, { type: 'folder' })
|
52
|
-
nb = results[0]
|
53
|
-
|
54
|
-
abort "notebook #{query} not found"
|
55
|
-
end
|
58
|
+
nb = results[0]
|
59
|
+
abort "notebook #{query} not found" unless nb and nb['title'] == query
|
56
60
|
|
57
61
|
notebook = Joplin::Notebook.new nb['id']
|
58
62
|
notes = notebook.notes
|
59
63
|
new_note = Joplin::Note.new
|
60
64
|
new_note.title = query
|
61
|
-
new_note.body = notes.map { |n| "\# #{n.title}\n\n#{n.body}" }.join
|
65
|
+
new_note.body = notes.map { |n| "\# #{n.title}\n\n#{n.body}" }.join
|
62
66
|
new_note.save!
|
63
67
|
puts "Saved: #{new_note.title} with id: #{new_note.id}"
|
64
68
|
end
|
65
69
|
|
66
|
-
desc :
|
70
|
+
desc :epub,
|
71
|
+
'build a note from a note (help build), write the note, and create an epub from the result. needs pandoc installed'
|
72
|
+
|
73
|
+
def epub(id)
|
74
|
+
note = build(id)
|
75
|
+
write(note.id)
|
76
|
+
FileUtils.cd note.title
|
77
|
+
`pandoc '#{note.title}.md' -o '../#{note.title}.epub' -t epub3 -f markdown+smart --title '#{note.title}' --toc --toc-depth=3 --metadata title='#{note.title}'`
|
78
|
+
note.delete!
|
79
|
+
FileUtils.cd '..'
|
80
|
+
FileUtils.rm_rf note.title
|
81
|
+
puts "OK. Done. Your book is #{note.title}.epub"
|
82
|
+
end
|
67
83
|
|
68
|
-
|
69
|
-
|
84
|
+
desc :build, 'build a note from a note containing references'
|
85
|
+
|
86
|
+
long_desc %(Takes a note and looks up all the referenced notes and makes a new
|
87
|
+
note from those in the same folder. The notes are concatenated with a separator.\n\nIf you have a
|
70
88
|
line with 'title: a title' then it will be used for the title of the built
|
71
|
-
|
89
|
+
note.)
|
72
90
|
|
73
91
|
def build(id)
|
74
92
|
token
|
75
|
-
note = Joplin::Note.new
|
93
|
+
note = Joplin::Note.new(id:)
|
76
94
|
notes = []
|
77
95
|
title = nil
|
78
|
-
note.body.each_line
|
79
|
-
title =
|
80
|
-
line =~
|
81
|
-
|
82
|
-
|
83
|
-
|
96
|
+
note.body.each_line do |line|
|
97
|
+
title = ::Regexp.last_match(1) if line =~ /title: (.*)$/
|
98
|
+
line =~ %r{\(:/(\w+)\)}
|
99
|
+
begin
|
100
|
+
notes.push Joplin::Note.new id: ::Regexp.last_match(1) if ::Regexp.last_match(1) && ::Regexp.last_match(1)
|
101
|
+
rescue Joplin::Note::NotFound
|
102
|
+
puts "Couldn't find note with id #{id} so we skip it"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
new_note = Joplin::Note.new parent_id: note.parent_id
|
84
106
|
new_note.title = title || "built: #{note.title}"
|
85
|
-
new_note.body = notes.map { |n| "\# #{n.title}\n\n#{n.body}" }.join
|
107
|
+
new_note.body = notes.map { |n| "\# #{n.title}\n\n#{n.body}" }.join
|
86
108
|
new_note.save!
|
87
|
-
|
109
|
+
new_note
|
88
110
|
end
|
89
111
|
|
90
112
|
private
|
91
|
-
|
92
|
-
|
93
|
-
|
113
|
+
|
114
|
+
def token
|
115
|
+
Joplin.token = Joplin.get_token || options[:token]
|
116
|
+
return if Joplin.token
|
117
|
+
|
118
|
+
raise "Couldn't find token in local database and it wasn't passed as an option. You better check yourself!"
|
94
119
|
end
|
95
120
|
end
|
96
121
|
|
data/joplin.gemspec
CHANGED
@@ -1,42 +1,42 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require 'joplin/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'joplin'
|
8
7
|
spec.version = Joplin::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
8
|
+
spec.authors = ['Daniel Bretoi']
|
9
|
+
spec.email = ['daniel@bretoi.com']
|
11
10
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
11
|
+
spec.summary = 'joplin API'
|
12
|
+
spec.description = 'joplin API'
|
13
|
+
spec.homepage = 'http://github.com/danielb2/joplin-ruby'
|
14
|
+
spec.license = 'MIT'
|
16
15
|
|
17
16
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
17
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
18
|
if spec.respond_to?(:metadata)
|
20
|
-
spec.metadata[
|
21
|
-
spec.metadata[
|
22
|
-
spec.metadata[
|
19
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
20
|
+
spec.metadata['source_code_uri'] = 'http://github.com/danielb2/joplin-ruby'
|
21
|
+
spec.metadata['changelog_uri'] = 'http://github.com/danielb2/joplin-ruby'
|
23
22
|
else
|
24
|
-
raise
|
25
|
-
|
23
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
24
|
+
'public gem pushes.'
|
26
25
|
end
|
27
26
|
|
28
27
|
# Specify which files should be added to the gem when it is released.
|
29
28
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
30
|
-
spec.files
|
29
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
31
30
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
32
31
|
end
|
33
|
-
spec.bindir =
|
32
|
+
spec.bindir = 'bin'
|
34
33
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }.reject { |f| f =~ /(console|setup)/ }
|
35
|
-
spec.require_paths = [
|
34
|
+
spec.require_paths = ['lib']
|
36
35
|
|
37
|
-
spec.add_dependency
|
38
|
-
spec.
|
39
|
-
spec.
|
40
|
-
spec.add_development_dependency
|
41
|
-
spec.add_development_dependency
|
36
|
+
spec.add_dependency 'http', '~> 5.1.1'
|
37
|
+
spec.add_dependency 'sqlite3', '~> 1.6.3'
|
38
|
+
spec.add_dependency 'thor', '~> 1.2.2'
|
39
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
40
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
41
|
+
spec.add_development_dependency 'rspec', '~> 3.12.0'
|
42
42
|
end
|
data/lib/joplin/version.rb
CHANGED
data/lib/joplin.rb
CHANGED
@@ -1,37 +1,36 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'joplin/version'
|
2
|
+
require 'http'
|
3
|
+
require 'json'
|
4
4
|
|
5
|
+
# https://joplinapp.org/api/overview/
|
5
6
|
module Joplin
|
6
7
|
class Error < StandardError; end
|
7
8
|
attr_accessor :token
|
9
|
+
|
8
10
|
@@token = nil
|
9
11
|
|
10
|
-
def self.token=
|
12
|
+
def self.token=(token)
|
11
13
|
@@token = token
|
12
14
|
end
|
13
15
|
|
14
16
|
def self.search(query, opts = {})
|
15
|
-
url = "#{Joplin
|
16
|
-
res =
|
17
|
-
|
18
|
-
return parsed
|
17
|
+
url = "#{Joplin.uri}/search/?query=#{query}&token=#{Joplin.token}&type=#{opts[:type]}"
|
18
|
+
res = HTTP.get url
|
19
|
+
JSON.parse res.body
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.get_token
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
return nil
|
27
|
-
end
|
23
|
+
settings = JSON.parse File.read("#{ENV['HOME']}/.config/joplin-desktop/settings.json")
|
24
|
+
settings['api.token']
|
25
|
+
rescue StandardError
|
26
|
+
nil
|
28
27
|
end
|
29
28
|
|
30
29
|
def self.token
|
31
30
|
@@token || get_token
|
32
31
|
end
|
33
32
|
|
34
|
-
def self.uri=
|
33
|
+
def self.uri=(uri)
|
35
34
|
@@uri = uri
|
36
35
|
end
|
37
36
|
|
@@ -39,42 +38,55 @@ module Joplin
|
|
39
38
|
@@uri
|
40
39
|
end
|
41
40
|
|
42
|
-
self.uri =
|
41
|
+
self.uri = 'http://localhost:41184'
|
43
42
|
|
44
43
|
class Resource
|
45
|
-
|
44
|
+
class NotFound < Joplin::Error; end
|
45
|
+
attr_reader :id, :filename, :mime
|
46
46
|
|
47
47
|
def self.all
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
48
|
+
url = "#{Joplin.uri}/resources/?token=#{Joplin.token}&fields=id,filename"
|
49
|
+
response = HTTP.get url
|
50
|
+
|
51
|
+
parsed = JSON.parse res.body
|
52
|
+
throw Error.new(parsed['error']) if response.status != 200
|
53
|
+
parsed.map do |resource|
|
54
|
+
Resource.new resource['id']
|
55
|
+
end
|
57
56
|
end
|
58
57
|
|
59
|
-
def initialize(id
|
58
|
+
def initialize(id)
|
59
|
+
raise Error, 'need id' unless id
|
60
60
|
|
61
|
-
raise Error.new("need id") unless id
|
62
61
|
@id = id
|
63
|
-
url = "#{Joplin
|
64
|
-
|
65
|
-
|
62
|
+
url = "#{Joplin.uri}/resources/#{id}?token=#{Joplin.token}&fields=mime,filename,id"
|
63
|
+
response = HTTP.get url
|
64
|
+
raise NotFound, "No resource found with id: #{id}" if response.code == 404
|
65
|
+
|
66
|
+
resource = @parsed = JSON.parse response.body
|
67
|
+
@filename = resource['filename']
|
68
|
+
@mime = resource['mime']
|
69
|
+
end
|
70
|
+
|
71
|
+
def file
|
72
|
+
url = "#{Joplin.uri}/resources/#{id}/file?token=#{Joplin.token}"
|
73
|
+
response = HTTP.get url
|
74
|
+
throw Error if response.status != 200
|
75
|
+
response.body
|
76
|
+
end
|
77
|
+
|
78
|
+
def write(path = nil)
|
79
|
+
IO.write path || id, file
|
66
80
|
end
|
67
81
|
|
68
82
|
def delete
|
69
|
-
url = "#{Joplin
|
70
|
-
res =
|
83
|
+
url = "#{Joplin.uri}/resources/#{id}?token=#{Joplin.token}"
|
84
|
+
res = HTTP.delete url
|
71
85
|
res.status == 200
|
72
86
|
end
|
73
87
|
|
74
88
|
def to_s
|
75
|
-
|
76
|
-
mime: #{@parsed['mime']}
|
77
|
-
filename: #{@parsed['filename']}"""
|
89
|
+
%(id: #{id}, mime: #{mime} filename: #{filename})
|
78
90
|
end
|
79
91
|
|
80
92
|
def self.orphaned
|
@@ -85,91 +97,116 @@ filename: #{@parsed['filename']}"""
|
|
85
97
|
end
|
86
98
|
|
87
99
|
class Note
|
88
|
-
|
89
|
-
attr_accessor :title
|
90
|
-
attr_reader :id
|
100
|
+
class NotFound < Joplin::Error; end
|
91
101
|
|
92
|
-
|
102
|
+
attr_accessor :body, :title, :parent_id
|
103
|
+
attr_reader :id
|
93
104
|
|
105
|
+
def initialize(id: nil, parent_id: nil)
|
94
106
|
@id = id
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
107
|
+
@parent_id = parent_id
|
108
|
+
return unless id
|
109
|
+
|
110
|
+
url = "#{Joplin.uri}/notes/#{id}?token=#{Joplin.token}&fields=title,body,id,parent_id"
|
111
|
+
parse HTTP.get url
|
99
112
|
end
|
100
113
|
|
101
114
|
def resources
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
115
|
+
url = "#{Joplin.uri}/notes/#{id}/resources?token=#{Joplin.token}&fields=id,filename"
|
116
|
+
response = HTTP.get url
|
117
|
+
raise Error, "#{response}" if response.code != 200
|
118
|
+
|
119
|
+
parsed = JSON.parse response.body
|
120
|
+
parsed['items'].map do |resource_data|
|
121
|
+
id = resource_data['id']
|
122
|
+
Resource.new id
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def prepare_body_for_writing_by_fixing_resources
|
127
|
+
prepared = String(body)
|
128
|
+
prepared.each_line do |line|
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def write
|
133
|
+
Dir.mkdir title
|
134
|
+
Dir.mkdir "#{title}/resources"
|
135
|
+
body_to_write = String(body) # make a copy
|
136
|
+
resources.each do |resource|
|
137
|
+
resource.write "#{title}/resources/#{resource.id}"
|
138
|
+
body_to_write.gsub!(%r{:/#{resource.id}}, "./resources/#{resource.id}")
|
139
|
+
end
|
140
|
+
IO.write "#{title}/#{title}.md", body_to_write
|
109
141
|
end
|
110
142
|
|
111
|
-
def to_json
|
143
|
+
def to_json(*_args)
|
112
144
|
{
|
113
|
-
title
|
114
|
-
body
|
145
|
+
title:,
|
146
|
+
body:,
|
147
|
+
parent_id:
|
115
148
|
}.to_json
|
116
149
|
end
|
117
150
|
|
118
151
|
def save!
|
119
152
|
if @id
|
120
|
-
url = "#{Joplin
|
121
|
-
response =
|
153
|
+
url = "#{Joplin.uri}/notes/#{@id}?token=#{Joplin.token}"
|
154
|
+
response = HTTP.put url, body: to_json
|
122
155
|
return response.status == 200
|
123
156
|
end
|
124
157
|
|
125
|
-
|
126
|
-
|
158
|
+
url = "#{Joplin.uri}/notes/?token=#{Joplin.token}"
|
159
|
+
parse HTTP.post url, body: to_json
|
127
160
|
end
|
128
161
|
|
129
162
|
def to_s
|
130
|
-
|
131
|
-
title: #{self.title}
|
132
|
-
body: #{self.body}"""
|
163
|
+
%(id: #{id} title: #{title} parent_id: #{parent_id} body: #{body})
|
133
164
|
end
|
134
165
|
|
135
166
|
def self.all
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
167
|
+
url = "#{Joplin.uri}/notes/?token=#{Joplin.token}&fields=id"
|
168
|
+
res = HTTP.get url
|
169
|
+
parsed = JSON.parse res.body
|
170
|
+
parsed.map do |note|
|
171
|
+
Note.new note['id']
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def delete!
|
176
|
+
url = "#{Joplin.uri}/notes/#{@id}?token=#{Joplin.token}"
|
177
|
+
response = HTTP.delete url
|
178
|
+
response.status == 200
|
142
179
|
end
|
143
180
|
|
144
181
|
private
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
182
|
+
|
183
|
+
def parse(response)
|
184
|
+
raise "No note found with id #{@id}" if response.body.empty?
|
185
|
+
|
149
186
|
note = JSON.parse response.body
|
150
|
-
if response.
|
151
|
-
|
152
|
-
|
187
|
+
raise NotFound, "No note found with id: #{id}" if response.code == 404
|
188
|
+
raise Error, "#{note['error']}\nid: #{id}" if response.code != 200
|
189
|
+
|
153
190
|
@body = note['body']
|
154
191
|
@title = note['title']
|
155
|
-
@id = note[
|
192
|
+
@id = note['id']
|
193
|
+
@parent_id = note['parent_id']
|
156
194
|
end
|
157
195
|
end
|
158
196
|
|
159
197
|
class Notebook
|
160
|
-
def initialize(id=nil)
|
161
|
-
|
198
|
+
def initialize(id = nil)
|
162
199
|
@id = id
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
200
|
+
return unless id
|
201
|
+
|
202
|
+
url = "#{Joplin.uri}/folders/#{id}?token=#{Joplin.token}"
|
203
|
+
res = HTTP.get url
|
204
|
+
parsed = JSON.parse res.body
|
168
205
|
end
|
169
206
|
|
170
207
|
def notes
|
171
|
-
url = "#{Joplin
|
172
|
-
res =
|
208
|
+
url = "#{Joplin.uri}/folders/#{@id}/notes?token=#{Joplin.token}"
|
209
|
+
res = HTTP.get url
|
173
210
|
notes = JSON.parse res.body
|
174
211
|
notes.map! { |n| Joplin::Note.new n['id'] }
|
175
212
|
end
|
data/{README.md → readme.md}
RENAMED
@@ -19,7 +19,7 @@ end
|
|
19
19
|
|
20
20
|
updating a note
|
21
21
|
```ruby
|
22
|
-
note = Joplin::Note.new "6e3811c7a73148a" # note id can be found in the information of any note
|
22
|
+
note = Joplin::Note.new id: "6e3811c7a73148a" # note id can be found in the information of any note
|
23
23
|
note.title = "a new note title"
|
24
24
|
note.save!
|
25
25
|
```
|
@@ -35,6 +35,13 @@ token = Joplin::Token.get
|
|
35
35
|
|
36
36
|
to get the token programatically. It reads from the sqlite database located in `~/.config/joplin-desktop`
|
37
37
|
|
38
|
+
### Saving to a specific notebook
|
39
|
+
|
40
|
+
You can specify the id of the notebook
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
note = Joplin::Note.new parent_id: 'c5e6827be8c946c78210d3508cce7ea6'
|
44
|
+
```
|
38
45
|
|
39
46
|
## CLI
|
40
47
|
|
@@ -43,3 +50,9 @@ to get the token programatically. It reads from the sqlite database located in `
|
|
43
50
|
Will take a notebook and concatenate all notes into one for easy export to PDF
|
44
51
|
|
45
52
|
The token argument is optional and if you have it installed locally it will find the token
|
53
|
+
|
54
|
+
### joplin epub <id of note>
|
55
|
+
|
56
|
+
This will generate an epub from the referenced notes in the note. It will not
|
57
|
+
include the actual note, but only linked markdown notes within. Rendering
|
58
|
+
things like tables, mermaid diagrams etc is not supported
|
metadata
CHANGED
@@ -1,85 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: joplin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Bretoi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: http
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.1.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 5.1.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: sqlite3
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
type: :
|
33
|
+
version: 1.6.3
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.6.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: thor
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 1.2.2
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '2.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '13.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '13.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
89
|
+
version: 3.12.0
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
96
|
+
version: 3.12.0
|
83
97
|
description: joplin API
|
84
98
|
email:
|
85
99
|
- daniel@bretoi.com
|
@@ -95,7 +109,6 @@ files:
|
|
95
109
|
- Gemfile.lock
|
96
110
|
- LICENSE.txt
|
97
111
|
- Makefile
|
98
|
-
- README.md
|
99
112
|
- Rakefile
|
100
113
|
- bin/console
|
101
114
|
- bin/joplin
|
@@ -103,6 +116,7 @@ files:
|
|
103
116
|
- joplin.gemspec
|
104
117
|
- lib/joplin.rb
|
105
118
|
- lib/joplin/version.rb
|
119
|
+
- readme.md
|
106
120
|
homepage: http://github.com/danielb2/joplin-ruby
|
107
121
|
licenses:
|
108
122
|
- MIT
|
@@ -125,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
139
|
- !ruby/object:Gem::Version
|
126
140
|
version: '0'
|
127
141
|
requirements: []
|
128
|
-
rubygems_version: 3.
|
142
|
+
rubygems_version: 3.4.10
|
129
143
|
signing_key:
|
130
144
|
specification_version: 4
|
131
145
|
summary: joplin API
|