markdownr 0.7.2 → 0.8.1

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: 6d5ca823262d9a08f16b3b6d7a569708cf443e3602afde1eb70c473be51c82f8
4
- data.tar.gz: 708b342c781158b34a5e0ecc9117dd84a497f4abb0415d80e7748f2867124369
3
+ metadata.gz: e25bef09e610cf90ddade4977a1ab04e69c5eff89e1904e7f25edebeacd11d05
4
+ data.tar.gz: ef7183813e31254cc73a8be5776e445dc67830c3387629724c3110707205ed50
5
5
  SHA512:
6
- metadata.gz: 8c85abe0fcdf961cfe3869ff3f770b5ac803c6ba861cf9f1164ff4d583c02a01ecf37949fe8ff435bc4e8a0b6e17ee9506a3907b815f5989b4d78692b8399a5e
7
- data.tar.gz: bdc41fdf3128d47ff1c55f38aff3f94e576fc906f83e511c661035a2f206dd05ad8d6fa7c6ca4e988a4edc6de92d22b9dfe30a1929db9b4fcb84a843564620d6
6
+ metadata.gz: e9528e7bf4f77ebf68486cf0ae3ac72042084365a6e8853a0ea638b6af1bc7edb2986c46ce0612c42880e38c34e9f169ce5ec93759af79253ad93a0f7f5d38ed
7
+ data.tar.gz: 4ccd4fac98ce2a4ce78d04bc1dec843be9648baa949cc5510f8da559aeb2b59d8db5a980b5a4da50cd60873f5c15662e066e793b0a151da14723e894056bc8e7
@@ -1,4 +1,4 @@
1
- FROM ruby:3.4-slim
1
+ FROM ruby:3.4.5-slim
2
2
  RUN apt-get update && apt-get install -y build-essential && gem install markdownr
3
3
  WORKDIR /data
4
4
  CMD ["markdownr", "--behind-proxy", "-b", "0.0.0.0", "/data"]
data/bin/markdownr CHANGED
@@ -32,6 +32,14 @@ OptionParser.new do |opts|
32
32
  options[:behind_proxy] = true
33
33
  end
34
34
 
35
+ opts.on("--admin", "Grant admin access to every visitor (use only on trusted local networks)") do
36
+ options[:admin_all] = true
37
+ end
38
+
39
+ opts.on("--admin-only", "Block all routes except /admin/login until logged in as admin") do
40
+ options[:admin_only] = true
41
+ end
42
+
35
43
  opts.on("-i", "--index-file FILENAME", "Render this file instead of the directory listing when present (e.g. index.md, moc.md)") do |f|
36
44
  options[:index_file] = f
37
45
  end
@@ -48,6 +56,18 @@ OptionParser.new do |opts|
48
56
  options[:verbose] = true
49
57
  end
50
58
 
59
+ opts.on("--default-vim", "Open the in-browser editor in vim mode by default (per-user toggle still wins via localStorage)") do
60
+ options[:default_vim] = true
61
+ end
62
+
63
+ opts.on("--allow-editor", "Enable the in-browser file editor (markdown / source). Without this flag, the Edit button is hidden and all editor write/preview/source routes return errors, even for admins.") do
64
+ options[:allow_editor] = true
65
+ end
66
+
67
+ opts.on("--allow-csv-editor", "Enable CSV editing (row update, duplicate, delete, add-on actions). Without this flag, CSV tables are forced read-only on the server and in the UI, even for admins.") do
68
+ options[:allow_csv_editor] = true
69
+ end
70
+
51
71
  opts.on("--plugin NAME", "Enable a plugin by name (can be specified multiple times)") do |name|
