org-ruby 0.2.0 → 0.3.0

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