adocsite 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.
Files changed (44) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +82 -0
  5. data/Rakefile +1 -0
  6. data/TODO.md +12 -0
  7. data/adocsite.gemspec +32 -0
  8. data/bin/adocsite +63 -0
  9. data/examples/myconfig.rb +7 -0
  10. data/examples/mywpconfig.rb +9 -0
  11. data/lib/adocsite.rb +35 -0
  12. data/lib/adocsite/commands.rb +83 -0
  13. data/lib/adocsite/config.rb +66 -0
  14. data/lib/adocsite/content_loader.rb +59 -0
  15. data/lib/adocsite/content_types.rb +60 -0
  16. data/lib/adocsite/context.rb +118 -0
  17. data/lib/adocsite/engine.rb +147 -0
  18. data/lib/adocsite/site.rb +49 -0
  19. data/lib/adocsite/templates.rb +91 -0
  20. data/lib/adocsite/version.rb +3 -0
  21. data/lib/adocsite/wp/post.rb +170 -0
  22. data/tpl/default/includes/anything.haml +2 -0
  23. data/tpl/default/includes/bottom.haml +2 -0
  24. data/tpl/default/includes/footer.haml +4 -0
  25. data/tpl/default/includes/header.haml +2 -0
  26. data/tpl/default/includes/menu.haml +9 -0
  27. data/tpl/default/includes/one_level_menu.haml +5 -0
  28. data/tpl/default/includes/top.haml +2 -0
  29. data/tpl/default/layouts/compact.haml +14 -0
  30. data/tpl/default/layouts/default.haml +14 -0
  31. data/tpl/default/literals/google_analytics +7 -0
  32. data/tpl/default/partials/article.haml +2 -0
  33. data/tpl/default/partials/category.haml +6 -0
  34. data/tpl/default/partials/home.haml +12 -0
  35. data/tpl/default/partials/page.haml +2 -0
  36. data/tpl/default/resources/asciidoc.js +189 -0
  37. data/tpl/default/resources/asciidoctor.css +351 -0
  38. data/tpl/default/resources/funky.css +0 -0
  39. data/tpl/default/resources/kernel.css +0 -0
  40. data/tpl/default/resources/myblueraven.css +11 -0
  41. data/tpl/default/resources/myblueraven.js +0 -0
  42. data/tpl/default/resources/old-myblueraven.css +1316 -0
  43. data/tpl/default/resources/sleepy.js +0 -0
  44. metadata +201 -0
