doing 1.0.93 → 2.0.2.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS +19 -0
  3. data/CHANGELOG.md +590 -0
  4. data/COMMANDS.md +1181 -0
  5. data/Gemfile +2 -0
  6. data/Gemfile.lock +110 -0
  7. data/LICENSE +23 -0
  8. data/README.md +15 -699
  9. data/Rakefile +79 -0
  10. data/_config.yml +1 -0
  11. data/bin/doing +1012 -486
  12. data/doing.fish +278 -0
  13. data/doing.gemspec +34 -0
  14. data/doing.rdoc +1759 -0
  15. data/example_plugin.rb +209 -0
  16. data/generate_completions.sh +4 -0
  17. data/img/doing-colors.jpg +0 -0
  18. data/img/doing-printf-wrap-800.jpg +0 -0
  19. data/img/doing-show-note-formatting-800.jpg +0 -0
  20. data/lib/completion/_doing.zsh +151 -0
  21. data/lib/completion/doing.bash +416 -0
  22. data/lib/completion/doing.fish +278 -0
  23. data/lib/doing/array.rb +8 -0
  24. data/lib/doing/cli_status.rb +66 -0
  25. data/lib/doing/colors.rb +136 -0
  26. data/lib/doing/configuration.rb +310 -0
  27. data/lib/doing/errors.rb +102 -0
  28. data/lib/doing/hash.rb +31 -0
  29. data/lib/doing/hooks.rb +59 -0
  30. data/lib/doing/item.rb +155 -0
  31. data/lib/doing/log_adapter.rb +342 -0
  32. data/lib/doing/markdown_document_listener.rb +174 -0
  33. data/lib/doing/note.rb +59 -0
  34. data/lib/doing/pager.rb +95 -0
  35. data/lib/doing/plugin_manager.rb +208 -0
  36. data/lib/doing/plugins/export/csv_export.rb +48 -0
  37. data/lib/doing/plugins/export/html_export.rb +83 -0
  38. data/lib/doing/plugins/export/json_export.rb +140 -0
  39. data/lib/doing/plugins/export/markdown_export.rb +85 -0
  40. data/lib/doing/plugins/export/taskpaper_export.rb +34 -0
  41. data/lib/doing/plugins/export/template_export.rb +141 -0
  42. data/lib/doing/plugins/import/cal_to_json.scpt +0 -0
  43. data/lib/doing/plugins/import/calendar_import.rb +76 -0
  44. data/lib/doing/plugins/import/doing_import.rb +144 -0
  45. data/lib/doing/plugins/import/timing_import.rb +78 -0
  46. data/lib/doing/string.rb +346 -0
  47. data/lib/doing/symbol.rb +16 -0
  48. data/lib/doing/time.rb +18 -0
  49. data/lib/doing/util.rb +186 -0
  50. data/lib/doing/version.rb +1 -1
  51. data/lib/doing/wwid.rb +1831 -2358
  52. data/lib/doing/wwidfile.rb +117 -0
  53. data/lib/doing.rb +43 -3
  54. data/lib/examples/commands/wiki.rb +80 -0
  55. data/lib/examples/plugins/hooks.rb +22 -0
  56. data/lib/examples/plugins/say_export.rb +202 -0
  57. data/lib/examples/plugins/templates/wiki.css +169 -0
  58. data/lib/examples/plugins/templates/wiki.haml +27 -0
  59. data/lib/examples/plugins/templates/wiki_index.haml +18 -0
  60. data/lib/examples/plugins/wiki_export.rb +87 -0
  61. data/lib/templates/doing-markdown.erb +5 -0
  62. data/man/doing.1 +964 -0
  63. data/man/doing.1.html +711 -0
  64. data/man/doing.1.ronn +600 -0
  65. data/package-lock.json +3 -0
  66. data/rdoc_to_mmd.rb +42 -0
  67. data/rdocfixer.rb +13 -0
  68. data/scripts/generate_bash_completions.rb +210 -0
  69. data/scripts/generate_fish_completions.rb +201 -0
  70. data/scripts/generate_zsh_completions.rb +164 -0
  71. metadata +82 -7
  72. data/lib/doing/helpers.rb +0 -191
  73. data/lib/doing/markdown_export.rb +0 -16
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ class Items < Array
5
+ def from(path)
6
+ return [] unless path
7
+ path = File.expand_path(path)
8
+
9
+ if File.exist?(path) && File.file?(path) && File.stat(path).size.positive?
10
+ input = IO.read(File.expand_path(input))
11
+ input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
12
+ end
13
+
14
+ section = 'Uncategorized'
15
+ lines = input.split(/[\n\r]/)
16
+ current = 0
17
+
18
+ lines.each do |line|
19
+ next if line =~ /^\s*$/
20
+
21
+ if line =~ /^(\S[\S ]+):\s*(@\S+\s*)*$/
22
+ section = Regexp.last_match(1)
23
+ @sections << { original: line, title: section }
24
+ current = 0
25
+ elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*)/
26
+ date = Regexp.last_match(1).strip
27
+ title = Regexp.last_match(2).strip
28
+ item = Item.new(date, title, section)
29
+ @items.push(item)
30
+ current += 1
31
+ elsif current.zero?
32
+ # if content[section][:items].length - 1 == current
33
+ @other_content_top.push(line)
34
+ elsif line =~ /^\S/
35
+ @other_content_bottom.push(line)
36
+ else
37
+ prev_item = @items[current - 1]
38
+ prev_item.note = Note.new unless prev_item.note
39
+
40
+ prev_item.note.add(line)
41
+ # end
42
+ end
43
+ end
44
+ Hooks.trigger :post_read, self
45
+ end
46
+
47
+ def section_titles
48
+ @sections.map { |s| s[:title] }
49
+ end
50
+
51
+ ##
52
+ ## @brief Adds a section.
53
+ ##
54
+ ## @param title (String) The new section title
55
+ ##
56
+ def add_section(title)
57
+ if section_titles.include?(title.cap_first)
58
+ Doing.logger.debug('Skipped': 'Section already exists')
59
+ return
60
+ end
61
+
62
+ @sections << { original: "#{title}:", title: title }
63
+ Doing.logger.info('Added section:', %("#{title.cap_first}"))
64
+ end
65
+
66
+ ##
67
+ ## @brief Attempt to match a string with an existing section
68
+ ##
69
+ ## @param frag (String) The user-provided string
70
+ ## @param guessed (Boolean) already guessed and failed
71
+ ##
72
+ def guess_section(frag, guessed: false, suggest: false)
73
+ return 'All' if frag =~ /^all$/i
74
+ frag ||= wwid.config['current_section']
75
+
76
+ @sections.each { |sect| return sect[:title].cap_first if frag.downcase == sect[:title].downcase }
77
+
78
+ section = false
79
+ re = frag.split('').join('.*?')
80
+ sections.each do |sect|
81
+ next unless sect =~ /#{re}/i
82
+
83
+ Doing.logger.debug('Section match:', %(Assuming "#{sect}" from "#{frag}"))
84
+ section = sect
85
+ break
86
+ end
87
+
88
+ return section if suggest
89
+
90
+ unless section || guessed
91
+ alt = WWID.guess_view(frag, guessed: true, suggest: true)
92
+ if alt
93
+ meant_view = WWID.yn("Did you mean `doing view #{alt}`?", default_response: 'n')
94
+ raise Errors::InvalidSection, "Run again with `doing view #{alt}`" if meant_view
95
+ end
96
+
97
+ res = WWID.yn("Section #{frag} not found, create it", default_response: 'n')
98
+
99
+ if res
100
+ add_section(frag.cap_first)
101
+ WWID.write(@doing_file)
102
+ return frag.cap_first
103
+ end
104
+
105
+ raise Errors::InvalidSection, "Unknown section: #{frag}"
106
+ end
107
+ section ? section.cap_first : guessed
108
+ end
109
+
110
+ def section_items(section)
111
+ section = guess_section(section)
112
+ return @items if section =~ /all/i
113
+
114
+ @items.filter { |i| i.section == section }
115
+ end
116
+ end
117
+ end
data/lib/doing.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'doing/version.rb'
1
+ # frozen_string_literal: true
2
+
3
+ require 'doing/version'
2
4
  require 'time'
