tiny_wiki 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af5c72a41a3d369a441ccc793dc7b2d3c7740859bea4d5dc3807731b4ce72441
4
- data.tar.gz: a9811b3e5d374cf0108561274c2ee58e333afb5e703cbbb2c75bccd629b359d4
3
+ metadata.gz: 903269ded1ae9f2bb397a82fc2fbb9ffba908bbfd201c3e24f95663dd2e6f604
4
+ data.tar.gz: b8a0d910250d1862c1438127e9a3e19c3e0a6dbfeb255ed8486e62754d8539cd
5
5
  SHA512:
6
- metadata.gz: 3c5d3f6c6d849c6790f8936c86e1a424faca750d32ec9f0dafefa29e6347b1f26b6df5b0c742c9aa51980be89496dbb2a742ea113281bc5dc592e2e5982b2c57
7
- data.tar.gz: a34c9d2b61a26389a30eca5a4801f516724b311f32102df402814cae8dee85efb6479dfcb7337ccde8334c5112c34b6f7a6b67ac971d9d653c26e4574ca2c26c
6
+ metadata.gz: 2c7dddd80cad267b123557bde677c44d1e525f8001fb03938c89a03d8d8ee10bfda3f02182f9f29aae3aecdae06587f12b8637a64cf6a03ae129bb05b2c0df60
7
+ data.tar.gz: e26ccab0193a60426a29af24c1a65c06d587aae683d79f1584c481e448078518d4507e03d99d4d000cd6b6270c83eed29f045097a4f558d28e8f1497a33a2f5b
data/exe/tiny_wiki_server CHANGED
@@ -17,6 +17,10 @@ OptionParser.new do |opts|
17
17
  options[:bind] = b
18
18
  end
19
19
 
20
+ opts.on("-d", "--debug", "Enable debug messages (verbose logging)") do |d|
21
+ options[:debug] = d
22
+ end
23
+
20
24
  opts.on("-h", "--help", "Prints this help") do
21
25
  puts opts
22
26
  exit
@@ -45,6 +49,9 @@ TinyWiki::App.set :wiki_root, File.expand_path(wiki_directory)
45
49
  TinyWiki::App.set :port, options[:port] if options[:port]
46
50
  TinyWiki::App.set :bind, options[:bind] if options[:bind]
47
51
 
52
+ # Set the debug flag in the Sinatra application settings
53
+ TinyWiki::App.set :debug, options[:debug] if options[:debug]
54
+
48
55
  puts "Starting TinyWiki server..."
49
56
  puts "Wiki root: #{TinyWiki::App.settings.wiki_root}"
50
57
  puts "Listening on #{TinyWiki::App.settings.bind}:#{TinyWiki::App.settings.port}"
data/lib/tiny_wiki/app.rb CHANGED
@@ -19,16 +19,38 @@ module TinyWiki
19
19
  # Enable sessions for flash messages (optional, but good for feedback)
20
20
  enable :sessions
21
21
 
22
+ # Default debug setting
23
+ set :debug, false
24
+
25
+ # Helper for conditional debug logging
26
+ def debug_log(message)
27
+ puts "DEBUG: #{message}" if settings.debug
28
+ end
29
+
22
30
  # Custom Redcarpet renderer to handle wiki links (e.g., [[Page Name]])
23
31
  class WikiLinkRenderer < Redcarpet::Render::HTML
24
32
  # The postprocess method is called after all other rendering is complete.
25
33
  # We use it to find and replace our custom wiki link syntax.
26
34
  def postprocess(full_document)
27
35
  full_document.gsub(/\[\[(.*?)\]\]/) do
28
- page_name = $1.strip # Get the text inside the brackets
29
- # Sanitize page name for URL: replace spaces with underscores, then URI encode
30
- url_safe_page_name = URI.encode_www_form_component(page_name.gsub(' ', '_'))
31
- "<a href=\"/#{url_safe_page_name}\">#{page_name}</a>"
36
+ raw_page_path = $1.strip # e.g., "Folder/Page Name"
37
+
38
+ # Split the path into components
39
+ path_components = raw_page_path.split('/')
40
+
41
+ # Sanitize each component and convert spaces to underscores for the URL
42
+ # Then URI encode each component
43
+ url_safe_components = path_components.map do |comp|
44
+ # Replace spaces with underscores for URL segment
45
+ sanitized_comp = comp.gsub(' ', '_')
46
+ # URI encode the individual component
47
+ URI.encode_www_form_component(sanitized_comp)
48
+ end
49
+
50
+ # Rejoin with '/' to form the URL path
51
+ url_path = url_safe_components.join('/')
52
+
53
+ "<a href=\"/#{url_path}\">#{raw_page_path}</a>"
32
54
  end
