Blux 0.0.3

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.
@@ -0,0 +1,15 @@
1
+ COPYING
2
+ Manifest
3
+ README.markdown
4
+ Rakefile
5
+ bin/blux
6
+ bin/blux_textile_to_html
7
+ bin/blux_wp_publish
8
+ lib/blog_manager.rb
9
+ lib/blux_config_reader.rb
10
+ lib/blux_option_parser.rb
11
+ lib/draft_manager.rb
12
+ lib/indexer.rb
13
+ spec/blog_manager_spec.rb
14
+ spec/blux_config_reader_spec.rb
15
+ spec/draft_manager_spec.rb
@@ -0,0 +1,81 @@
1
+ # Blux
2
+ Blux is an offline blog manager that lets you manage your blog posts offline and publish them to any blog engine that supports AtomPub.
3
+
4
+ ## install
5
+ gem install Blux
6
+
7
+ That's it!
8
+
9
+ ## configuration
10
+ Blux reads its configuration info from ~/.bluxrc. The first time you run blux, it will create this file for you, but will immediately complain about missing configuration items. Use the following configuration example for a Wordpress blog and edit each line as needed:
11
+
12
+ editor: vim
13
+ html_converter: blux_textile_to_html
14
+
15
+ blog: myWordpressBlog
16
+ author_name: Mr. Author
17
+ user_name: my_user_id
18
+ password: my_password
19
+
20
+ **editor:** this is the shell command that will be executed to launch your editor of choice
21
+
22
+ **html_converter:** Blux will use this shell command to convert your blog draft to html. In the example above, Blux will use the blux_textile_to_html script, which is included with this application. The script will transform your post, written in the textile markup language, and convert it to html.
23
+
24
+ **blog:** this is your Wordpress blog ID
25
+
26
+ **author_name:** the name of the author
27
+
28
+ **user_name:** your Wordpress user name that Blux will use to publish your posts
29
+
30
+ **password:** your Wordpress password
31
+
32
+ ## Blux from command line
33
+
34
+ Blux is a command line tool that currently operates without a GUI of any sort. Here are a few of the commands you can use:
35
+
36
+ > $ blux -n (--new)
37
+
38
+ this command launches your text editor. As soon as you quit the editor, it will create a draft in the Blux draft folder in ~/.blux/draft
39
+
40
+ > $ blux -s (--set) --latest title "a title"
41
+
42
+ this command sets a title on the latest created draft
43
+
44
+ > $ blux -s -f draft1.23 title "a title"
45
+
46
+ the -f <filename> option can be used to tell Blux to operate on a specific draft by use the draft's filename (without the path)
47
+
48
+ > $ blux -s --title "old title" title "new title"
49
+
50
+ use --title <title> to tell Blux to operate on a draft with a specific title. In this case, blux will change the title of the "old title" draft to "new title"
51
+
52
+ > $ blux -l (--list)
53
+
54
+ this command will list all your drafts, showing each draft by filename
55
+
56
+ > $ blux -l --with-preview
57
+
58
+ use --with-preview when you want to show a small snippet of each draft during the listing
59
+
60
+ > $ blux -l --details -f draft1.23
61
+
62
+ user --details to see each draft filename followed by the drafts attributes in JSON format when listing
63
+
64
+ > $ blux -o (--out) -f draft1.23
65
+
66
+ this command will output the content of your draft to stdin
67
+
68
+ > $ blux -c (--convert) --latest
69
+
70
+ this command will invoke the specified converter to convert your post to html
71
+
72
+ > $ blux -e (--edit) --title "title 1"
73
+
74
+ use this command to edit a draft
75
+
76
+ > $ blux -e -f draft1.23 --verbose
77
+
78
+ when using the --verbose option, Blux will output a lot of extra information to the screen as it works
79
+
80
+ ## community
81
+ feel free to post your comments or questions to the Blux Google group here: blux_manager@googlegroups.com
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('Blux', '0.0.3') do |p|
6
+ p.description = 'An offline blog manager'
7
+ p.url = 'http://github.com/louissalin/blux'
8
+ p.author = 'Louis Salin'
9
+ p.email = 'louis.phil@gmail.com'
10
+ p.ignore_pattern = ["tags", "TODO", "plan", "gem-public_cert.pem"]
11
+ p.development_dependencies = ["OptionParser >=0.5.1",
12
+ "atom-tools >=2.0.5",
13
+ "json >=1.4.6",
14
+ "RedCloth >=4.2.3"]
15
+ p.runtime_dependencies = ["OptionParser >=0.5.1",
16
+ "atom-tools >=2.0.5",
17
+ "json >=1.4.6",
18
+ "RedCloth >=4.2.3"]
19
+ end
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright 2010 Louis-Philippe Salin de l'Etoile, aka Louis Salin
4
+ # email: louis.phil@gmail.com
5
+ #
6
+ # This file is part of Blux.
7
+ #
8
+ # Blux is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Blux is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with Blux. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ require "#{File.dirname(__FILE__)}/../lib/blux_option_parser.rb"
22
+ require "#{File.dirname(__FILE__)}/../lib/blog_manager.rb"
23
+
24
+ def validate_command(options)
25
+ if (options.command != nil)
26
+ yield options
27
+ else
28
+ STDERR << "No command specified. Use -h for a list of possible commands\n"
29
+ end
30
+ end
31
+
32
+ def validate_set_options(options)
33
+ if options.attributes.length.modulo(2) == 0
34
+ yield options.attributes[0], options.attributes[1]
35
+ else
36
+ STDERR << "Attribute error: you must specify an attribute name and a value."
37
+ end
38
+ end
39
+
40
+ def check_filename(options, blog_manager)
41
+ filename = blog_manager.draft_manager.get_latest_created_draft if options.use_latest
42
+ filename = blog_manager.draft_manager.get_draft_by_title(options.title) if options.use_title
43
+ filename = options.filename || filename
44
+
45
+ puts "check_filename: #{filename}" if options.verbose
46
+ if filename != nil
47
+ yield filename
48
+ else
49
+ STDERR << "Please specify the draft file you want to work with. If you want to work with the latest created/edited draft, use the --latest option. You can also tell blux to get a draft with a specific title with --title."
50
+ end
51
+ end
52
+
53
+ validate_command(BluxOptionParser.parse(ARGV)) do |options|
54
+ puts "#{options}" if options.verbose
55
+
56
+ draft_manager = DraftManager.new
57
+ mgr = BlogManager.new(draft_manager, :verbose => options.verbose)
58
+ mgr.load_config
59
+ mgr.start
60
+
61
+ case options.command
62
+ when :new
63
+ mgr.draft_manager.create_draft
64
+ when :edit
65
+ check_filename(options, mgr) do |filename|
66
+ mgr.draft_manager.edit_draft filename
67
+ end
68
+ when :list
69
+ mgr.draft_manager.list.each do |item|
70
+ break if options.filename != nil && options.filename != item
71
+ puts "#{item}"
72
+ puts " #{mgr.draft_manager.show_info(item)}" if options.list_details
73
+ puts " #{mgr.draft_manager.show_preview(item)}" if options.list_preview
74
+ end
75
+ when :set
76
+ check_filename(options, mgr) do |filename|
77
+ validate_set_options(options) do |attribute, value|
78
+ mgr.draft_manager.set_attribute(filename, attribute, value)
79
+ end
80
+ end
81
+ when :out
82
+ check_filename(options, mgr) do |filename|
83
+ STDOUT.puts(mgr.draft_manager.output filename)
84
+ end
85
+ when :convert
86
+ check_filename(options, mgr) do |filename|
87
+ system "blux --out -f #{filename} | #{mgr.config.html_converter_cmd}"
88
+ end
89
+ when :publish
90
+ check_filename(options, mgr) do |filename|
91
+ puts "publishing" if options.verbose
92
+ mgr.publish filename
93
+ end
94
+ when :update
95
+ check_filename(options, mgr) do |filename|
96
+ puts "updating" if options.verbose
97
+ mgr.update filename
98
+ end
99
+ when :set_edit_url
100
+ check_filename(options, mgr) do |filename|
101
+ ARGF.each do |url|
102
+ mgr.set_attribute(filename, 'edit_url', url.strip)
103
+ end
104
+ end
105
+ end
106
+ end
107
+
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright 2010 Louis-Philippe Salin de l'Etoile, aka Louis Salin
4
+ # email: louis.phil@gmail.com
5
+ #
6
+ # This file is part of Blux.
7
+ #
8
+ # Blux is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Blux is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with Blux. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ require 'redcloth'
22
+
23
+ ARGF.each do |line|
24
+ STDOUT.puts RedCloth.new(line).to_html
25
+ end
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+ ## Copyright (c) 2007 John Mettraux
3
+ ## Released under the MIT license
4
+ ## http://www.opensource.org/licenses/mit-license.php
5
+ ##
6
+ ## Modifications by Louis Salin, October 2010
7
+ ## => reading blog information from the configuration file
8
+
9
+ require 'optparse'
10
+ require 'net/http'
11
+ require 'atom/entry' # sudo gem install atom-tools
12
+ require 'atom/collection'
13
+ require "#{File.dirname(__FILE__)}/../lib/blux_config_reader"
14
+
15
+
16
+ #
17
+ # parse options
18
+
19
+ tags = []
20
+ title = nil
21
+ type = 'html'
22
+ bluxrc = nil
23
+ command = :post
24
+ entry_id = nil
25
+
26
+ opts = OptionParser.new
27
+ opts.banner = "Usage: post.rb [options]"
28
+ opts.separator ""
29
+ opts.separator "options :"
30
+
31
+ opts.on(
32
+ "-c",
33
+ "--categories {list}",
34
+ "comma separated list of tags/categories") do |v|
35
+
36
+ tags = v.split ","
37
+ end
38
+
39
+ opts.on(
40
+ "-t",
41
+ "--title {title}",
42
+ "title for the post") do |v|
43
+
44
+ title = v
45
+ end
46
+
47
+ opts.on(
48
+ "-T",
49
+ "--type {html|xhtml|text}",
50
+ "type of the content. ('html' is the default).") do |v|
51
+
52
+ type = v
53
+ end
54
+
55
+ opts.on(
56
+ "--config {config_file}",
57
+ "blux config file path") do |f|
58
+ bluxrc = f
59
+ end
60
+
61
+ opts.on(
62
+ "--update {entry_id}",
63
+ "update an existing post") do |id|
64
+ command = :put
65
+ entry_id = id
66
+ end
67
+
68
+ opts.on(
69
+ "-h",
70
+ "--help",
71
+ "displays this help") do
72
+
73
+ puts
74
+ puts opts.to_s
75
+ puts
76
+ exit 0
77
+ end
78
+
79
+ opts.parse ARGV
80
+
81
+ raise "please specify a title for the post with the -t option" unless title
82
+
83
+ # a great thanks to the devs of all the libs used here
84
+ #
85
+ # some info about you and your blog
86
+
87
+ config = BluxConfigurationReader.new
88
+ config.load_config bluxrc
89
+
90
+ blog = config.blog
91
+ authorname = config.author_name
92
+ username = config.user_name
93
+ password = config.password
94
+
95
+ bloguri = "http://#{blog}.wordpress.com"
96
+ base = "https://#{blog}.wordpress.com/wp-app.php"
97
+
98
+ #
99
+ # gather content
100
+
101
+ content = ""
102
+ loop do
103
+ line = STDIN.gets
104
+ break unless line
105
+ content += line
106
+ end
107
+
108
+ # create entry
109
+
110
+ entry = Atom::Entry.new
111
+ entry.title = title
112
+ entry.updated!
113
+
114
+ author = Atom::Author.new
115
+ author.name = authorname
116
+ author.uri = bloguri
117
+ entry.authors << author
118
+
119
+ tags.each do |t|
120
+ c = Atom::Category.new
121
+ c["scheme"] = bloguri
122
+ c["term"] = t.strip
123
+ entry.categories << c
124
+ end
125
+
126
+ entry.content = content
127
+ entry.content["type"] = type if type
128
+
129
+ h = Atom::HTTP.new
130
+ h.user = username
131
+ h.pass = password
132
+ h.always_auth = :basic
133
+
134
+ c = Atom::Collection.new(base + "/posts", h)
135
+ if command == :post
136
+ res = c.post! entry
137
+ puts Atom::Entry.parse(res.read_body).edit_url
138
+ elsif command == :put
139
+ entry.edit_url = entry_id
140
+ res = c.put! entry
141
+ end
142
+
@@ -0,0 +1,99 @@
1
+ #
2
+ # Copyright 2010 Louis-Philippe Salin de l'Etoile, aka Louis Salin
3
+ # email: louis.phil@gmail.com
4
+ #
5
+ # This file is part of Blux.
6
+ #
7
+ # Blux is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # Blux is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Blux. If not, see <http://www.gnu.org/licenses/>.
19
+ require "#{File.dirname(__FILE__)}/draft_manager"
20
+ require "#{File.dirname(__FILE__)}/blux_config_reader"
21
+ require "#{File.dirname(__FILE__)}/indexer"
22
+
23
+ class BlogManager
24
+ attr_accessor :home, :blux_dir, :blux_rc, :blux_tmp_dir, :draft_dir
25
+ attr_accessor :draft_manager
26
+ attr_accessor :config
27
+ attr_accessor :index
28
+ attr_accessor :index_file
29
+
30
+ include BluxIndexer
31
+
32
+ def initialize(draft_manager, options = {})
33
+ @options = options
34
+ @verbose = options[:verbose] ||= false
35
+
36
+ @home = ENV['HOME']
37
+ @blux_dir = "#{@home}/.blux"
38
+ @draft_dir = "#{@blux_dir}/draft"
39
+ @blux_tmp_dir = "#{@blux_dir}/tmp"
40
+ @blux_rc = "#{@home}/.bluxrc"
41
+ @index_file = "#{@blux_dir}/.published"
42
+
43
+ @draft_manager = draft_manager
44
+ end
45
+
46
+ def start
47
+ unless Dir.exists?(@blux_dir)
48
+ puts "creating #{@blux_dir}\n" if @verbose
49
+ Dir.mkdir(@blux_dir)
50
+ end
51
+
52
+ unless Dir.exists?(@draft_dir)
53
+ puts "creating #{@draft_dir}\n" if @verbose
54
+ Dir.mkdir(@draft_dir)
55
+ end
56
+
57
+ unless Dir.exists?(@blux_tmp_dir)
58
+ puts "creating #{@blux_tmp_dir}\n" if @verbose
59
+ Dir.mkdir(@blux_tmp_dir)
60
+ end
61
+
62
+ load_index
63
+ end
64
+
65
+ def load_config
66
+ @config = BluxConfigurationReader.new
67
+ @config.load_config @blux_rc, @verbose
68
+
69
+ @draft_manager.setup(@config.launch_editor_cmd, @blux_tmp_dir, @draft_dir, @options)
70
+ end
71
+
72
+ def publish(filename)
73
+ title = @draft_manager.get_attribute(filename, "title") || 'no title'
74
+
75
+ cmd = "blux --convert -f #{filename} | blux_wp_publish -t #{title} --config #{@blux_rc} | blux --set_edit_url -f #{filename}"
76
+ cmd = cmd + " --verbose" if @verbose
77
+
78
+ puts cmd if @verbose
79
+ system cmd
80
+
81
+ load_index
82
+ set_attribute(filename, :published_time, Time.now)
83
+ end
84
+
85
+ def update(filename)
86
+ title = @draft_manager.get_attribute(filename, "title") || 'no title'
87
+ url = get_attribute(filename, "edit_url")
88
+
89
+ raise "couldn't find an edit url for the draft: #{filename}" unless url
90
+
91
+ cmd = "blux --convert -f #{filename} | blux_wp_publish.rb -t #{title} --update #{url} --config #{@blux_rc}"
92
+
93
+ puts cmd if @verbose
94
+ system cmd
95
+
96
+ set_attribute(filename, :published_time, Time.now)
97
+ end
98
+
99
+ end