3
5
  require 'date'
4
6
  require 'yaml'
@@ -8,7 +10,45 @@ require 'tempfile'
8
10
  require 'chronic'
9
11
  require 'haml'
10
12
  require 'json'
11
- require 'doing/helpers'
12
- require 'doing/markdown_export'
13
+ require 'logger'
14
+ require 'safe_yaml/load'
15
+ require 'doing/hash'
16
+ require 'doing/colors'
17
+ require 'doing/string'
18
+ require 'doing/time'
19
+ require 'doing/array'
20
+ require 'doing/symbol'
21
+ require 'doing/util'
22
+ require 'doing/configuration'
23
+ require 'doing/item'
24
+ require 'doing/note'
25
+ require 'doing/wwidfile'
13
26
  require 'doing/wwid'
27
+ require 'doing/log_adapter'
28
+ require 'doing/errors'
29
+ require 'doing/hooks'
30
+ require 'doing/plugin_manager'
31
+ require 'doing/pager'
14
32
  # require 'doing/markdown_document_listener'
33
+
34
+ # Main doing module
35
+ module Doing
36
+ class << self
37
+ #
38
+ # @brief Fetch the logger
39
+ #
40
+ # @return the LogAdapter instance.
41
+ #
42
+ def logger
43
+ @logger ||= LogAdapter.new((ENV['DOING_LOG_LEVEL'] || :info).to_sym)
44
+ end
45
+
46
+ def config
47
+ @config ||= Configuration.new
48
+ end
49
+
50
+ def config_with(file, options = {})
51
+ @config = Configuration.new(file, options: options)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,80 @@
1
+ desc 'Output a tag wiki'
2
+ command :wiki do |c|
3
+ c.desc 'Section to rotate'
4
+ c.arg_name 'SECTION_NAME'
5
+ c.flag %i[s section], default_value: 'All'
6
+
7
+ c.desc 'Tag filter, combine multiple tags with a comma, use with --bool'
8
+ c.arg_name 'TAG'
9
+ c.flag [:tag]
10
+
11
+ c.desc 'Tag boolean (AND,OR,NOT)'
12
+ c.arg_name 'BOOLEAN'
13
+ c.flag %i[b bool], must_match: REGEX_BOOL, default_value: 'OR'
14
+
15
+ c.desc 'Include entries older than date'
16
+ c.arg_name 'DATE_STRING'
17
+ c.flag [:before]
18
+
19
+ c.desc 'Include entries newer than date'
20
+ c.arg_name 'DATE_STRING'
21
+ c.flag [:after]
22
+
23
+ c.desc 'Search filter, surround with slashes for regex (/query/), start with single quote for exact match ("\'query")'
24
+ c.arg_name 'QUERY'
25
+ c.flag [:search]
26
+
27
+ c.desc %(
28
+ Date range to include, or a single day to filter date on.
29
+ Date range argument should be quoted. Date specifications can be natural language.
30
+ To specify a range, use "to" or "through": `doing show --from "monday to friday"`
31
+ )
32
+ c.arg_name 'DATE_OR_RANGE'
33
+ c.flag %i[f from]
34
+
35
+ c.desc 'Only show items with recorded time intervals'
36
+ c.switch [:only_timed], default_value: false, negatable: false
37
+
38
+ c.action do |global, options, args|
39
+ wwid = global[:wwid]
40
+ tags = wwid.tag_groups([], opt: options)
41
+
42
+ wiki = Doing::Plugins.plugins.dig(:export, 'wiki', :class)
43
+
44
+ tags.each do |tag, items|
45
+ export_options = { page_title: tag, is_single: false, options: options }
46
+
47
+ raise RuntimeError, 'Missing plugin "wiki"' unless wiki
48
+
49
+ out = wiki.render(wwid, items, variables: export_options)
50
+
51
+ if out
52
+ FileUtils.mkdir_p('doing_wiki')
53
+ File.open(File.join('doing_wiki', tag + '.html'), 'w') do |f|
54
+ f.puts out
55
+ end
56
+ end
57
+ end
58
+
59
+ template = if wwid.config['export_templates']['wiki_index'] && File.exist?(File.expand_path(wwid.config['export_templates']['wiki_index']))
60
+ IO.read(File.expand_path(wwid.config['export_templates']['wiki_index']))
61
+ else
62
+ wiki.template('wiki_index')
63
+ end
64
+ style = if wwid.config['export_templates']['wiki_css'] && File.exist?(File.expand_path(wwid.config['export_templates']['wiki_css']))
65
+ IO.read(File.expand_path(wwid.config['export_templates']['wiki_css']))
66
+ else
67
+ wiki.template('wiki_css')
68
+ end
69
+ tags_out = tags.map { |t| {url: "#{t}.html"} }
70
+ engine = Haml::Engine.new(template)
71
+ index_out = engine.render(Object.new,
72
+ { :@tags => tags.each_with_object([]) { |(tag, items), arr| arr << { name: tag, count: items.count } }, :@page_title => "Tags wiki", :@style => style })
73
+
74
+ if index_out
75
+ File.open(File.join('doing_wiki', 'index.html'), 'w') do |f|
76
+ f.puts index_out
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ # Hooks.register :post_config do |wwid|
5
+ # wwid.config['twizzle'] = 'Fo shizzle'
6
+ # wwid.write_config(File.expand_path('~/Desktop/wwidconfig.yml'))
7
+ # end
8
+
9
+ # Hooks.register :post_read, priority: 10 do |wwid|
10
+ # Doing.logger.warn('Hook 1:', 'triggered priority 10')
11
+ # Doing.logger.warn('Hook 2:', wwid.config['twizzle'])
12
+ # end
13
+
14
+ # Hooks.register :post_read, priority: 100 do |wwid|
15
+ # Doing.logger.warn('Hook 2:', 'triggered priority 100')
16
+ # end
17
+
18
+ Hooks.register :post_write do |filename|
19
+ res = `/bin/bash /Users/ttscoff/scripts/after_doing.sh`.strip
20
+ Doing.logger.debug('Hooks:', res) unless res =~ /^\.\.\.$/
21
+ end
22
+ end
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ # title: Export plugin example
4
+ # description: Speak the most recent entry (macOS)
5
+ # author: Brett Terpstra
6
+ # url: https://brettterpstra.com
7
+
8
+ # Example
9
+ #
10
+ # doing show -o sayit
11
+ #
12
+ # ## Configuration
13
+ #
14
+ # Change what the plugin says by generating a template with
15
+ # `doing template --type say`, saving it to a file, and
16
+ # putting the path to that file in `export_templates->say` in
17
+ # .doingrc.
18
+ #
19
+ # export_templates:
20
+ # say: /path/to/template.txt
21
+ #
22
+ # Use a different voice by adding a `say_voice` key to your
23
+ # .doingrc. Use `say -v ?` to see available voices.
24
+ #
25
+ # say_voice: Zarvox
26
+
27
+ module Doing
28
+ ##
29
+ ## @brief Plugin class
30
+ ##
31
+ class SayExport
32
+ include Doing::Util
33
+
34
+ #-------------------------------------------------------
35
+ ## Plugin Settings. A plugin must have a self.settings
36
+ ## method that returns a hash with plugin settings.
37
+ ##
38
+ ## trigger: (required) Regular expression to match
39
+ ## FORMAT when used with `--output FORMAT`. Registered
40
+ ## name of plugin must be able to match the trigger, but
41
+ ## alternatives can be included
42
+ ##
43
+ ## templates: (optional) Array of templates this plugin
44
+ ## can export (plugin must have :template method)
45
+ ##
46
+ ## Each template is a hash containing:
47
+ ## - name: display name for template
48
+ ## - trigger: regular expression for
49
+ ## `template --type FORMAT`
50
+ ##
51
+ ## If a template is included, a config key will
52
+ ## automatically be added for the user to override
53
+ ## The config key will be available at:
54
+ ##
55
+ ## wwid.config['export_templates'][PLUGIN_NAME]
56
+ ##
57
+ ## config: (optional) A Hash which will be
58
+ ## added to the main configuration in the plugins section.
59
+ ## Options defined here are included when config file is
60
+ ## created or updated with `config --update`. Use this to
61
+ ## add new configuration keys, not to override existing
62
+ ## ones.
63
+ ##
64
+ ## The configuration keys will be available at:
65
+ ##
66
+ ## wwid.config['plugins'][PLUGIN_NAME][KEY]
67
+ ##
68
+ ## @brief Method to return plugin settings (required)
69
+ ##
70
+ ## @return Hash of settings for this plugin
71
+ ##
72
+ def self.settings
73
+ {
74
+ trigger: 'say(?:it)?',
75
+ templates: [
76
+ { name: 'say', trigger: 'say(?:it)?' }
77
+ ],
78
+ config: {
79
+ 'say_voice' => 'Fiona'
80
+ }
81
+ }
82
+ end
83
+
84
+
85
+ #-------------------------------------------------------
86
+ ## Output a template. Only required if template(s) are
87
+ ## included in settings. The method should return a
88
+ ## string (not output it to the STDOUT).
89
+ ##
90
+ ## @brief Method to return template (optional)
91
+ ##
92
+ ## @param trigger The trigger passed to the
93
+ ## template function. When this
94
+ ## method defines multiple
95
+ ## templates, the trigger can be
96
+ ## used to determine which one is
97
+ ## output.
98
+ ##
99
+ ## @return (String) template contents
100
+ ##
101
+ def self.template(trigger)
102
+ return unless trigger =~ /^say(it)?$/
103
+ 'On %date, you were %title, recorded in section %section%took'
104
+ end
105
+
106
+
107
+ ##
108
+ ## @brief Render data received from an output
109
+ ## command
110
+ ##
111
+ ## @param wwid The wwid object with config
112
+ ## and public methods
113
+ ## @param items An array of items to be output
114
+ ## { <Date>date, <String>title,
115
+ ## <String>section, <Array>note }
116
+ ## @param variables Additional variables including
117
+ ## flags passed to command
118
+ ## (variables[:options])
119
+ ##
120
+ ## @return (String) Rendered output
121
+ ##
122
+ def self.render(wwid, items, variables: {})
123
+ return if items.nil? || items.empty?
124
+
125
+ # the :options key includes the flags passed to the
126
+ # command that called the plugin use `puts
127
+ # variables.inspect` to see properties and methods
128
+ # when run
129
+ opt = variables[:options]
130
+
131
+ # This plugin just grabs the last item in the `items`
132
+ # list (which could be the oldest or newest, depending
133
+ # on the sort order of the command that called the
134
+ # plugin). Most of the time you'll want to use :each
135
+ # or :map to generate output.
136
+ i = items[-1]
137
+
138
+ # Format the item. Items are a hash with 3 keys: date,
139
+ # title, and section (parent section) Start time is in
140
+ # item.date. The wwid object has some methods for
141
+ # calculation and formatting, including
142
+ # wwid.item.end_date to convert the @done
143
+ # timestamp to an end date.
144
+ if opt[:times]
145
+ interval = i.interval
146
+
147
+ if interval
148
+ took = '. You finished on '
149
+ finished_at = i.end_date
150
+ took += finished_at.strftime('%A %B %e at %I:%M%p')
151
+
152
+ d, h, m = wwid.fmt_time(interval)
153
+ took += ' and it took'
154
+ took += " #{d.to_i} days" if d.to_i.positive?
155
+ took += " #{h.to_i} hours" if h.to_i.positive?
156
+ took += " #{m.to_i} minutes" if m.to_i.positive?
157
+ end
158
+ end
159
+
160
+ date = i.date.strftime('%A %B %e at %I:%M%p')
161
+ title = i.title.gsub(/ @done\(.*?\)/, '').gsub(/@/, 'hashtag ')
162
+ tpl = template('say')
163
+
164
+ if wwid.config['export_templates'].key?('say')
165
+ cfg_tpl = wwid.config['export_templates']['say']
166
+ tpl = cfg_tpl unless cfg_tpl.nil? || cfg_tpl.empty?
167
+ end
168
+ output = tpl.dup
169
+ output.gsub!(/%date/, date)
170
+ output.gsub!(/%title/, title)
171
+ output.gsub!(/%section/, i.section)
172
+ output.gsub!(/%took/, took || '')
173
+
174
+ # Debugging output
175
+ # warn "Saying: #{output}"
176
+
177
+ # To provide results on the command line after the
178
+ # command runs, add to the wwid.results array. Results
179
+ # are provided on STDERR unless doing is run with
180
+ # `--stdout`
181
+ Doing.logger.info('Spoke the last entry. Did you hear it?')
182
+
183
+ # This export runs a command for fun, most plugins won't
184
+ voice = wwid.config['plugins']['say']['say_voice'] || 'Alex'
185
+ `say -v "#{voice}" "#{output}"`
186
+
187
+ # Return the result (don't output to terminal with puts or print)
188
+ output
189
+ end
190
+
191
+ # Register the plugin with doing.
192
+ # Doing::Plugins.register 'NAME', TYPE, Class
193
+ #
194
+ # Name should be lowercase, no spaces
195
+ #
196
+ # TYPE is :import or :export
197
+ #
198
+ # Class is the plugin class (e.g. Doing::SayExport), or
199
+ # self if called within the class
200
+ Doing::Plugins.register 'say', :export, self
201
+ end
202
+ end
@@ -0,0 +1,169 @@
1
+ body {
2
+ background: #fff;
3
+ color: #333;
4
+ font-family: Helvetica,arial,freesans,clean,sans-serif;
5
+ font-size: 21px;
6
+ line-height: 1.5;
7
+ text-align: justify;
8
+ }
9
+
10
+ @media only screen and (max-width: 900px) {
11
+ body {
12
+ font-size: calc(12px + 1vw);
13
+ }
14
+
15
+ .date,
16
+ .note {
17
+ font-size: calc(8px + 1vw)!important;
18
+ }
19
+ }
20
+
21
+ h1 {
22
+ margin-bottom: 1em;
23
+ margin-left: .1em;
24
+ position: relative;
25
+ text-align: left;
26
+ }
27
+
28
+ ul {
29
+ list-style-position: outside;
30
+ position: relative;
31
+ text-align: left;
32
+ padding-left: 0;
33
+ }
34
+
35
+ article > ul > li {
36
+ display: grid;
37
+ grid-template-columns: 14ch auto;
38
+ line-height: 1.2;
39
+ list-style-type: none;
40
+ padding-left: 10px;
41
+ position: relative;
42
+ word-break: break-word;
43
+ transition: background .2s ease-in-out;
44
+ }
45
+
46
+ article > ul > li:hover {
47
+ background: rgba(150,150,150,.05);
48
+ }
49
+
50
+ .date {
51
+ color: #7d9ca2;
52
+ font-size: 17px;
53
+ padding: 15px 1ch 0 0;
54
+ text-align: right;
55
+ white-space: nowrap;
56
+ transition: color .2s ease-in-out;
57
+ }
58
+
59
+ .entry {
60
+ border-left: solid 1px #ccc;
61
+ line-height: 1.2;
62
+ padding: 10px 10px 10px 3ch;
63
+ text-indent: -2ch;
64
+ }
65
+
66
+ .tag {
67
+ color: #999;
68
+ transition: color 1s ease-in;
69
+ }
70
+
71
+ .note {
72
+ color: #aaa;
73
+ display: block;
74
+ font-size: 17px;
75
+ line-height: 1.1;
76
+ padding: 1em 0 0 2ch;
77
+ position: relative;
78
+ transition: color .2s ease-in-out;
79
+ }
80
+
81
+ li:hover .note {
82
+ color: #777;
83
+ }
84
+
85
+ li:hover .tag {
86
+ color: rgb(182, 120, 125);
87
+ }
88
+
89
+ li:hover .date {
90
+ color: rgb(100, 169, 165);
91
+ }
92
+
93
+ .note li {
94
+ margin-bottom: .5em;
95
+ list-style: none;
96
+ position: relative;
97
+ }
98
+
99
+ .note li:before {
100
+ color: #ddd;
101
+ content: '\25BA';
102
+ font-size: 12px;
103
+ font-weight: 300;
104
+ left: -3ch;
105
+ position: absolute;
106
+ top: .25em;
107
+ }
108
+
109
+ .time {
110
+ background: #f9fced;
111
+ border-bottom: dashed 1px #ccc;
112
+ color: #729953;
113
+ font-size: 15px;
114
+ margin-right: 4px;
115
+ padding: 0 5px;
116
+ position: relative;
117
+ text-align: right;
118
+ }
119
+
120
+ table td {
121
+ border-bottom: solid 1px #ddd;
122
+ height: 24px;
123
+ }
124
+
125
+ caption {
126
+ border-bottom: solid 1px #aaa;
127
+ margin: 10px 0;
128
+ text-align: left;
129
+ }
130
+
131
+ table {
132
+ margin: 50px 0 0 211px;
133
+ width: 400px;
134
+ }
135
+
136
+ th {
137
+ padding-bottom: 10px;
138
+ }
139
+
140
+ th, td {
141
+ padding-right: 20px;
142
+ }
143
+
144
+ table {
145
+ margin: 50px 0 2em 16ch;
146
+ max-width: 400px;
147
+ }
148
+
149
+ .section {
150
+ border-left: solid 1px rgb(182, 120, 125);
151
+ border-radius: 25px;
152
+ border-right: solid 1px rgb(182, 120, 125);
153
+ color: rgb(182, 120, 125);
154
+ font-size: .8em;
155
+ line-height: 1 !important;
156
+ padding: 0 4px;
157
+ transition: background .4s ease-in, color .4s ease-in;
158
+ }
159
+
160
+ li:hover .section {
161
+ color: #fff;
162
+ background: rgb(182, 120, 125);
163
+ }
164
+
165
+ a:link {
166
+ background-color: rgba(203, 255, 251, .15);
167
+ color: #64a9a5;
168
+ text-decoration: none;
169
+ }
@@ -0,0 +1,27 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %meta{"charset" => "utf-8"}/
5
+ %meta{"content" => "IE=edge,chrome=1", "http-equiv" => "X-UA-Compatible"}/
6
+ %title what are you doing?
7
+ %style= @style
8
+ %body
9
+ %header
10
+ %h1= @page_title
11
+ %p
12
+ %a{ href: 'index.html' }= "[[Home]]"
13
+ %article
14
+ %ul
15
+ - @items.each do |i|
16
+ %li
17
+ %span.date= i[:date]
18
+ %div.entry
19
+ = i[:title]
20
+ %span.section= i[:section]
21
+ - if i[:time] && i[:time] != "00:00:00"
22
+ %span.time= i[:time]
23
+ - if i[:note]
24
+ %ul.note
25
+ - i[:note].map{|n| n.strip }.each do |li|
26
+ %li= li
27
+ = @totals
@@ -0,0 +1,18 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %meta{"charset" => "utf-8"}/
5
+ %meta{"content" => "IE=edge,chrome=1", "http-equiv" => "X-UA-Compatible"}/
6
+ %title= @page_title
7
+ %style= @style
8
+ %body
9
+ %header
10
+ %h1= @page_title
11
+ %article
12
+ %ul
13
+ - @tags.each do |tag|
14
+ %li
15
+ %a{href: "#{tag[:name]}.html"}
16
+ %span.tag= tag[:name]
17
+ %span.count= "(#{tag[:count]})"
18
+