52
72
  options[:plugin_overrides] = (options[:plugin_overrides] || {}).merge(
53
73
  name => (options.dig(:plugin_overrides, name) || {}).merge("enabled" => true)
@@ -58,6 +78,14 @@ OptionParser.new do |opts|
58
78
  (options[:plugin_dirs] ||= []) << d
59
79
  end
60
80
 
81
+ opts.on("--follow-link PATH", Array, "Allow this symlink (inside the served dir) to escape to its target. Repeatable; comma-separated values also accepted.") do |paths|
82
+ (options[:follow_links] ||= []).concat(paths)
83
+ end
84
+
85
+ opts.on("--unhide ENTRY", "Show a normally-hidden entry (repeatable). Bare name matches anywhere; @/path is project-root-anchored; multi-segment narrows the listing.") do |v|
86
+ (options[:unhide] ||= []) << v
87
+ end
88
+
61
89
  opts.on("-v", "--version", "Show version") do
62
90
  puts "markdownr #{MarkdownServer::VERSION}"
63
91
  exit
@@ -74,18 +102,39 @@ end
74
102
 
75
103
  MarkdownServer::App.set :root_dir, dir
76
104
  MarkdownServer::App.set :behind_proxy, options[:behind_proxy] || false
105
+ MarkdownServer::App.set :admin_all, options[:admin_all] || false
106
+ MarkdownServer::App.set :admin_only, options[:admin_only] || false
77
107
  MarkdownServer::App.set :custom_title, options[:title]
78
108
  MarkdownServer::App.set :allow_robots, options[:allow_robots] || false
79
109
  MarkdownServer::App.set :index_file, options[:index_file]
80
110
  MarkdownServer::App.set :link_tooltips, options.fetch(:link_tooltips, true)
81
111
  MarkdownServer::App.set :hard_wrap, options.fetch(:hard_wrap, true)
82
112
  MarkdownServer::App.set :verbose, options[:verbose] || false
113
+ MarkdownServer::App.set :default_vim, options[:default_vim] || false
114
+ MarkdownServer::App.set :allow_editor, options[:allow_editor] || false
115
+ MarkdownServer::App.set :allow_csv_editor, options[:allow_csv_editor] || false
83
116
  MarkdownServer::App.set :port, options[:port]
84
117
  MarkdownServer::App.set :bind, options[:bind]
85
118
  MarkdownServer::App.set :server_settings, { max_threads: options[:threads], min_threads: 1 }
86
119
  MarkdownServer::App.set :plugin_overrides, options[:plugin_overrides] || {}
87
120
  MarkdownServer::App.set :plugin_dirs, options[:plugin_dirs] || []
88
121
 
122
+ root_real = File.realpath(dir)
123
+ followed_links = (options[:follow_links] || []).filter_map do |p|
124
+ expanded = File.expand_path(p, dir)
125
+ unless File.exist?(expanded)
126
+ $stderr.puts "Warning: --follow-link path does not exist, skipping: #{p}"
127
+ next nil
128
+ end
129
+ link_real = File.realpath(expanded)
130
+ unless expanded == root_real || expanded.start_with?("#{root_real}/")
131
+ $stderr.puts "Warning: --follow-link path is outside the served dir, skipping: #{p}"
132
+ next nil
133
+ end
134
+ link_real
135
+ end.uniq
136
+ MarkdownServer::App.set :followed_links, followed_links
137
+
89
138
  # Load .markdownr.yml popup settings
90
139
  config_path = File.join(dir, ".markdownr.yml")
91
140
  if File.exist?(config_path)
@@ -101,6 +150,36 @@ if File.exist?(config_path)
101
150
  existing = MarkdownServer::App.settings.plugin_dirs
102
151
  MarkdownServer::App.set :plugin_dirs, (yaml["plugin_dirs"] + existing).uniq
103
152
  end
153
+
154
+ if yaml && yaml.key?("admin_only") && !options[:admin_only]
155
+ MarkdownServer::App.set :admin_only, yaml["admin_only"] == true
156
+ end
157
+
158
+ # Load CSV database config (top-level key or legacy plugin key)
159
+ csv_db_paths = yaml&.dig("csv_databases") || yaml&.dig("plugins", "csv_browser", "databases")
160
+ if csv_db_paths.is_a?(Array) && !csv_db_paths.empty?
161
+ require_relative "../lib/markdown_server/csv_browser/config_loader"
162
+ loader = MarkdownServer::CsvBrowser::ConfigLoader.new(csv_db_paths, dir)
163
+ MarkdownServer::App.set :csv_browser_config, loader
164
+ end
165
+
166
+ # Load CSV add-on files (absolute paths keyed by add-on name)
167
+ csv_addons = yaml&.dig("csv_addons")
168
+ if csv_addons.is_a?(Hash) && !csv_addons.empty?
169
+ require_relative "../lib/markdown_server/csv_browser/addon_registry"
170
+ MarkdownServer::CsvBrowser::CsvAddonRegistry.load(csv_addons, dir)
171
+ end
172
+ end
173
+
174
+ # Compile and apply unhide rules (YAML + CLI, additive merge).
175
+ yaml_unhide = (defined?(yaml) && yaml.is_a?(Hash) && yaml["unhide"].is_a?(Array)) ? yaml["unhide"] : []
176
+ combined_unhide = (yaml_unhide + (options[:unhide] || [])).uniq
177
+ unless combined_unhide.empty?
178
+ begin
179
+ MarkdownServer::App.set :unhide_rules, MarkdownServer::Unhide.compile(combined_unhide)
180
+ rescue MarkdownServer::Unhide::CompileError => e
181
+ abort "Invalid unhide config: #{e.message}"
182
+ end
104
183
  end
105
184
 
106
185
  MarkdownServer::App.load_plugins!
@@ -0,0 +1,39 @@
1
+ # Orchestrates local markdownr servers.
2
+ #
3
+ # Start: docker compose -f bin/markdownr-servers.yaml up -d --build
4
+ # Restart: docker compose -f bin/markdownr-servers.yaml restart
5
+ # Rebuild (after publishing a new markdownr gem):
6
+ # docker compose -f bin/markdownr-servers.yaml up -d --build --force-recreate
7
+ # Stop: docker compose -f bin/markdownr-servers.yaml down
8
+ #
9
+ x-markdownr: &markdownr
10
+ build:
11
+ context: .
12
+ dockerfile: Dockerfile.markdownr
13
+ restart: unless-stopped
14
+ command: ["markdownr", "--behind-proxy", "-b", "0.0.0.0", "/data"]
15
+
16
+ services:
17
+ lofts:
18
+ <<: *markdownr
19
+ container_name: markdownr-lofts
20
+ ports:
21
+ - "4444:4567"
22
+ volumes:
23
+ - ~/code/claude/lofts/projects:/data
24
+
25
+ bible-repo:
26
+ <<: *markdownr
27
+ container_name: markdownr-bible-repo
28
+ ports:
29
+ - "4569:4567"
30
+ volumes:
31
+ - ~/code/claude/bible/bible-repo:/data
32
+
33
+ scripture:
34
+ <<: *markdownr
35
+ container_name: markdownr-scripture
36
+ ports:
37
+ - "4568:4567"
38
+ volumes:
39
+ - ~/code/claude/bible/scripture/resource/books/bible:/data
data/bin/start-claude ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ claude --chrome