33
55
  end
34
56
  end
@@ -36,7 +58,7 @@ module TinyWiki
36
58
  # Markdown renderer setup
37
59
  # Create a Redcarpet renderer that uses HTML with code highlighting and auto-links.
38
60
  # The `fenced_code_blocks` and `autolink` extensions are common and useful.
39
- markdown_renderer = WikiLinkRenderer.new(
61
+ markdown_renderer = WikiLinkRenderer.new( # Use our custom renderer here
40
62
  filter_html: true,
41
63
  hard_wrap: true,
42
64
  link_attributes: { rel: "nofollow", target: "_blank" },
@@ -57,12 +79,15 @@ module TinyWiki
57
79
  )
58
80
 
59
81
  # Helper method to get the full path to a markdown file
60
- # `page_name` is expected to be URL-decoded and safe for filenames.
61
- def wiki_file_path(page_name)
62
- # Ensure the page name doesn't contain directory traversal attempts
63
- # This is a basic sanitization. For production, more robust checks are needed.
64
- sanitized_page_name = page_name.gsub(/[^a-zA-Z0-9_\-]/, '') # Allow only alphanumeric, underscore, hyphen
65
- File.join(settings.wiki_root, "#{sanitized_page_name}.md")
82
+ # `page_path` is expected to be URL-decoded and can contain slashes.
83
+ def wiki_file_path(page_path)
84
+ # Normalize path to prevent directory traversal (e.g., /foo/../bar)
85
+ # Split by '/' and reject empty components, '.' and '..'.
86
+ # Then re-join to form a safe relative path.
87
+ safe_components = page_path.split('/').reject { |c| c.empty? || c == '.' || c == '..' }
88
+
89
+ # Reconstruct the path. File.join handles OS-specific separators.
90
+ File.join(settings.wiki_root, "#{safe_components.join('/')}.md")
66
91
  end
67
92
 
68
93
  # Helper method to read the content of a wiki page
@@ -84,10 +109,14 @@ module TinyWiki
84
109
  @@markdown.render(markdown_content)
85
110
  end
86
111
 
87
- # Helper to get all wiki pages (filenames without extension)
112
+ # Helper to get all wiki pages (filenames without extension, including paths)
88
113
  def all_wiki_pages
89
- Dir.glob(File.join(settings.wiki_root, '*.md')).map do |file|
90
- File.basename(file, '.md')
114
+ # Find all .md files recursively within the wiki_root
115
+ Dir.glob(File.join(settings.wiki_root, '**', '*.md')).map do |file_path|
116
+ # Get the path relative to wiki_root and remove the .md extension
117
+ # Example: /path/to/wiki_root/Folder/Page.md -> Folder/Page
118
+ relative_path_with_ext = file_path.sub("#{settings.wiki_root}/", '')
119
+ relative_path_with_ext.sub(/\.md$/, '')
91
120
  end.sort
92
121
  rescue Errno::ENOENT
93
122
  # If the wiki_root directory doesn't exist yet, return an empty array
@@ -101,46 +130,71 @@ module TinyWiki
101
130
  redirect to('/Home')
102
131
  end
103
132
 
133
+ # Handle favicon.ico requests directly to avoid treating them as wiki pages
134
+ get '/favicon.ico' do
135
+ # You can serve an actual favicon.ico file here if you have one.
136
+ # For now, we'll just return a 404 to prevent redirection.
137
+ status 404
138
+ '' # Return empty body
139
+ end
140
+
141
+ # Handle Chrome DevTools specific requests
142
+ get '/.well-known/appspecific/com.chrome.devtools.json' do
143
+ status 404
144
+ '' # Return empty body
145
+ end
146
+
104
147
  # List all wiki pages
105
148
  get '/_list' do
106
149
  @pages = all_wiki_pages
107
150
  erb :list # Render a 'list.erb' template (you'll need to create this)
108
151
  end
109
152
 
110
- # Display a wiki page
111
- get '/:page_name' do
112
- @page_name = URI.decode_www_form_component(params[:page_name])
113
- @markdown_content = read_page(@page_name)
114
-
115
- if @markdown_content
116
- @html_content = markdown_to_html(@markdown_content)
117
- erb :show # Render 'show.erb'
118
- else
119
- # Page not found, redirect to edit page
120
- session[:message] = "Page '#{@page_name}' does not exist. Create it!"
121
- redirect to("/#{@page_name}/edit")
122
- end
123
- end
124
-
125
153
  # Show the edit form for a wiki page
126
- get '/:page_name/edit' do
127
- @page_name = URI.decode_www_form_component(params[:page_name])
154
+ # The splat parameter `*page_path` will match multiple path segments, including slashes.
155
+ get '/*page_path/edit' do
156
+ @page_name = URI.decode_www_form_component(params[:page_path])
128
157
  @markdown_content = read_page(@page_name) || "" # Empty string if new page
129
- erb :edit # Render 'edit.erb'
158
+ debug_log "Rendering edit form for page: #{@page_name}" # DEBUG
159
+ erb :edit
130
160
  end
131
161
 
132
162
  # Save the content of a wiki page
133
- post '/:page_name' do
134
- @page_name = URI.decode_www_form_component(params[:page_name])
163
+ # The splat parameter `*page_path` will match multiple path segments, including slashes.
164
+ post '/*page_path' do
165
+ @page_name = URI.decode_www_form_component(params[:page_path])
135
166
  new_content = params[:content]
167
+ debug_log "POST request to save page: #{@page_name}" # DEBUG
168
+ debug_log "Content received: #{new_content.inspect}" # DEBUG
136
169
 
137
170
  if new_content && !new_content.strip.empty?
138
171
  write_page(@page_name, new_content)
139
172
  session[:message] = "Page '#{@page_name}' saved successfully!"
173
+ debug_log "Page saved, redirecting to /#{@page_name}" # DEBUG
140
174
  redirect to("/#{@page_name}")
141
175
  else
142
176
  session[:message] = "Page content cannot be empty!"
143
- redirect to("/#{@page_name}/edit") # Redirect back to edit with error
177
+ debug_log "Empty content, redirecting to /#{@page_name}/edit" # DEBUG
178
+ redirect to("/#{@page_name}/edit")
179
+ end
180
+ end
181
+
182
+ # Display a wiki page
183
+ # The splat parameter `*page_path` will match multiple path segments, including slashes.
184
+ get '/*page_path' do
185
+ @page_name = URI.decode_www_form_component(params[:page_path])
186
+ @markdown_content = read_page(@page_name)
187
+
188
+ if @markdown_content
189
+ @html_content = markdown_to_html(@markdown_content)
190
+ erb :show
191
+ else
192
+ # Page not found, redirect to edit page
193
+ session[:message] = "Page '#{@page_name}' does not exist. Create it!"
194
+ # Ensure the page_name doesn't already end with '/edit' before redirecting
195
+ clean_page_name_for_redirect = @page_name.sub(/\/edit$/, '')
196
+ debug_log "Redirecting to edit for non-existent page: /#{clean_page_name_for_redirect}/edit" # DEBUG
197
+ redirect to("/#{clean_page_name_for_redirect}/edit")
144
198
  end
145
199
  end
146
200
 
@@ -1,6 +1,6 @@
1
1
  <h1>Editing <%= @page_name.empty? ? 'New Page' : @page_name %></h1>
2
2
 
3
- <form action="/<%= URI.encode_www_form_component(@page_name) %>" method="post">
3
+ <form action="<%= to(@page_name) %>" method="post">
4
4
  <textarea name="content"><%= @markdown_content %></textarea><br>
5
5
  <input type="submit" value="Save Page">
6
6
  </form>
@@ -5,7 +5,7 @@
5
5
  <% else %>
6
6
  <ul>
7
7
  <% @pages.each do |page| %>
8
- <li><a href="/<%= URI.encode_www_form_component(page) %>"><%= page %></a></li>
8
+ <li><a href="/<%= page %>"><%= page %></a></li>
9
9
  <% end %>
10
10
  </ul>
11
11
  <% end %>
@@ -1,5 +1,5 @@
1
1
  # Defines the version of the gem.
2
2
 
3
3
  module TinyWiki
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiny_wiki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Yuzwa