@@ -0,0 +1,3 @@
1
+ module Adocsite
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,170 @@
1
+ module Adocsite
2
+ class WpPost
3
+ attr_reader :categories, :content, :title, :excerpt, :name, :img_srcs, :post_media
4
+
5
+ def initialize
6
+ @engine = Adocsite::Engine::new
7
+
8
+ @wp = Rubypress::Client.new(Adocsite.wpconfig)
9
+ end
10
+
11
+ def process_by_title(article_title)
12
+ article_name = Adocsite::Content::title_to_name(article_title)
13
+ process(article_name)
14
+ end
15
+
16
+ def process(article_name)
17
+ @name = article_name
18
+ context = Adocsite::Context::new(@engine, Adocsite::Request.new('article', @name))
19
+ article = context.get_article
20
+ if article.nil?
21
+ abort "Can't find article."
22
+ end
23
+
24
+ @categories = article.categories
25
+ @content = article.content
26
+ @title = article.title
27
+ @excerpt = article.abstract
28
+
29
+ collect_images
30
+ create_post
31
+ upload_post_media
32
+ replace_images(@post_media)
33
+ update_post
34
+ end
35
+
36
+ def create_post
37
+ # get all WP categories
38
+ wp_categories = @wp.getTerms(:taxonomy => 'category')
39
+ all_categories = Hash.new
40
+ wp_categories.each {|term|
41
+ all_categories[term['name']] = term['term_id']
42
+ }
43
+
44
+ # are there any new we need to create?
45
+ new_categories_names = @categories - all_categories.keys
46
+
47
+ # pp new_categories_names
48
+
49
+ # create new categories, collect term_ids
50
+ new_categories = Hash.new
51
+ unless new_categories_names.empty?
52
+ new_categories_names.each {|name|
53
+ term_id = @wp.newTerm(:content => {:taxonomy => 'category', :name => name})
54
+ new_categories[name] = term_id
55
+ }
56
+ end
57
+
58
+ # create list of all article categories with their term_ids
59
+ article_categories = Hash.new
60
+ @categories.each {|name|
61
+ if all_categories.include?(name)
62
+ article_categories[name] = all_categories[name]
63
+ end
64
+ if new_categories.include?(name)
65
+ article_categories[name] = new_categories[name]
66
+ end
67
+ }
68
+
69
+ # now create new post from article
70
+ @post_id = @wp.newPost(:content => {
71
+ # :post_type => 'post', # by default post_type is 'post'
72
+ :post_status => 'draft', # post will be draft if post_status is omitted
73
+ :post_title => @title,
74
+ # :post_author => 'admin', # by default post_author is same as user you use for calling wp.newPost method
75
+ :post_excerpt => @excerpt,
76
+ :post_content => "", # empty content for now
77
+ :terms =>
78
+ {
79
+ :category => article_categories.values # these are term_ids for categories, if omitted default is 'Uncategorized'
80
+ }
81
+ })
82
+ # pp post_id
83
+ @post_id
84
+ end
85
+
86
+ def find_full_image_path(image_name, image_list)
87
+ ret_arr = image_list.collect {|element|
88
+ if element.end_with? image_name
89
+ element
90
+ else
91
+ nil
92
+ end
93
+ }
94
+ ret_arr.compact[0]
95
+ end
96
+
97
+ def upload_post_media
98
+ site_images = @engine.content_loader.images
99
+ @post_media = Hash.new
100
+ @img_srcs.each {|image_name|
101
+ file_path = find_full_image_path(image_name, site_images)
102
+ # file_name = File.join("", file_path)
103
+ file_name = file_path
104
+
105
+ image_contents = XMLRPC::Base64.new(IO.read(file_name))
106
+ image_type = MIME::Types.type_for(image_name).first.to_s
107
+
108
+ media_upload = @wp.uploadFile(:data => {
109
+ :name => image_name,
110
+ :type => image_type,
111
+ # :filename => file_name,
112
+ :bits => image_contents,
113
+ :overwrite => false,
114
+ :post_id => @post_id
115
+ })
116
+ # media_upload[:url] is NOT going to work here
117
+ @post_media[image_name] = media_upload["url"]
118
+ # pp media_upload
119
+ }
120
+
121
+ end
122
+
123
+ def update_post
124
+ #Update/Edit post
125
+ @post_id = @wp.editPost(:post_id => @post_id,
126
+ :content => {
127
+ :post_status => 'publish', # it was created as draft, now publish it
128
+ :post_content => @content
129
+ })
130
+ # pp post_id
131
+ @post_id
132
+ end
133
+
134
+ def stringreturn(img_name)
135
+ @img_hash[img_name]
136
+ end
137
+
138
+ def collect_images
139
+ doc = Nokogiri::HTML(@content)
140
+ img_srcs = doc.css('img').map{ |i| i['src'] } # Array of strings
141
+
142
+ # pp article_content
143
+
144
+ # pp img_srcs
145
+
146
+ img_srcs = img_srcs.collect {|img_src|
147
+ md = /^img\/(.*)/.match(img_src)
148
+ md.captures[0] unless md == nil
149
+ }
150
+
151
+ @img_srcs = img_srcs.compact
152
+
153
+ # pp img_srcs
154
+ end
155
+
156
+ def replace_images(new_images)
157
+ @img_hash = Hash.new
158
+ @img_srcs.each {|img_nm|
159
+ # @img_hash[img_nm] = "\"myimages/#{img_nm}\""
160
+ @img_hash[img_nm] = new_images[img_nm]
161
+ }
162
+
163
+ # pp article_content
164
+ @content = @content.gsub(/"img\/(.*?)"/) {|img_tag| stringreturn("#$1")}
165
+ # pp article_content
166
+ end
167
+
168
+ private :create_post, :find_full_image_path, :upload_post_media, :update_post, :stringreturn, :collect_images, :replace_images
169
+ end
170
+ end
@@ -0,0 +1,2 @@
1
+ %p
2
+ =SiteCore.render_menu
@@ -0,0 +1,2 @@
1
+ %p
2
+ =SiteCore.render_menu
@@ -0,0 +1,4 @@
1
+ %p
2
+ Copyright © 2014 Ravendyne Inc.
3
+ %script
4
+ = get_literal('google_analytics')
@@ -0,0 +1,2 @@
1
+ %p
2
+ This is site header.
@@ -0,0 +1,9 @@
1
+ %ul
2
+ - get_categories().each do |category|
3
+ %li
4
+ = category.name
5
+ %ul
6
+ - category.articles.each do |article|
7
+ %li
8
+ %a(href="show?article=#{article.doctitle}")
9
+ = article.title
@@ -0,0 +1,5 @@
1
+ %ul
2
+ - SiteCore.get_categories.each do |category|
3
+ %li
4
+ %a(href="show?cat=#{category}")
5
+ = category
@@ -0,0 +1,2 @@
1
+ %p
2
+ =SiteCore.render_menu
@@ -0,0 +1,14 @@
1
+ %html
2
+ %head
3
+ %title= page_title
4
+ %script{:src => 'js/asciidoc.js'}
5
+ %script{:src => 'js/myblueraven.js'}
6
+ %link{:rel => 'stylesheet', :media => "screen", :href => 'css/myblueraven.css'}
7
+ %body
8
+ #page
9
+ #header
10
+ This is 'compact' layout. Looks the same as default, it's here only to show that you can have different ones.
11
+ #content
12
+ = get_content_for_layout()
13
+ #footer
14
+ = get_include('footer')
@@ -0,0 +1,14 @@
1
+ %html
2
+ %head
3
+ %title= page_title
4
+ %script{:src => 'js/asciidoc.js'}
5
+ %script{:src => 'js/myblueraven.js'}
6
+ %link{:rel => 'stylesheet', :media => "screen", :href => 'css/myblueraven.css'}
7
+ %body
8
+ #page
9
+ #header
10
+ = get_include('header')
11
+ #content
12
+ = get_content_for_layout()
13
+ #footer
14
+ = get_include('footer')
@@ -0,0 +1,7 @@
1
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
3
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
4
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
5
+
6
+ //ga('create', 'UA-931975-7', 'unknownworlds.com');
7
+ //ga('send', 'pageview');
@@ -0,0 +1,2 @@
1
+ %p
2
+ = article.content
@@ -0,0 +1,6 @@
1
+ %p
2
+ - category.articles.each do |article|
3
+ %p
4
+ %a{:href => sitenav('article', article.name)}
5
+ = article.title
6
+
@@ -0,0 +1,12 @@
1
+ .content
2
+ %h1 Pages list
3
+ - get_pages().each do |page|
4
+ %p
5
+ %a{:href => sitenav('page', page.name)}
6
+ = page.name
7
+ %h1 Categories list
8
+ - get_categories().each do |category|
9
+ %p
10
+ %a{:href => sitenav('category', category.name)}
11
+ = category.name
12
+
@@ -0,0 +1,2 @@
1
+ %p
2
+ = page.content
@@ -0,0 +1,189 @@
1
+ var asciidoc = { // Namespace.
2
+
3
+ /////////////////////////////////////////////////////////////////////
4
+ // Table Of Contents generator
5
+ /////////////////////////////////////////////////////////////////////
6
+
7
+ /* Author: Mihai Bazon, September 2002
8
+ * http://students.infoiasi.ro/~mishoo
9
+ *
10
+ * Table Of Content generator
11
+ * Version: 0.4
12
+ *
13
+ * Feel free to use this script under the terms of the GNU General Public
14
+ * License, as long as you do not remove or alter this notice.
15
+ */
16
+
17
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
18
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
19
+
20
+ // toclevels = 1..4.
21
+ toc: function (toclevels) {
22
+
23
+ function getText(el) {
24
+ var text = "";
25
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
26
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
27
+ text += i.data;
28
+ else if (i.firstChild != null)
29
+ text += getText(i);
30
+ }
31
+ return text;
32
+ }
33
+
34
+ function TocEntry(el, text, toclevel) {
35
+ this.element = el;
36
+ this.text = text;
37
+ this.toclevel = toclevel;
38
+ }
39
+
40
+ function tocEntries(el, toclevels) {
41
+ var result = new Array;
42
+ var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
43
+ // Function that scans the DOM tree for header elements (the DOM2
44
+ // nodeIterator API would be a better technique but not supported by all
45
+ // browsers).
46
+ var iterate = function (el) {
47
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
48
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
49
+ var mo = re.exec(i.tagName);
50
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
51
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
52
+ }
53
+ iterate(i);
54
+ }
55
+ }
56
+ }
57
+ iterate(el);
58
+ return result;
59
+ }
60
+
61
+ var toc = document.getElementById("toc");
62
+ if (!toc) {
63
+ return;
64
+ }
65
+
66
+ // Delete existing TOC entries in case we're reloading the TOC.
67
+ var tocEntriesToRemove = [];
68
+ var i;
69
+ for (i = 0; i < toc.childNodes.length; i++) {
70
+ var entry = toc.childNodes[i];
71
+ if (entry.nodeName == 'div'
72
+ && entry.getAttribute("class")
73
+ && entry.getAttribute("class").match(/^toclevel/))
74
+ tocEntriesToRemove.push(entry);
75
+ }
76
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
77
+ toc.removeChild(tocEntriesToRemove[i]);
78
+ }
79
+
80
+ // Rebuild TOC entries.
81
+ var entries = tocEntries(document.getElementById("content"), toclevels);
82
+ for (var i = 0; i < entries.length; ++i) {
83
+ var entry = entries[i];
84
+ if (entry.element.id == "")
85
+ entry.element.id = "_toc_" + i;
86
+ var a = document.createElement("a");
87
+ a.href = "#" + entry.element.id;
88
+ a.appendChild(document.createTextNode(entry.text));
89
+ var div = document.createElement("div");
90
+ div.appendChild(a);
91
+ div.className = "toclevel" + entry.toclevel;
92
+ toc.appendChild(div);
93
+ }
94
+ if (entries.length == 0)
95
+ toc.parentNode.removeChild(toc);
96
+ },
97
+
98
+
99
+ /////////////////////////////////////////////////////////////////////
100
+ // Footnotes generator
101
+ /////////////////////////////////////////////////////////////////////
102
+
103
+ /* Based on footnote generation code from:
104
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
105
+ */
106
+
107
+ footnotes: function () {
108
+ // Delete existing footnote entries in case we're reloading the footnodes.
109
+ var i;
110
+ var noteholder = document.getElementById("footnotes");
111
+ if (!noteholder) {
112
+ return;
113
+ }
114
+ var entriesToRemove = [];
115
+ for (i = 0; i < noteholder.childNodes.length; i++) {
116
+ var entry = noteholder.childNodes[i];
117
+ if (entry.nodeName == 'div' && entry.getAttribute("class") == "footnote")
118
+ entriesToRemove.push(entry);
119
+ }
120
+ for (i = 0; i < entriesToRemove.length; i++) {
121
+ noteholder.removeChild(entriesToRemove[i]);
122
+ }
123
+
124
+ // Rebuild footnote entries.
125
+ var cont = document.getElementById("content");
126
+ var spans = cont.getElementsByTagName("span");
127
+ var refs = {};
128
+ var n = 0;
129
+ for (i=0; i<spans.length; i++) {
130
+ if (spans[i].className == "footnote") {
131
+ n++;
132
+ var note = spans[i].getAttribute("data-note");
133
+ if (!note) {
134
+ // Use [\s\S] in place of . so multi-line matches work.
135
+ // Because JavaScript has no s (dotall) regex flag.
136
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
137
+ spans[i].innerHTML =
138
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
139
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
140
+ spans[i].setAttribute("data-note", note);
141
+ }
142
+ noteholder.innerHTML +=
143
+ "<div class='footnote' id='_footnote_" + n + "'>" +
144
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
145
+ n + "</a>. " + note + "</div>";
146
+ var id =spans[i].getAttribute("id");
147
+ if (id != null) refs["#"+id] = n;
148
+ }
149
+ }
150
+ if (n == 0)
151
+ noteholder.parentNode.removeChild(noteholder);
152
+ else {
153
+ // Process footnoterefs.
154
+ for (i=0; i<spans.length; i++) {
155
+ if (spans[i].className == "footnoteref") {
156
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
157
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
158
+ n = refs[href];
159
+ spans[i].innerHTML =
160
+ "[<a href='#_footnote_" + n +
161
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
162
+ }
163
+ }
164
+ }
165
+ },
166
+
167
+ install: function(toclevels) {
168
+ var timerId;
169
+
170
+ function reinstall() {
171
+ asciidoc.footnotes();
172
+ if (toclevels) {
173
+ asciidoc.toc(toclevels);
174
+ }
175
+ }
176
+
177
+ function reinstallAndRemoveTimer() {
178
+ clearInterval(timerId);
179
+ reinstall();
180
+ }
181
+
182
+ timerId = setInterval(reinstall, 500);
183
+ if (document.addEventListener)
184
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
185
+ else
186
+ window.onload = reinstallAndRemoveTimer;
187
+ }
188
+
189
+ }