jekyll-import 0.1.0.beta1

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,73 @@
1
+ require 'rubygems'
2
+ require 'sequel'
3
+ require 'fileutils'
4
+ require 'yaml'
5
+
6
+ # NOTE: This converter requires Sequel and the MySQL gems.
7
+ # The MySQL gem can be difficult to install on OS X. Once you have MySQL
8
+ # installed, running the following commands should work:
9
+ # $ sudo gem install sequel
10
+ # $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
11
+
12
+ module JekyllImport
13
+ module Drupal7
14
+ # Reads a MySQL database via Sequel and creates a post file for each post
15
+ # in wp_posts that has post_status = 'publish'. This restriction is made
16
+ # because 'draft' posts are not guaranteed to have valid dates.
17
+ QUERY = "SELECT n.nid, \
18
+ n.title, \
19
+ fdb.body_value, \
20
+ n.created, \
21
+ n.status \
22
+ FROM node AS n, \
23
+ field_data_body AS fdb \
24
+ WHERE (n.type = 'blog' OR n.type = 'story') \
25
+ AND n.vid = fdb.entity_id"
26
+
27
+ def self.process(dbname, user, pass, host = 'localhost', prefix = '')
28
+ db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8')
29
+
30
+ if prefix != ''
31
+ QUERY[" node "] = " " + prefix + "node "
32
+ QUERY[" field_data_body "] = " " + prefix + "field_data_body "
33
+ end
34
+
35
+ FileUtils.mkdir_p "_posts"
36
+ FileUtils.mkdir_p "_drafts"
37
+
38
+ db[QUERY].each do |post|
39
+ # Get required fields and construct Jekyll compatible name
40
+ node_id = post[:nid]
41
+ title = post[:title]
42
+ content = post[:body_value]
43
+ created = post[:created]
44
+ time = Time.at(created)
45
+ is_published = post[:status] == 1
46
+ dir = is_published ? "_posts" : "_drafts"
47
+ slug = title.strip.downcase.gsub(/(&|&)/, ' and ').gsub(/[\s\.\/\\]/, '-').gsub(/[^\w-]/, '').gsub(/[-_]{2,}/, '-').gsub(/^[-_]/, '').gsub(/[-_]$/, '')
48
+ name = time.strftime("%Y-%m-%d-") + slug + '.md'
49
+
50
+ # Get the relevant fields as a hash, delete empty fields and convert
51
+ # to YAML for the header
52
+ data = {
53
+ 'layout' => 'default',
54
+ 'title' => title.to_s,
55
+ 'created' => created,
56
+ }.delete_if { |k,v| v.nil? || v == ''}.to_yaml
57
+
58
+ # Write out the data and content to file
59
+ File.open("#{dir}/#{name}", "w") do |f|
60
+ f.puts data
61
+ f.puts "---"
62
+ f.puts content
63
+ end
64
+
65
+ end
66
+
67
+ # TODO: Make dirs & files for nodes of type 'page'
68
+ # Make refresh pages for these as well
69
+
70
+ # TODO: Make refresh dirs & files according to entries in url_alias table
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,49 @@
1
+ # Adapted by Rodrigo Pinto <rodrigopqn@gmail.com>
2
+ # Based on typo.rb by Toby DiPasquale
3
+
4
+ require 'fileutils'
5
+ require 'rubygems'
6
+ require 'sequel'
7
+
8
+ module JekyllImport
9
+ module Enki
10
+ SQL = <<-EOS
11
+ SELECT p.id,
12
+ p.title,
13
+ p.slug,
14
+ p.body,
15
+ p.published_at as date,
16
+ p.cached_tag_list as tags
17
+ FROM posts p
18
+ EOS
19
+
20
+ # Just working with postgres, but can be easily adapted
21
+ # to work with both mysql and postgres.
22
+ def self.process(dbname, user, pass, host = 'localhost')
23
+ FileUtils.mkdir_p('_posts')
24
+ db = Sequel.postgres(:database => dbname,
25
+ :user => user,
26
+ :password => pass,
27
+ :host => host,
28
+ :encoding => 'utf8')
29
+
30
+ db[SQL].each do |post|
31
+ name = [ sprintf("%.04d", post[:date].year),
32
+ sprintf("%.02d", post[:date].month),
33
+ sprintf("%.02d", post[:date].day),
34
+ post[:slug].strip ].join('-')
35
+ name += '.textile'
36
+
37
+ File.open("_posts/#{name}", 'w') do |f|
38
+ f.puts({ 'layout' => 'post',
39
+ 'title' => post[:title].to_s,
40
+ 'enki_id' => post[:id],
41
+ 'categories' => post[:tags]
42
+ }.delete_if { |k, v| v.nil? || v == '' }.to_yaml)
43
+ f.puts '---'
44
+ f.puts post[:body].delete("\r")
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'sequel'
3
+ require 'fileutils'
4
+ require 'safe_yaml'
5
+
6
+ # NOTE: This migrator is made for Joomla 1.5 databases.
7
+ # NOTE: This converter requires Sequel and the MySQL gems.
8
+ # The MySQL gem can be difficult to install on OS X. Once you have MySQL
9
+ # installed, running the following commands should work:
10
+ # $ sudo gem install sequel
11
+ # $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
12
+
13
+ module JekyllImport
14
+ module Joomla
15
+ def self.process(dbname, user, pass, host = 'localhost', table_prefix = 'jos_', section = '1')
16
+ db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8')
17
+
18
+ FileUtils.mkdir_p("_posts")
19
+
20
+ # Reads a MySQL database via Sequel and creates a post file for each
21
+ # post in wp_posts that has post_status = 'publish'. This restriction is
22
+ # made because 'draft' posts are not guaranteed to have valid dates.
23
+ query = "SELECT `title`, `alias`, CONCAT(`introtext`,`fulltext`) as content, `created`, `id` FROM #{table_prefix}content WHERE state = '0' OR state = '1' AND sectionid = '#{section}'"
24
+
25
+ db[query].each do |post|
26
+ # Get required fields and construct Jekyll compatible name.
27
+ title = post[:title]
28
+ slug = post[:alias]
29
+ date = post[:created]
30
+ content = post[:content]
31
+ name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, date.day,
32
+ slug]
33
+
34
+ # Get the relevant fields as a hash, delete empty fields and convert
35
+ # to YAML for the header.
36
+ data = {
37
+ 'layout' => 'post',
38
+ 'title' => title.to_s,
39
+ 'joomla_id' => post[:id],
40
+ 'joomla_url' => post[:alias],
41
+ 'date' => date
42
+ }.delete_if { |k,v| v.nil? || v == '' }.to_yaml
43
+
44
+ # Write out the data and content to file
45
+ File.open("_posts/#{name}", "w") do |f|
46
+ f.puts data
47
+ f.puts "---"
48
+ f.puts content
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,52 @@
1
+ require 'safe_yaml'
2
+ require 'fileutils'
3
+
4
+ module JekyllImport
5
+ module Marley
6
+ def self.regexp
7
+ { :id => /^\d{0,4}-{0,1}(.*)$/,
8
+ :title => /^#\s*(.*)\s+$/,
9
+ :title_with_date => /^#\s*(.*)\s+\(([0-9\/]+)\)$/,
10
+ :published_on => /.*\s+\(([0-9\/]+)\)$/,
11
+ :perex => /^([^\#\n]+\n)$/,
12
+ :meta => /^\{\{\n(.*)\}\}\n$/mi # Multiline Regexp
13
+ }
14
+ end
15
+
16
+ def self.process(marley_data_dir)
17
+ raise ArgumentError, "marley dir #{marley_data_dir} not found" unless File.directory?(marley_data_dir)
18
+
19
+ FileUtils.mkdir_p "_posts"
20
+
21
+ posts = 0
22
+ Dir["#{marley_data_dir}/**/*.txt"].each do |f|
23
+ next unless File.exists?(f)
24
+
25
+ #copied over from marley's app/lib/post.rb
26
+ file_content = File.read(f)
27
+ meta_content = file_content.slice!( self.regexp[:meta] )
28
+ body = file_content.sub( self.regexp[:title], '').sub( self.regexp[:perex], '').strip
29
+
30
+ title = file_content.scan( self.regexp[:title] ).first.to_s.strip
31
+ prerex = file_content.scan( self.regexp[:perex] ).first.to_s.strip
32
+ published_on = DateTime.parse( post[:published_on] ) rescue File.mtime( File.dirname(f) )
33
+ meta = ( meta_content ) ? YAML::load( meta_content.scan( self.regexp[:meta]).to_s ) : {}
34
+ meta['title'] = title
35
+ meta['layout'] = 'post'
36
+
37
+ formatted_date = published_on.strftime('%Y-%m-%d')
38
+ post_name = File.dirname(f).split(%r{/}).last.gsub(/\A\d+-/, '')
39
+
40
+ name = "#{formatted_date}-#{post_name}"
41
+ File.open("_posts/#{name}.markdown", "w") do |f|
42
+ f.puts meta.to_yaml
43
+ f.puts "---\n"
44
+ f.puts "\n#{prerex}\n\n" if prerex
45
+ f.puts body
46
+ end
47
+ posts += 1
48
+ end
49
+ "Created #{posts} posts!"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,84 @@
1
+ # Quickly hacked together my Michael Ivey
2
+ # Based on mt.rb by Nick Gerakines, open source and publically
3
+ # available under the MIT license. Use this module at your own risk.
4
+
5
+ require 'rubygems'
6
+ require 'sequel'
7
+ require 'fastercsv'
8
+ require 'fileutils'
9
+ require File.join(File.dirname(__FILE__),"csv.rb")
10
+
11
+ # NOTE: This converter requires Sequel and the MySQL gems.
12
+ # The MySQL gem can be difficult to install on OS X. Once you have MySQL
13
+ # installed, running the following commands should work:
14
+ # $ sudo gem install sequel
15
+ # $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
16
+
17
+ module JekyllImport
18
+ module Mephisto
19
+ #Accepts a hash with database config variables, exports mephisto posts into a csv
20
+ #export PGPASSWORD if you must
21
+ def self.postgres(c)
22
+ sql = <<-SQL
23
+ BEGIN;
24
+ CREATE TEMP TABLE jekyll AS
25
+ SELECT title, permalink, body, published_at, filter FROM contents
26
+ WHERE user_id = 1 AND type = 'Article' ORDER BY published_at;
27
+ COPY jekyll TO STDOUT WITH CSV HEADER;
28
+ ROLLBACK;
29
+ SQL
30
+ command = %Q(psql -h #{c[:host] || "localhost"} -c "#{sql.strip}" #{c[:database]} #{c[:username]} -o #{c[:filename] || "posts.csv"})
31
+ puts command
32
+ `#{command}`
33
+ CSV.process
34
+ end
35
+
36
+ # This query will pull blog posts from all entries across all blogs. If
37
+ # you've got unpublished, deleted or otherwise hidden posts please sift
38
+ # through the created posts to make sure nothing is accidently published.
39
+ QUERY = "SELECT id, \
40
+ permalink, \
41
+ body, \
42
+ published_at, \
43
+ title \
44
+ FROM contents \
45
+ WHERE user_id = 1 AND \
46
+ type = 'Article' AND \
47
+ published_at IS NOT NULL \
48
+ ORDER BY published_at"
49
+
50
+ def self.process(dbname, user, pass, host = 'localhost')
51
+ db = Sequel.mysql(dbname, :user => user,
52
+ :password => pass,
53
+ :host => host,
54
+ :encoding => 'utf8')
55
+
56
+ FileUtils.mkdir_p "_posts"
57
+
58
+ db[QUERY].each do |post|
59
+ title = post[:title]
60
+ slug = post[:permalink]
61
+ date = post[:published_at]
62
+ content = post[:body]
63
+
64
+ # Ideally, this script would determine the post format (markdown,
65
+ # html, etc) and create files with proper extensions. At this point
66
+ # it just assumes that markdown will be acceptable.
67
+ name = [date.year, date.month, date.day, slug].join('-') + ".markdown"
68
+
69
+ data = {
70
+ 'layout' => 'post',
71
+ 'title' => title.to_s,
72
+ 'mt_id' => post[:entry_id],
73
+ }.delete_if { |k,v| v.nil? || v == ''}.to_yaml
74
+
75
+ File.open("_posts/#{name}", "w") do |f|
76
+ f.puts data
77
+ f.puts "---"
78
+ f.puts content
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,142 @@
1
+ # Created by Nick Gerakines, open source and publically available under the
2
+ # MIT license. Use this module at your own risk.
3
+ # I'm an Erlang/Perl/C++ guy so please forgive my dirty ruby.
4
+
5
+ require 'rubygems'
6
+ require 'sequel'
7
+ require 'fileutils'
8
+ require 'safe_yaml'
9
+
10
+ # NOTE: This converter requires Sequel and the MySQL gems.
11
+ # The MySQL gem can be difficult to install on OS X. Once you have MySQL
12
+ # installed, running the following commands should work:
13
+ # $ sudo gem install sequel
14
+ # $ sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
15
+
16
+ module JekyllImport
17
+ module MT
18
+
19
+ STATUS_DRAFT = 1
20
+ STATUS_PUBLISHED = 2
21
+ MORE_CONTENT_SEPARATOR = '<!--more-->'
22
+
23
+ def self.default_options
24
+ {
25
+ :blog_id => nil,
26
+ :categories => true,
27
+ :dest_encoding => 'utf-8',
28
+ :src_encoding => 'utf-8'
29
+ }
30
+ end
31
+
32
+ # By default this migrator will include posts for all your MovableType blogs.
33
+ # Specify a single blog by providing blog_id.
34
+
35
+ # Main migrator function. Call this to perform the migration.
36
+ #
37
+ # dbname:: The name of the database
38
+ # user:: The database user name
39
+ # pass:: The database user's password
40
+ # host:: The address of the MySQL database host. Default: 'localhost'
41
+ # options:: A hash of configuration options
42
+ #
43
+ # Supported options are:
44
+ #
45
+ # :blog_id:: Specify a single MovableType blog to export by providing blog_id.
46
+ # Default: nil, importer will include posts for all blogs.
47
+ # :categories:: If true, save the post's categories in its
48
+ # YAML front matter. Default: true
49
+ # :src_encoding:: Encoding of strings from the database. Default: UTF-8
50
+ # If your output contains mangled characters, set src_encoding to
51
+ # something appropriate for your database charset.
52
+ # :dest_encoding:: Encoding of output strings. Default: UTF-8
53
+ def self.process(dbname, user, pass, host = 'localhost', options = {})
54
+ options = default_options.merge(options)
55
+
56
+ db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host)
57
+ post_categories = db[:mt_placement].join(:mt_category, :category_id => :placement_category_id)
58
+
59
+ FileUtils.mkdir_p "_posts"
60
+
61
+ posts = db[:mt_entry]
62
+ posts = posts.filter(:entry_blog_id => options[:blog_id]) if options[:blog_id]
63
+ posts.each do |post|
64
+ categories = post_categories.filter(
65
+ :mt_placement__placement_entry_id => post[:entry_id]
66
+ ).map {|ea| encode(ea[:category_basename], options) }
67
+
68
+ file_name = post_file_name(post, options)
69
+
70
+ data = post_metadata(post, options)
71
+ data['categories'] = categories if !categories.empty? && options[:categories]
72
+ yaml_front_matter = data.delete_if { |k,v| v.nil? || v == '' }.to_yaml
73
+
74
+ content = post_content(post, options)
75
+
76
+ File.open("_posts/#{file_name}", "w") do |f|
77
+ f.puts yaml_front_matter
78
+ f.puts "---"
79
+ f.puts encode(content, options)
80
+ end
81
+ end
82
+ end
83
+
84
+ # Extracts metadata for YAML front matter from post
85
+ def self.post_metadata(post, options = default_options)
86
+ metadata = {
87
+ 'layout' => 'post',
88
+ 'title' => encode(post[:entry_title], options),
89
+ 'date' => post[:entry_authored_on].strftime("%Y-%m-%d %H:%M:%S %z"),
90
+ 'excerpt' => encode(post[:entry_excerpt], options),
91
+ 'mt_id' => post[:entry_id]
92
+ }
93
+ metadata['published'] = false if post[:entry_status] != STATUS_PUBLISHED
94
+ metadata
95
+ end
96
+
97
+ # Extracts text body from post
98
+ def self.post_content(post, options = default_options)
99
+ if post[:entry_text_more].strip.empty?
100
+ post[:entry_text]
101
+ else
102
+ post[:entry_text] + "\n\n#{MORE_CONTENT_SEPARATOR}\n\n" + post[:entry_text_more]
103
+ end
104
+ end
105
+
106
+ def self.post_file_name(post, options = default_options)
107
+ date = post[:entry_authored_on]
108
+ slug = post[:entry_basename]
109
+ file_ext = suffix(post[:entry_convert_breaks])
110
+
111
+ "#{date.strftime('%Y-%m-%d')}-#{slug}.#{file_ext}"
112
+ end
113
+
114
+ def self.encode(str, options = default_options)
115
+ if str.respond_to?(:encoding)
116
+ str.encode(options[:dest_encoding], options[:src_encoding])
117
+ else
118
+ str
119
+ end
120
+ end
121
+
122
+ # Ideally, this script would determine the post format (markdown,
123
+ # html, etc) and create files with proper extensions. At this point
124
+ # it just assumes that markdown will be acceptable.
125
+ def self.suffix(entry_type)
126
+ if entry_type.nil? || entry_type.include?("markdown") || entry_type.include?("__default__")
127
+ # The markdown plugin I have saves this as
128
+ # "markdown_with_smarty_pants", so I just look for "markdown".
129
+ "markdown"
130
+ elsif entry_type.include?("textile")
131
+ # This is saved as "textile_2" on my installation of MT 5.1.
132
+ "textile"
133
+ elsif entry_type == "0" || entry_type.include?("richtext")
134
+ # Richtext looks to me like it's saved as HTML, so I include it here.
135
+ "html"
136
+ else
137
+ # Other values might need custom work.
138
+ entry_type
139
+ end
140
+ end
141
+ end
142
+ end