org-ruby 0.2.0 → 0.3.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 (56) hide show
  1. data/History.txt +32 -24
  2. data/README.txt +66 -66
  3. data/Rakefile +26 -22
  4. data/bin/org-ruby +40 -40
  5. data/lib/org-ruby.rb +50 -48
  6. data/lib/org-ruby/headline.rb +75 -75
  7. data/lib/org-ruby/html_output_buffer.rb +81 -80
  8. data/lib/org-ruby/line.rb +173 -172
  9. data/lib/org-ruby/output_buffer.rb +154 -154
  10. data/lib/org-ruby/parser.rb +76 -72
  11. data/lib/org-ruby/regexp_helper.rb +156 -156
  12. data/lib/org-ruby/textile_output_buffer.rb +67 -67
  13. data/spec/data/freeform.org +111 -111
  14. data/spec/data/hyp-planning.org +335 -335
  15. data/spec/data/remember.org +53 -53
  16. data/spec/headline_spec.rb +55 -55
  17. data/spec/html_examples/block_code.html +30 -29
  18. data/spec/html_examples/block_code.org +35 -35
  19. data/spec/html_examples/blockquote.html +7 -7
  20. data/spec/html_examples/blockquote.org +13 -13
  21. data/spec/html_examples/escape-pre.html +7 -0
  22. data/spec/html_examples/escape-pre.org +6 -0
  23. data/spec/html_examples/inline-formatting.html +10 -10
  24. data/spec/html_examples/inline-formatting.org +17 -17
  25. data/spec/html_examples/lists.html +19 -19
  26. data/spec/html_examples/lists.org +36 -36
  27. data/spec/html_examples/only-list.html +5 -0
  28. data/spec/html_examples/only-list.org +3 -0
  29. data/spec/html_examples/only-table.html +6 -0
  30. data/spec/html_examples/only-table.org +5 -0
  31. data/spec/html_examples/tables.html +20 -20
  32. data/spec/html_examples/tables.org +26 -26
  33. data/spec/html_examples/text.html +2 -2
  34. data/spec/html_examples/text.org +16 -16
  35. data/spec/line_spec.rb +89 -89
  36. data/spec/parser_spec.rb +86 -86
  37. data/spec/regexp_helper_spec.rb +57 -57
  38. data/spec/spec_helper.rb +20 -20
  39. data/spec/textile_examples/block_code.org +35 -35
  40. data/spec/textile_examples/block_code.textile +29 -29
  41. data/spec/textile_examples/blockquote.org +13 -13
  42. data/spec/textile_examples/blockquote.textile +11 -11
  43. data/spec/textile_examples/keywords.org +13 -13
  44. data/spec/textile_examples/keywords.textile +11 -11
  45. data/spec/textile_examples/links.org +11 -11
  46. data/spec/textile_examples/links.textile +10 -10
  47. data/spec/textile_examples/lists.org +36 -36
  48. data/spec/textile_examples/lists.textile +20 -20
  49. data/spec/textile_examples/single-space-plain-list.org +13 -13
  50. data/spec/textile_examples/single-space-plain-list.textile +10 -10
  51. data/spec/textile_examples/tables.org +26 -26
  52. data/spec/textile_examples/tables.textile +23 -23
  53. data/spec/textile_output_buffer_spec.rb +21 -21
  54. data/tasks/test_case.rake +49 -0
  55. metadata +21 -5
  56. data/.bnsignore +0 -18
