Blux 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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