@@ -1,156 +1,156 @@
1
- require 'logger'
2
-
3
- module Orgmode
4
-
5
- # = Summary
6
- #
7
- # This class contains helper routines to deal with the Regexp "black
8
- # magic" you need to properly parse org-mode files.
9
- #
10
- # = Key methods
11
- #
12
- # * Use +rewrite_emphasis+ to replace org-mode emphasis strings (e.g.,
13
- # \/italic/) with the suitable markup for the output.
14
- #
15
- # * Use +rewrite_links+ to get a chance to rewrite all org-mode
16
- # links with suitable markup for the output.
17
- class RegexpHelper
18
-
19
- ######################################################################
20
- # EMPHASIS
21
- #
22
- # I figure it's best to stick as closely to the elisp implementation
23
- # as possible for emphasis. org.el defines the regular expression that
24
- # is used to apply "emphasis" (in my terminology, inline formatting
25
- # instead of block formatting). Here's the documentation from org.el.
26
- #
27
- # Terminology: In an emphasis string like " *strong word* ", we
28
- # call the initial space PREMATCH, the final space POSTMATCH, the
29
- # stars MARKERS, "s" and "d" are BORDER characters and "trong wor"
30
- # is the body. The different components in this variable specify
31
- # what is allowed/forbidden in each part:
32
- #
33
- # pre Chars allowed as prematch. Line beginning allowed, too.
34
- # post Chars allowed as postmatch. Line end will be allowed too.
35
- # border The chars *forbidden* as border characters.
36
- # body-regexp A regexp like \".\" to match a body character. Don't use
37
- # non-shy groups here, and don't allow newline here.
38
- # newline The maximum number of newlines allowed in an emphasis exp.
39
- #
40
- # I currently don't use +newline+ because I've thrown this information
41
- # away by this point in the code. TODO -- revisit?
42
- attr_reader :pre_emphasis
43
- attr_reader :post_emphasis
44
- attr_reader :border_forbidden
45
- attr_reader :body_regexp
46
- attr_reader :markers
47
-
48
- attr_reader :org_emphasis_regexp
49
-
50
- def initialize
51
- # Set up the emphasis regular expression.
52
- @pre_emphasis = " \t\\('\""
53
- @post_emphasis = "- \t.,:!?;'\"\\)"
54
- @border_forbidden = " \t\r\n,\"'"
55
- @body_regexp = ".*?"
56
- @markers = "*/_=~+"
57
- @logger = Logger.new(STDERR)
58
- @logger.level = Logger::WARN
59
- build_org_emphasis_regexp
60
- build_org_link_regexp
61
- end
62
-
63
- # Finds all emphasis matches in a string.
64
- # Supply a block that will get the marker and body as parameters.
65
- def match_all(str)
66
- str.scan(@org_emphasis_regexp) do |match|
67
- yield $2, $3
68
- end
69
- end
70
-
71
- # Compute replacements for all matching emphasized phrases.
72
- # Supply a block that will get the marker and body as parameters;
73
- # return the replacement string from your block.
74
- #
75
- # = Example
76
- #
77
- # re = RegexpHelper.new
78
- # result = re.rewrite_emphasis("*bold*, /italic/, =code=") do |marker, body|
79
- # "<#{map[marker]}>#{body}</#{map[marker]}>"
80
- # end
81
- #
82
- # In this example, the block body will get called three times:
83
- #
84
- # 1. Marker: "*", body: "bold"
85
- # 2. Marker: "/", body: "italic"
86
- # 3. Marker: "=", body: "code"
87
- #
88
- # The return from this block is a string that will be used to
89
- # replace "*bold*", "/italic/", and "=code=",
90
- # respectively. (Clearly this sample string will use HTML-like
91
- # syntax, assuming +map+ is defined appropriately.)
92
- def rewrite_emphasis(str)
93
- str.gsub(@org_emphasis_regexp) do |match|
94
- inner = yield $2, $3
95
- "#{$1}#{inner}#{$4}"
96
- end
97
- end
98
-
99
- # = Summary
100
- #
101
- # Rewrite org-mode links in a string to markup suitable to the
102
- # output format.
103
- #
104
- # = Usage
105
- #
106
- # Give this a block that expect the link and optional friendly
107
- # text. Return how that link should get formatted.
108
- #
109
- # = Example
110
- #
111
- # re = RegexpHelper.new
112
- # result = re.rewrite_links("[[http://www.bing.com]] and [[http://www.hotmail.com][Hotmail]]") do |link, text}
113
- # text ||= link
114
- # "<a href=\"#{link}\">#{text}</a>"
115
- # end
116
- #
117
- # In this example, the block body will get called two times. In the
118
- # first instance, +text+ will be nil (the org-mode markup gives no
119
- # friendly text for the link +http://www.bing.com+. In the second
120
- # instance, the block will get text of *Hotmail* and the link
121
- # +http://www.hotmail.com+. In both cases, the block returns an
122
- # HTML-style link, and that is how things will get recorded in
123
- # +result+.
124
- def rewrite_links(str)
125
- i = str.gsub(@org_link_regexp) do |match|
126
- yield $1, nil
127
- end
128
- i.gsub(@org_link_text_regexp) do |match|
129
- yield $1, $2
130
- end
131
- end
132
-
133
- private
134
-
135
- def build_org_emphasis_regexp
136
- @org_emphasis_regexp = Regexp.new("([#{@pre_emphasis}]|^)\n" +
137
- "( [#{@markers}] )\n" +
138
- "( [^#{@border_forbidden}] | " +
139
- " [^#{@border_forbidden}]#{@body_regexp}[^#{@border_forbidden}] )\n" +
140
- "\\2\n" +
141
- "([#{@post_emphasis}]|$)\n", Regexp::EXTENDED)
142
- @logger.debug "Just created regexp: #{@org_emphasis_regexp}"
143
- end
144
-
145
- def build_org_link_regexp
146
- @org_link_regexp = /\[\[
147
- ([^\]]*) # This is the URL
148
- \]\]/x
149
- @org_link_text_regexp = /\[\[
150
- ([^\]]*) # This is the URL
151
- \]\[
152
- ([^\]]*) # This is the friendly text
153
- \]\]/x
154
- end
155
- end # class Emphasis
156
- end # module Orgmode
1
+ require 'logger'
2
+
3
+ module Orgmode
4
+
5
+ # = Summary
6
+ #
7
+ # This class contains helper routines to deal with the Regexp "black
8
+ # magic" you need to properly parse org-mode files.
9
+ #
10
+ # = Key methods
11
+ #
12
+ # * Use +rewrite_emphasis+ to replace org-mode emphasis strings (e.g.,
13
+ # \/italic/) with the suitable markup for the output.
14
+ #
15
+ # * Use +rewrite_links+ to get a chance to rewrite all org-mode
16
+ # links with suitable markup for the output.
17
+ class RegexpHelper
18
+
19
+ ######################################################################
20
+ # EMPHASIS
21
+ #
22
+ # I figure it's best to stick as closely to the elisp implementation
23
+ # as possible for emphasis. org.el defines the regular expression that
24
+ # is used to apply "emphasis" (in my terminology, inline formatting
25
+ # instead of block formatting). Here's the documentation from org.el.
26
+ #
27
+ # Terminology: In an emphasis string like " *strong word* ", we
28
+ # call the initial space PREMATCH, the final space POSTMATCH, the
29
+ # stars MARKERS, "s" and "d" are BORDER characters and "trong wor"
30
+ # is the body. The different components in this variable specify
31
+ # what is allowed/forbidden in each part:
32
+ #
33
+ # pre Chars allowed as prematch. Line beginning allowed, too.
34
+ # post Chars allowed as postmatch. Line end will be allowed too.
35
+ # border The chars *forbidden* as border characters.
36
+ # body-regexp A regexp like \".\" to match a body character. Don't use
37
+ # non-shy groups here, and don't allow newline here.
38
+ # newline The maximum number of newlines allowed in an emphasis exp.
39
+ #
40
+ # I currently don't use +newline+ because I've thrown this information
41
+ # away by this point in the code. TODO -- revisit?
42
+ attr_reader :pre_emphasis
43
+ attr_reader :post_emphasis
44
+ attr_reader :border_forbidden
45
+ attr_reader :body_regexp
46
+ attr_reader :markers
47
+
48
+ attr_reader :org_emphasis_regexp
49
+
50
+ def initialize
51
+ # Set up the emphasis regular expression.
52
+ @pre_emphasis = " \t\\('\""
53
+ @post_emphasis = "- \t.,:!?;'\"\\)"
54
+ @border_forbidden = " \t\r\n,\"'"
55
+ @body_regexp = ".*?"
56
+ @markers = "*/_=~+"
57
+ @logger = Logger.new(STDERR)
58
+ @logger.level = Logger::WARN
59
+ build_org_emphasis_regexp
60
+ build_org_link_regexp
61
+ end
62
+
63
+ # Finds all emphasis matches in a string.
64
+ # Supply a block that will get the marker and body as parameters.
65
+ def match_all(str)
66
+ str.scan(@org_emphasis_regexp) do |match|
67
+ yield $2, $3
68
+ end
69
+ end
70
+
71
+ # Compute replacements for all matching emphasized phrases.
72
+ # Supply a block that will get the marker and body as parameters;
73
+ # return the replacement string from your block.
74
+ #
75
+ # = Example
76
+ #
77
+ # re = RegexpHelper.new
78
+ # result = re.rewrite_emphasis("*bold*, /italic/, =code=") do |marker, body|
79
+ # "<#{map[marker]}>#{body}</#{map[marker]}>"
80
+ # end
81
+ #
82
+ # In this example, the block body will get called three times:
83
+ #
84
+ # 1. Marker: "*", body: "bold"
85
+ # 2. Marker: "/", body: "italic"
86
+ # 3. Marker: "=", body: "code"
87
+ #
88
+ # The return from this block is a string that will be used to
89
+ # replace "*bold*", "/italic/", and "=code=",
90
+ # respectively. (Clearly this sample string will use HTML-like
91
+ # syntax, assuming +map+ is defined appropriately.)
92
+ def rewrite_emphasis(str)
93
+ str.gsub(@org_emphasis_regexp) do |match|
94
+ inner = yield $2, $3
95
+ "#{$1}#{inner}#{$4}"
96
+ end
97
+ end
98
+
99
+ # = Summary
100
+ #
101
+ # Rewrite org-mode links in a string to markup suitable to the
102
+ # output format.
103
+ #
104
+ # = Usage
105
+ #
106
+ # Give this a block that expect the link and optional friendly
107
+ # text. Return how that link should get formatted.
108
+ #
109
+ # = Example
110
+ #
111
+ # re = RegexpHelper.new
112
+ # result = re.rewrite_links("[[http://www.bing.com]] and [[http://www.hotmail.com][Hotmail]]") do |link, text}
113
+ # text ||= link
114
+ # "<a href=\"#{link}\">#{text}</a>"
115
+ # end
116
+ #
117
+ # In this example, the block body will get called two times. In the
118
+ # first instance, +text+ will be nil (the org-mode markup gives no
119
+ # friendly text for the link +http://www.bing.com+. In the second
120
+ # instance, the block will get text of *Hotmail* and the link
121
+ # +http://www.hotmail.com+. In both cases, the block returns an
122
+ # HTML-style link, and that is how things will get recorded in
123
+ # +result+.
124
+ def rewrite_links(str)
125
+ i = str.gsub(@org_link_regexp) do |match|
126
+ yield $1, nil
127
+ end
128
+ i.gsub(@org_link_text_regexp) do |match|
129
+ yield $1, $2
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ def build_org_emphasis_regexp
136
+ @org_emphasis_regexp = Regexp.new("([#{@pre_emphasis}]|^)\n" +
137
+ "( [#{@markers}] )\n" +
138
+ "( [^#{@border_forbidden}] | " +
139
+ " [^#{@border_forbidden}]#{@body_regexp}[^#{@border_forbidden}] )\n" +
140
+ "\\2\n" +
141
+ "([#{@post_emphasis}]|$)\n", Regexp::EXTENDED)
142
+ @logger.debug "Just created regexp: #{@org_emphasis_regexp}"
143
+ end
144
+
145
+ def build_org_link_regexp
146
+ @org_link_regexp = /\[\[
147
+ ([^\]]*) # This is the URL
148
+ \]\]/x
149
+ @org_link_text_regexp = /\[\[
150
+ ([^\]]*) # This is the URL
151
+ \]\[
152
+ ([^\]]*) # This is the friendly text
153
+ \]\]/x
154
+ end
155
+ end # class Emphasis
156
+ end # module Orgmode
@@ -1,67 +1,67 @@
1
- require 'stringio'
2
-
3
- module Orgmode
4
-
5
- class TextileOutputBuffer < OutputBuffer
6
-
7
- def initialize(output)
8
- super(output)
9
- @add_paragraph = false
10
- end
11
-
12
- def push_mode(mode)
13
- super(mode)
14
- @output << "bc.. " if mode == :code
15
- end
16
-
17
- def pop_mode(mode = nil)
18
- m = super(mode)
19
- @add_paragraph = (m == :code)
20
- m
21
- end
22
-
23
- # Maps org markup to textile markup.
24
- TextileMap = {
25
- "*" => "*",
26
- "/" => "_",
27
- "_" => "_",
28
- "=" => "@",
29
- "~" => "@",
30
- "+" => "+"
31
- }
32
-
33
- # Handles inline formatting for textile.
34
- def inline_formatting(input)
35
- input = @re_help.rewrite_emphasis(input) do |marker, body|
36
- m = TextileMap[marker]
37
- "#{m}#{body}#{m}"
38
- end
39
- input = @re_help.rewrite_links(input) do |link, text|
40
- text ||= link
41
- link = link.gsub(/ /, "%20")
42
- "\"#{text}\":#{link}"
43
- end
44
- input
45
- end
46
-
47
- # Flushes the current buffer
48
- def flush!
49
- @logger.debug "FLUSH ==========> #{@output_type}"
50
- if (@output_type == :blank) then
51
- @output << "\n"
52
- elsif (@buffer.length > 0) then
53
- if @add_paragraph then
54
- @output << "p. " if @output_type == :paragraph
55
- @add_paragraph = false
56
- end
57
- @output << "bq. " if current_mode == :blockquote
58
- @output << "#" * @list_indent_stack.length << " " if @output_type == :ordered_list
59
- @output << "*" * @list_indent_stack.length << " " if @output_type == :unordered_list
60
- @output << inline_formatting(@buffer) << "\n"
61
- end
62
- @buffer = ""
63
- end
64
-
65
-
66
- end # class TextileOutputBuffer
67
- end # module Orgmode
1
+ require 'stringio'
2
+
3
+ module Orgmode
4
+
5
+ class TextileOutputBuffer < OutputBuffer
6
+
7
+ def initialize(output)
8
+ super(output)
9
+ @add_paragraph = false
10
+ end
11
+
12
+ def push_mode(mode)
13
+ super(mode)
14
+ @output << "bc.. " if mode == :code
15
+ end
16
+
17
+ def pop_mode(mode = nil)
18
+ m = super(mode)
19
+ @add_paragraph = (m == :code)
20
+ m
21
+ end
22
+
23
+ # Maps org markup to textile markup.
24
+ TextileMap = {
25
+ "*" => "*",
26
+ "/" => "_",
27
+ "_" => "_",
28
+ "=" => "@",
29
+ "~" => "@",
30
+ "+" => "+"
31
+ }
32
+
33
+ # Handles inline formatting for textile.
34
+ def inline_formatting(input)
35
+ input = @re_help.rewrite_emphasis(input) do |marker, body|
36
+ m = TextileMap[marker]
37
+ "#{m}#{body}#{m}"
38
+ end
39
+ input = @re_help.rewrite_links(input) do |link, text|
40
+ text ||= link
41
+ link = link.gsub(/ /, "%20")
42
+ "\"#{text}\":#{link}"
43
+ end
44
+ input
45
+ end
46
+
47
+ # Flushes the current buffer
48
+ def flush!
49
+ @logger.debug "FLUSH ==========> #{@output_type}"
50
+ if (@output_type == :blank) then
51
+ @output << "\n"
52
+ elsif (@buffer.length > 0) then
53
+ if @add_paragraph then
54
+ @output << "p. " if @output_type == :paragraph
55
+ @add_paragraph = false
56
+ end
57
+ @output << "bq. " if current_mode == :blockquote
58
+ @output << "#" * @list_indent_stack.length << " " if @output_type == :ordered_list
59
+ @output << "*" * @list_indent_stack.length << " " if @output_type == :unordered_list
60
+ @output << inline_formatting(@buffer) << "\n"
61
+ end
62
+ @buffer = ""
63
+ end
64
+
65
+
66
+ end # class TextileOutputBuffer
67
+ end # module Orgmode
@@ -1,111 +1,111 @@
1
- #+TITLE: Freeform
2
- #+AUTHOR:
3
- #+EMAIL: bdewey@gmail.com
4
- #+DATE: 2009-12-20 Sun
5
- #+DESCRIPTION:
6
- #+KEYWORDS:
7
- #+LANGUAGE: en
8
- #+OPTIONS: H:3 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
9
- #+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc
10
- #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
11
- #+EXPORT_SELECT_TAGS: export
12
- #+EXPORT_EXCLUDE_TAGS: noexport
13
- #+LINK_UP:
14
- #+LINK_HOME:
15
- Freeform
16
-
17
- This is my todo list, research file, and log record from working on
18
- the Freeform project.
19
-
20
- * Future ideas :someday:
21
- - Add *posts*
22
- - Enforce uniqueness of url_token
23
- - Add FeedSync support
24
- - Auto-recognize URLs
25
- - Edit in place
26
- - Import/export of content. I want it to be safe to store real content on the site.
27
- - Page reordering.
28
- - AtomPub support.
29
- - Organization:
30
- - Move pages around
31
- - Add tags and navigation by tags
32
- - Add a breadcrumb bar
33
-
34
- * TODO Add versioning support :current:feature:
35
-
36
- ** DONE UI rough-in
37
- CLOSED: [2009-11-26 Thu]
38
-
39
- ** DONE Author logging
40
- CLOSED: [2009-11-27 Fri]
41
-
42
- ** DONE Version table and model updates
43
- CLOSED: [2009-11-28 Sat 22:40]
44
- CLOCK: [2009-11-28 Sat 21:35]--[2009-11-28 Sat 22:40] => 1:05
45
- CLOCK: [2009-11-28 Sat 21:01]--[2009-11-28 Sat 21:25] => 0:24
46
- CLOCK: [2009-11-28 Sat 19:46]--[2009-11-28 Sat 20:54] => 1:08
47
- CLOCK: [2009-11-28 Sat 14:38]--[2009-11-28 Sat 15:08] => 0:30
48
- CLOCK: [2009-11-28 Sat 13:21]--[2009-11-28 Sat 14:37] => 1:16
49
-
50
- OK, my current thinking is to have each idea have many Changes. A
51
- change has many change records. A change record is a list of
52
- specific attributes that change, and includes the old and the new
53
- values. I'll use callbacks on the Idea model to maintain the
54
- changes.
55
-
56
-
57
- *** DONE Create version method
58
- CLOSED: [2009-11-28 Sat 22:40]
59
-
60
- *** DONE Make current method
61
- CLOSED: [2009-11-28 Sat 22:40]
62
-
63
- ** Update pages controller
64
-
65
- *** DONE Show versions
66
- CLOSED: [2009-11-30 Mon 00:34]
67
- CLOCK: [2009-11-29 Sun 21:27]--[2009-11-29 Sun 21:54] => 0:27
68
- CLOCK: [2009-11-29 Sun 15:40]--[2009-11-29 Sun 15:44] => 0:04
69
- CLOCK: [2009-11-28 Sat 22:44]--[2009-11-28 Sat 23:50] => 1:06
70
-
71
- I'm now at the point where I *list* versions, but I can't show
72
- them.
73
-
74
- - [X] I currently suspect that I broke my version recovery code
75
- when I switched the order of the idea_changes. I need to
76
- investigate why nothing's failing in the tests; I expected
77
- failures. Possible addition to test: start looking at those
78
- version numbers.
79
-
80
- OK, here's what was going on: In the test, you need to
81
- reload the idea_changes array from the database to get the
82
- database sort order. I also make sure I do this inside the
83
- Idea methods.
84
-
85
- **** DONE Write a test for Idea::attributes_for_change
86
- CLOSED: [2009-11-29 Sun 23:59]
87
- CLOCK: [2009-11-29 Sun 23:47]--[2009-11-29 Sun 23:58] => 0:11
88
- CLOCK: [2009-11-29 Sun 22:02]--[2009-11-29 Sun 23:42] => 1:40
89
- CLOCK: [2009-11-29 Sun 21:54]--[2009-11-29 Sun 21:56] => 0:02
90
-
91
- *** DONE Write integration tests that cover versions.
92
- CLOSED: [2009-12-11 Fri 23:25]
93
- CLOCK: [2009-12-11 Fri 20:27]--[2009-12-11 Fri 23:25] => 2:58
94
-
95
- *** DONE Recover versions
96
- CLOSED: [2009-12-12 Sat 22:09]
97
- CLOCK: [2009-12-12 Sat 21:02]--[2009-12-12 Sat 22:09] => 1:07
98
- CLOCK: [2009-12-12 Sat 20:13]--[2009-12-12 Sat 21:00] => 0:47
99
-
100
- *** DONE Move to recycle bin
101
- CLOSED: [2009-12-12 Sat 22:59]
102
- CLOCK: [2009-12-12 Sat 22:23]--[2009-12-12 Sat 22:59] => 0:36
103
-
104
- Note I'm avoiding logging delete operations because I'm presuming
105
- there will be a recycle bin, and therefore the *pages* controller
106
- will never actually delete files. At some point, when I want to
107
- support full FeedSync, I'll need to tackle this.
108
-
109
- The other timebomb: I don't know how well my logging scheme will
110
- work when pages move. I don't yet know if I will address this in
111
- the current sprint.
1
+ #+TITLE: Freeform
2
+ #+AUTHOR:
3
+ #+EMAIL: bdewey@gmail.com
4
+ #+DATE: 2009-12-20 Sun
5
+ #+DESCRIPTION:
6
+ #+KEYWORDS:
7
+ #+LANGUAGE: en
8
+ #+OPTIONS: H:3 num:t toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
9
+ #+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc
10
+ #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
11
+ #+EXPORT_SELECT_TAGS: export
12
+ #+EXPORT_EXCLUDE_TAGS: noexport
13
+ #+LINK_UP:
14
+ #+LINK_HOME:
15
+ Freeform
16
+
17
+ This is my todo list, research file, and log record from working on
18
+ the Freeform project.
19
+
20
+ * Future ideas :someday:
21
+ - Add *posts*
22
+ - Enforce uniqueness of url_token
23
+ - Add FeedSync support
24
+ - Auto-recognize URLs
25
+ - Edit in place
26
+ - Import/export of content. I want it to be safe to store real content on the site.
27
+ - Page reordering.
28
+ - AtomPub support.
29
+ - Organization:
30
+ - Move pages around
31
+ - Add tags and navigation by tags
32
+ - Add a breadcrumb bar
33
+
34
+ * TODO Add versioning support :current:feature:
35
+
36
+ ** DONE UI rough-in
37
+ CLOSED: [2009-11-26 Thu]
38
+
39
+ ** DONE Author logging
40
+ CLOSED: [2009-11-27 Fri]
41
+
42
+ ** DONE Version table and model updates
43
+ CLOSED: [2009-11-28 Sat 22:40]
44
+ CLOCK: [2009-11-28 Sat 21:35]--[2009-11-28 Sat 22:40] => 1:05
45
+ CLOCK: [2009-11-28 Sat 21:01]--[2009-11-28 Sat 21:25] => 0:24
46
+ CLOCK: [2009-11-28 Sat 19:46]--[2009-11-28 Sat 20:54] => 1:08
47
+ CLOCK: [2009-11-28 Sat 14:38]--[2009-11-28 Sat 15:08] => 0:30
48
+ CLOCK: [2009-11-28 Sat 13:21]--[2009-11-28 Sat 14:37] => 1:16
49
+
50
+ OK, my current thinking is to have each idea have many Changes. A
51
+ change has many change records. A change record is a list of
52
+ specific attributes that change, and includes the old and the new
53
+ values. I'll use callbacks on the Idea model to maintain the
54
+ changes.
55
+
56
+
57
+ *** DONE Create version method
58
+ CLOSED: [2009-11-28 Sat 22:40]
59
+
60
+ *** DONE Make current method
61
+ CLOSED: [2009-11-28 Sat 22:40]
62
+
63
+ ** Update pages controller
64
+
65
+ *** DONE Show versions
66
+ CLOSED: [2009-11-30 Mon 00:34]
67
+ CLOCK: [2009-11-29 Sun 21:27]--[2009-11-29 Sun 21:54] => 0:27
68
+ CLOCK: [2009-11-29 Sun 15:40]--[2009-11-29 Sun 15:44] => 0:04
69
+ CLOCK: [2009-11-28 Sat 22:44]--[2009-11-28 Sat 23:50] => 1:06
70
+
71
+ I'm now at the point where I *list* versions, but I can't show
72
+ them.
73
+
74
+ - [X] I currently suspect that I broke my version recovery code
75
+ when I switched the order of the idea_changes. I need to
76
+ investigate why nothing's failing in the tests; I expected
77
+ failures. Possible addition to test: start looking at those
78
+ version numbers.
79
+
80
+ OK, here's what was going on: In the test, you need to
81
+ reload the idea_changes array from the database to get the
82
+ database sort order. I also make sure I do this inside the
83
+ Idea methods.
84
+
85
+ **** DONE Write a test for Idea::attributes_for_change
86
+ CLOSED: [2009-11-29 Sun 23:59]
87
+ CLOCK: [2009-11-29 Sun 23:47]--[2009-11-29 Sun 23:58] => 0:11
88
+ CLOCK: [2009-11-29 Sun 22:02]--[2009-11-29 Sun 23:42] => 1:40
89
+ CLOCK: [2009-11-29 Sun 21:54]--[2009-11-29 Sun 21:56] => 0:02
90
+
91
+ *** DONE Write integration tests that cover versions.
92
+ CLOSED: [2009-12-11 Fri 23:25]
93
+ CLOCK: [2009-12-11 Fri 20:27]--[2009-12-11 Fri 23:25] => 2:58
94
+
95
+ *** DONE Recover versions
96
+ CLOSED: [2009-12-12 Sat 22:09]
97
+ CLOCK: [2009-12-12 Sat 21:02]--[2009-12-12 Sat 22:09] => 1:07
98
+ CLOCK: [2009-12-12 Sat 20:13]--[2009-12-12 Sat 21:00] => 0:47
99
+
100
+ *** DONE Move to recycle bin
101
+ CLOSED: [2009-12-12 Sat 22:59]
102
+ CLOCK: [2009-12-12 Sat 22:23]--[2009-12-12 Sat 22:59] => 0:36
103
+
104
+ Note I'm avoiding logging delete operations because I'm presuming
105
+ there will be a recycle bin, and therefore the *pages* controller
106
+ will never actually delete files. At some point, when I want to
107
+ support full FeedSync, I'll need to tackle this.
108
+
109
+ The other timebomb: I don't know how well my logging scheme will
110
+ work when pages move. I don't yet know if I will address this in
111
+ the current sprint.