kward 0.70.0 → 0.71.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 +4 -4
- data/.github/workflows/pages.yml +1 -1
- data/CHANGELOG.md +48 -2
- data/Gemfile +2 -0
- data/Gemfile.lock +90 -2
- data/README.md +30 -6
- data/Rakefile +96 -0
- data/doc/agent-tools.md +43 -0
- data/doc/api.md +92 -0
- data/doc/authentication.md +39 -25
- data/doc/configuration.md +1 -15
- data/doc/context-tools.md +70 -0
- data/doc/plugins.md +2 -2
- data/doc/releasing.md +14 -5
- data/doc/rpc.md +3 -11
- data/doc/session-management.md +220 -0
- data/doc/usage.md +7 -8
- data/doc/workspace-tools.md +105 -0
- data/lib/kward/cli/commands.rb +8 -0
- data/lib/kward/cli/openrouter_commands.rb +55 -0
- data/lib/kward/cli/prompt_interface.rb +80 -6
- data/lib/kward/cli/rendering.rb +11 -6
- data/lib/kward/cli/sessions.rb +260 -11
- data/lib/kward/cli/settings.rb +0 -30
- data/lib/kward/cli/slash_commands.rb +24 -6
- data/lib/kward/cli.rb +13 -0
- data/lib/kward/compactor.rb +4 -1
- data/lib/kward/config_files.rb +4 -6
- data/lib/kward/conversation.rb +49 -20
- data/lib/kward/model/client.rb +37 -50
- data/lib/kward/model/context_usage.rb +13 -6
- data/lib/kward/model/model_info.rb +92 -16
- data/lib/kward/model/payloads.rb +2 -0
- data/lib/kward/openrouter_model_cache.rb +120 -0
- data/lib/kward/plugin_registry.rb +47 -1
- data/lib/kward/prompt_interface/banner.rb +16 -51
- data/lib/kward/prompt_interface/composer_controller.rb +60 -87
- data/lib/kward/prompt_interface/composer_renderer.rb +7 -1
- data/lib/kward/prompt_interface/key_handler.rb +31 -10
- data/lib/kward/prompt_interface/layout.rb +2 -2
- data/lib/kward/prompt_interface/prompt_renderer.rb +32 -13
- data/lib/kward/prompt_interface/question_prompt.rb +34 -42
- data/lib/kward/prompt_interface/runtime_state.rb +6 -1
- data/lib/kward/prompt_interface/screen.rb +1 -0
- data/lib/kward/prompt_interface/selection_prompt.rb +513 -54
- data/lib/kward/prompt_interface/transcript_buffer.rb +7 -16
- data/lib/kward/prompt_interface/transcript_renderer.rb +3 -3
- data/lib/kward/prompt_interface.rb +22 -28
- data/lib/kward/prompts/commands.rb +2 -1
- data/lib/kward/prompts.rb +2 -2
- data/lib/kward/rpc/server.rb +3 -8
- data/lib/kward/rpc/session_manager.rb +17 -6
- data/lib/kward/session_store.rb +23 -4
- data/lib/kward/telemetry/logger.rb +5 -3
- data/lib/kward/tool_output_compactor.rb +127 -0
- data/lib/kward/tools/base.rb +8 -2
- data/lib/kward/tools/registry.rb +37 -6
- data/lib/kward/tools/retrieve_tool_output.rb +71 -0
- data/lib/kward/tools/search/web.rb +2 -2
- data/lib/kward/tools/summarize_file_structure.rb +29 -0
- data/lib/kward/tools/tool_call.rb +2 -0
- data/lib/kward/version.rb +1 -1
- data/lib/kward/workspace.rb +58 -2
- data/templates/default/fulldoc/html/css/kward.css +256 -7
- data/templates/default/fulldoc/html/full_list.erb +107 -0
- data/templates/default/fulldoc/html/js/kward.js +161 -2
- data/templates/default/fulldoc/html/setup.rb +8 -0
- data/templates/default/kward_navigation.rb +91 -0
- data/templates/default/layout/html/layout.erb +39 -8
- data/templates/default/layout/html/setup.rb +33 -38
- metadata +13 -3
- data/lib/kward/resources/avatar_kward_logo.rb +0 -50
- data/lib/kward/resources/pixel_logo.rb +0 -232
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require_relative "base"
|
|
2
|
+
|
|
3
|
+
# Namespace for the Kward CLI agent runtime.
|
|
4
|
+
module Kward
|
|
5
|
+
# Model-callable tool wrappers and their argument schemas.
|
|
6
|
+
module Tools
|
|
7
|
+
# Retrieves original tool outputs that were compacted out of model context.
|
|
8
|
+
class RetrieveToolOutput < Base
|
|
9
|
+
DEFAULT_LIMIT = 120
|
|
10
|
+
|
|
11
|
+
# Builds the retrieval tool schema.
|
|
12
|
+
def initialize
|
|
13
|
+
super(
|
|
14
|
+
"retrieve_tool_output",
|
|
15
|
+
"Retrieve original output from a compacted previous tool result.",
|
|
16
|
+
properties: {
|
|
17
|
+
id: { type: "string", description: "Tool output id, for example toolout_abc123." },
|
|
18
|
+
query: { type: "string", description: "Optional case-insensitive text search within the original output." },
|
|
19
|
+
offset: { type: "integer", description: "1-indexed line offset for returned output." },
|
|
20
|
+
limit: { type: "integer", description: "Maximum lines to return; default 120." }
|
|
21
|
+
},
|
|
22
|
+
required: ["id"]
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Executes retrieval from the active conversation artifact store.
|
|
27
|
+
def call(args, conversation, cancellation: nil)
|
|
28
|
+
cancellation&.raise_if_cancelled!
|
|
29
|
+
id = argument(args, :id, "").to_s
|
|
30
|
+
return "Error: id is required" if id.empty?
|
|
31
|
+
|
|
32
|
+
artifact = conversation.tool_output_artifacts[id]
|
|
33
|
+
return "Error: unknown tool output id: #{id}" unless artifact
|
|
34
|
+
|
|
35
|
+
content = artifact[:content].to_s
|
|
36
|
+
query = argument(args, :query, "").to_s
|
|
37
|
+
lines = query.empty? ? content.split("\n", -1) : matching_lines(content, query)
|
|
38
|
+
return "No matching lines for #{query.inspect} in #{id}." if lines.empty?
|
|
39
|
+
|
|
40
|
+
slice_lines(id, lines, offset: argument(args, :offset), limit: argument(args, :limit), query: query)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def matching_lines(content, query)
|
|
46
|
+
needle = query.downcase
|
|
47
|
+
content.split("\n", -1).each_with_index.filter_map do |line, index|
|
|
48
|
+
next unless line.downcase.include?(needle)
|
|
49
|
+
|
|
50
|
+
"#{index + 1}: #{line}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def slice_lines(id, lines, offset:, limit:, query:)
|
|
55
|
+
start_index = [offset.to_i - 1, 0].max
|
|
56
|
+
return "Error: offset #{offset} is beyond output (#{lines.length} lines total)" if start_index >= lines.length
|
|
57
|
+
|
|
58
|
+
line_limit = limit.to_i.positive? ? limit.to_i : DEFAULT_LIMIT
|
|
59
|
+
selected = lines[start_index, line_limit] || []
|
|
60
|
+
header = "[Retrieved tool output #{id}"
|
|
61
|
+
header << " matching #{query.inspect}" unless query.empty?
|
|
62
|
+
header << ": lines #{start_index + 1}-#{start_index + selected.length} of #{lines.length}]"
|
|
63
|
+
output = "#{header}\n#{selected.join("\n")}".rstrip
|
|
64
|
+
if start_index + selected.length < lines.length
|
|
65
|
+
output << "\n\n[#{lines.length - start_index - selected.length} more lines. Use offset=#{start_index + selected.length + 1} to continue.]"
|
|
66
|
+
end
|
|
67
|
+
output
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -619,8 +619,8 @@ module Kward
|
|
|
619
619
|
return web_config[snake] if web_config.key?(snake)
|
|
620
620
|
return web_config[camel] if web_config.key?(camel)
|
|
621
621
|
return config[prefixed] if config.key?(prefixed)
|
|
622
|
-
return config[snake] if config.key?(snake)
|
|
623
|
-
return config[camel] if config.key?(camel)
|
|
622
|
+
return config[snake] if key.to_s != "provider" && config.key?(snake)
|
|
623
|
+
return config[camel] if key.to_s != "provider" && config.key?(camel)
|
|
624
624
|
|
|
625
625
|
nil
|
|
626
626
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require_relative "base"
|
|
2
|
+
|
|
3
|
+
# Namespace for the Kward CLI agent runtime.
|
|
4
|
+
module Kward
|
|
5
|
+
# Model-callable tool wrappers and their argument schemas.
|
|
6
|
+
module Tools
|
|
7
|
+
# Returns a compact symbol outline for a workspace source file.
|
|
8
|
+
class SummarizeFileStructure < Base
|
|
9
|
+
# Builds the tool schema and stores the execution dependency.
|
|
10
|
+
def initialize(workspace:)
|
|
11
|
+
@workspace = workspace
|
|
12
|
+
super(
|
|
13
|
+
"summarize_file_structure",
|
|
14
|
+
"Return a compact outline of classes, modules, methods, and functions in a workspace source file.",
|
|
15
|
+
properties: {
|
|
16
|
+
path: { type: "string", description: "Workspace-relative source file path." }
|
|
17
|
+
},
|
|
18
|
+
required: ["path"]
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Executes the structure summary tool.
|
|
23
|
+
def call(args, _conversation, cancellation: nil)
|
|
24
|
+
cancellation&.raise_if_cancelled!
|
|
25
|
+
@workspace.summarize_file_structure(argument(args, :path, ""))
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -17,6 +17,8 @@ module Kward
|
|
|
17
17
|
"run_shell_command" => "bash",
|
|
18
18
|
"list_directory" => "list_directory",
|
|
19
19
|
"code_search" => "code_search",
|
|
20
|
+
"summarize_file_structure" => "summarize_file_structure",
|
|
21
|
+
"retrieve_tool_output" => "retrieve_tool_output",
|
|
20
22
|
"web_search" => "web_search",
|
|
21
23
|
"fetch_content" => "fetch_content",
|
|
22
24
|
"fetch_raw" => "fetch_raw",
|
data/lib/kward/version.rb
CHANGED
data/lib/kward/workspace.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Kward
|
|
|
20
20
|
MAX_FILE_BYTES = 256 * 1024
|
|
21
21
|
MAX_READ_OUTPUT_BYTES = 50 * 1024
|
|
22
22
|
MAX_READ_OUTPUT_LINES = 2_000
|
|
23
|
-
MAX_COMMAND_OUTPUT_BYTES =
|
|
23
|
+
MAX_COMMAND_OUTPUT_BYTES = 128 * 1024
|
|
24
24
|
MAX_EDIT_DIFF_BYTES = 8 * 1024
|
|
25
25
|
DEFAULT_COMMAND_TIMEOUT_SECONDS = 30
|
|
26
26
|
|
|
@@ -64,7 +64,27 @@ module Kward
|
|
|
64
64
|
content = File.read(resolved)
|
|
65
65
|
return "Error: not a text file: #{path}" if binary_content?(content)
|
|
66
66
|
|
|
67
|
-
read_file_slice(content, offset: offset, limit: limit)
|
|
67
|
+
large_file_outline_response(path, content, offset: offset, limit: limit) || read_file_slice(content, offset: offset, limit: limit)
|
|
68
|
+
rescue SecurityError, Errno::ENOENT => e
|
|
69
|
+
"Error: #{e.message}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns a compact outline of recognizable source-code declarations.
|
|
73
|
+
def summarize_file_structure(path)
|
|
74
|
+
resolved = workspace_path(path)
|
|
75
|
+
return "Error: not a file: #{path}" unless File.file?(resolved)
|
|
76
|
+
|
|
77
|
+
size = File.size(resolved)
|
|
78
|
+
return "Error: file too large: #{path} is #{size} bytes; limit is #{@max_file_bytes} bytes" if size > @max_file_bytes
|
|
79
|
+
|
|
80
|
+
content = File.read(resolved)
|
|
81
|
+
return "Error: not a text file: #{path}" if binary_content?(content)
|
|
82
|
+
|
|
83
|
+
lines = content.split("\n", -1)
|
|
84
|
+
outline = source_outline(lines)
|
|
85
|
+
return "No recognizable source structure found in #{path}." if outline.empty?
|
|
86
|
+
|
|
87
|
+
(["# File structure: #{path}", "- Lines: #{lines.length}", "- Bytes: #{content.bytesize}", "", "## Outline"] + outline).join("\n")
|
|
68
88
|
rescue SecurityError, Errno::ENOENT => e
|
|
69
89
|
"Error: #{e.message}"
|
|
70
90
|
end
|
|
@@ -196,6 +216,42 @@ module Kward
|
|
|
196
216
|
Pathname.new(path).relative_path_from(@root).to_s
|
|
197
217
|
end
|
|
198
218
|
|
|
219
|
+
def large_file_outline_response(path, content, offset:, limit:)
|
|
220
|
+
return nil unless offset.nil? && limit.nil?
|
|
221
|
+
lines = content.split("\n", -1)
|
|
222
|
+
return nil unless lines.length > @max_read_output_lines || content.bytesize > @max_read_output_bytes
|
|
223
|
+
|
|
224
|
+
outline = source_outline(lines)
|
|
225
|
+
return nil if outline.empty?
|
|
226
|
+
|
|
227
|
+
preview_limit = [120, @max_read_output_lines].min
|
|
228
|
+
preview = lines.first(preview_limit).join("\n")
|
|
229
|
+
[
|
|
230
|
+
"File has #{lines.length} lines (#{content.bytesize} bytes). Showing an outline and the first #{preview_limit} lines to reduce model context.",
|
|
231
|
+
"",
|
|
232
|
+
"Outline:",
|
|
233
|
+
outline.join("\n"),
|
|
234
|
+
"",
|
|
235
|
+
"First #{preview_limit} lines:",
|
|
236
|
+
preview,
|
|
237
|
+
"",
|
|
238
|
+
"[Use read_file with offset=#{preview_limit + 1} and limit to continue, or request a specific section from the outline.]"
|
|
239
|
+
].join("\n")
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def source_outline(lines)
|
|
243
|
+
outline = []
|
|
244
|
+
lines.each_with_index do |line, index|
|
|
245
|
+
stripped = line.strip
|
|
246
|
+
next unless stripped.match?(/\A(class|module|def)\s+/) || stripped.match?(/\A(function|async function)\s+/) || stripped.match?(/\A(export\s+)?(class|interface|type)\s+/)
|
|
247
|
+
|
|
248
|
+
indent = line[/\A\s*/].to_s.length
|
|
249
|
+
outline << "line #{index + 1}: #{' ' * [indent / 2, 6].min}#{stripped}"
|
|
250
|
+
break if outline.length >= 80
|
|
251
|
+
end
|
|
252
|
+
outline
|
|
253
|
+
end
|
|
254
|
+
|
|
199
255
|
def read_file_slice(content, offset:, limit:)
|
|
200
256
|
lines = content.split("\n", -1)
|
|
201
257
|
lines = [""] if lines.empty?
|
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
--kward-accent: #9caf35;
|
|
11
11
|
--kward-accent-bright: #d2df62;
|
|
12
12
|
--kward-code: #030604;
|
|
13
|
+
--kward-syntax-comment: #7f8b67;
|
|
14
|
+
--kward-syntax-constant: #f0bf6a;
|
|
15
|
+
--kward-syntax-keyword: #d2df62;
|
|
16
|
+
--kward-syntax-method: #b8d852;
|
|
17
|
+
--kward-syntax-string: #8fd15b;
|
|
18
|
+
--kward-syntax-symbol: #ff7f6f;
|
|
19
|
+
--kward-syntax-variable: #a7c884;
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
html {
|
|
@@ -131,12 +138,31 @@ body.kward-docs::before {
|
|
|
131
138
|
width: 1px;
|
|
132
139
|
}
|
|
133
140
|
|
|
134
|
-
.kward-guide-search
|
|
141
|
+
.kward-guide-search,
|
|
142
|
+
.kward-api-index-link {
|
|
135
143
|
justify-self: end;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.kward-guide-search {
|
|
136
147
|
position: relative;
|
|
137
148
|
width: min(280px, 24vw);
|
|
138
149
|
}
|
|
139
150
|
|
|
151
|
+
.kward-api-index-link {
|
|
152
|
+
border: 1px solid rgba(156, 175, 53, 0.42);
|
|
153
|
+
border-radius: 999px;
|
|
154
|
+
color: var(--kward-ink);
|
|
155
|
+
padding: 10px 14px;
|
|
156
|
+
text-decoration: none;
|
|
157
|
+
white-space: nowrap;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.kward-api-index-link:hover,
|
|
161
|
+
.kward-api-index-link:focus {
|
|
162
|
+
background: rgba(156, 175, 53, 0.13);
|
|
163
|
+
color: var(--kward-accent-bright);
|
|
164
|
+
}
|
|
165
|
+
|
|
140
166
|
.kward-guide-search input {
|
|
141
167
|
background: rgba(3, 6, 4, 0.72);
|
|
142
168
|
border: 1px solid rgba(156, 175, 53, 0.42);
|
|
@@ -328,6 +354,90 @@ body.kward-docs code {
|
|
|
328
354
|
border-radius: 6px;
|
|
329
355
|
}
|
|
330
356
|
|
|
357
|
+
body.kward-docs pre.code .comment {
|
|
358
|
+
color: var(--kward-syntax-comment);
|
|
359
|
+
font-style: italic;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
body.kward-docs pre.code .const,
|
|
363
|
+
body.kward-docs pre.code .constant,
|
|
364
|
+
body.kward-docs #content .summary_desc pre.code .const > .object_link a,
|
|
365
|
+
body.kward-docs #content .docstring pre.code .const > .object_link a {
|
|
366
|
+
color: var(--kward-syntax-constant);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
body.kward-docs pre.code .kw,
|
|
370
|
+
body.kward-docs pre.code .rubyid_require,
|
|
371
|
+
body.kward-docs pre.code .rubyid_extend,
|
|
372
|
+
body.kward-docs pre.code .rubyid_include {
|
|
373
|
+
color: var(--kward-syntax-keyword);
|
|
374
|
+
font-weight: 700;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
body.kward-docs pre.code .id,
|
|
378
|
+
body.kward-docs #content .summary_desc pre.code .id > .object_link a,
|
|
379
|
+
body.kward-docs #content .docstring pre.code .id > .object_link a {
|
|
380
|
+
color: var(--kward-syntax-method);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
body.kward-docs pre.code .tstring_content,
|
|
384
|
+
body.kward-docs pre.code .heredoc_beg,
|
|
385
|
+
body.kward-docs pre.code .heredoc_end,
|
|
386
|
+
body.kward-docs pre.code .qwords_beg,
|
|
387
|
+
body.kward-docs pre.code .qwords_end,
|
|
388
|
+
body.kward-docs pre.code .qwords_sep,
|
|
389
|
+
body.kward-docs pre.code .words_beg,
|
|
390
|
+
body.kward-docs pre.code .words_end,
|
|
391
|
+
body.kward-docs pre.code .words_sep,
|
|
392
|
+
body.kward-docs pre.code .qsymbols_beg,
|
|
393
|
+
body.kward-docs pre.code .qsymbols_end,
|
|
394
|
+
body.kward-docs pre.code .qsymbols_sep,
|
|
395
|
+
body.kward-docs pre.code .symbols_beg,
|
|
396
|
+
body.kward-docs pre.code .symbols_end,
|
|
397
|
+
body.kward-docs pre.code .symbols_sep,
|
|
398
|
+
body.kward-docs pre.code .tstring,
|
|
399
|
+
body.kward-docs pre.code .dstring,
|
|
400
|
+
body.kward-docs pre.code .regexp,
|
|
401
|
+
body.kward-docs .dregexp {
|
|
402
|
+
color: var(--kward-syntax-string);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
body.kward-docs pre.code .label,
|
|
406
|
+
body.kward-docs pre.code .symbol {
|
|
407
|
+
color: var(--kward-syntax-symbol);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
body.kward-docs pre.code .ivar,
|
|
411
|
+
body.kward-docs pre.code .gvar,
|
|
412
|
+
body.kward-docs pre.code .rubyid_backref,
|
|
413
|
+
body.kward-docs pre.code .rubyid_nth_ref {
|
|
414
|
+
color: var(--kward-syntax-variable);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
body.kward-docs pre.code .op,
|
|
418
|
+
body.kward-docs pre.code .period,
|
|
419
|
+
body.kward-docs pre.code .comma,
|
|
420
|
+
body.kward-docs pre.code .lparen,
|
|
421
|
+
body.kward-docs pre.code .rparen,
|
|
422
|
+
body.kward-docs pre.code .lbrace,
|
|
423
|
+
body.kward-docs pre.code .rbrace,
|
|
424
|
+
body.kward-docs pre.code .lbracket,
|
|
425
|
+
body.kward-docs pre.code .rbracket {
|
|
426
|
+
color: rgba(239, 232, 208, 0.74);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
body.kward-docs pre.code a,
|
|
430
|
+
body.kward-docs pre.code a:visited {
|
|
431
|
+
text-decoration-color: rgba(210, 223, 98, 0.45);
|
|
432
|
+
text-decoration-thickness: 1px;
|
|
433
|
+
text-underline-offset: 2px;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
body.kward-docs pre.code a:hover {
|
|
437
|
+
background: rgba(156, 175, 53, 0.16);
|
|
438
|
+
color: var(--kward-accent-bright);
|
|
439
|
+
}
|
|
440
|
+
|
|
331
441
|
body.kward-docs .copy-code-button {
|
|
332
442
|
background: transparent;
|
|
333
443
|
border: 1px solid rgba(156, 175, 53, 0.48);
|
|
@@ -364,7 +474,8 @@ body.kward-docs #footer {
|
|
|
364
474
|
}
|
|
365
475
|
|
|
366
476
|
.kward-topnav,
|
|
367
|
-
.kward-guide-search
|
|
477
|
+
.kward-guide-search,
|
|
478
|
+
.kward-api-index-link {
|
|
368
479
|
display: none;
|
|
369
480
|
}
|
|
370
481
|
|
|
@@ -1081,17 +1192,26 @@ body.kward-docs .kward-home #footer {
|
|
|
1081
1192
|
border-radius: 12px;
|
|
1082
1193
|
box-shadow: 0 24px 70px rgba(0, 0, 0, 0.48);
|
|
1083
1194
|
display: none;
|
|
1084
|
-
gap:
|
|
1085
|
-
grid-template-columns: repeat(
|
|
1195
|
+
gap: 16px;
|
|
1196
|
+
grid-template-columns: repeat(2, minmax(160px, 220px));
|
|
1086
1197
|
left: 50%;
|
|
1198
|
+
max-width: calc(100vw - 48px);
|
|
1087
1199
|
opacity: 0;
|
|
1088
|
-
padding:
|
|
1200
|
+
padding: 20px;
|
|
1089
1201
|
pointer-events: none;
|
|
1090
1202
|
position: absolute;
|
|
1091
1203
|
top: 100%;
|
|
1092
1204
|
transform: translate(-50%, -8px);
|
|
1093
1205
|
transition: opacity 140ms ease, transform 140ms ease;
|
|
1094
|
-
width:
|
|
1206
|
+
width: max-content;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
.kward-advanced-nav-dropdown {
|
|
1210
|
+
grid-template-columns: repeat(3, minmax(150px, 200px));
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
.kward-api-nav-dropdown {
|
|
1214
|
+
grid-template-columns: repeat(2, minmax(170px, 210px));
|
|
1095
1215
|
}
|
|
1096
1216
|
|
|
1097
1217
|
.kward-nav-dropdown::before {
|
|
@@ -1257,6 +1377,134 @@ body.kward-docs .kward-home #footer {
|
|
|
1257
1377
|
}
|
|
1258
1378
|
}
|
|
1259
1379
|
|
|
1380
|
+
/* YARD's class/method/file list pages use a separate full_list template. */
|
|
1381
|
+
.kward-full-list-body .kward-topbar {
|
|
1382
|
+
position: relative;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
.kward-full-list-body .kward-page {
|
|
1386
|
+
padding-top: 40px;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
.kward-full-list-body #content {
|
|
1390
|
+
background: var(--kward-panel-strong);
|
|
1391
|
+
border: 1px solid var(--kward-border);
|
|
1392
|
+
border-radius: 14px;
|
|
1393
|
+
box-shadow: 0 26px 70px rgba(0, 0, 0, 0.28);
|
|
1394
|
+
padding: 38px;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
.kward-full-list-body .fixed_header {
|
|
1398
|
+
background: transparent;
|
|
1399
|
+
height: auto;
|
|
1400
|
+
margin: 0 0 24px;
|
|
1401
|
+
padding: 0;
|
|
1402
|
+
position: static;
|
|
1403
|
+
width: auto;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
.kward-full-list-body #full_list_header {
|
|
1407
|
+
color: var(--kward-ink);
|
|
1408
|
+
font-size: clamp(36px, 5vw, 62px);
|
|
1409
|
+
letter-spacing: -0.04em;
|
|
1410
|
+
line-height: 0.98;
|
|
1411
|
+
margin: 0 0 18px;
|
|
1412
|
+
padding: 0;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
.kward-full-list-body #full_list_nav {
|
|
1416
|
+
color: var(--kward-muted);
|
|
1417
|
+
font-size: 14px;
|
|
1418
|
+
margin: 0 0 18px;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
.kward-full-list-body #full_list_nav a,
|
|
1422
|
+
.kward-full-list-body #full_list_nav a:visited {
|
|
1423
|
+
color: var(--kward-accent-bright);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
.kward-full-list-body #full_list_nav a:hover {
|
|
1427
|
+
color: #f0f7a0;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
.kward-full-list-body #search {
|
|
1431
|
+
color: var(--kward-muted);
|
|
1432
|
+
font-size: 14px;
|
|
1433
|
+
margin: 0;
|
|
1434
|
+
padding: 0;
|
|
1435
|
+
width: auto;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
.kward-full-list-body #search input {
|
|
1439
|
+
background: rgba(3, 6, 4, 0.72);
|
|
1440
|
+
border: 1px solid rgba(156, 175, 53, 0.42);
|
|
1441
|
+
border-radius: 999px;
|
|
1442
|
+
color: var(--kward-ink);
|
|
1443
|
+
font: inherit;
|
|
1444
|
+
margin-left: 8px;
|
|
1445
|
+
outline: none;
|
|
1446
|
+
padding: 8px 12px;
|
|
1447
|
+
width: min(260px, 60vw);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
.kward-full-list-body #search input:focus {
|
|
1451
|
+
border-color: var(--kward-accent-bright);
|
|
1452
|
+
box-shadow: 0 0 0 3px rgba(156, 175, 53, 0.18);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
.kward-full-list-body #full_list {
|
|
1456
|
+
background: rgba(3, 6, 4, 0.42);
|
|
1457
|
+
border: 1px solid rgba(156, 175, 53, 0.22);
|
|
1458
|
+
border-radius: 12px;
|
|
1459
|
+
font-size: 15px;
|
|
1460
|
+
margin: 0;
|
|
1461
|
+
overflow: auto;
|
|
1462
|
+
padding: 8px;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
.kward-full-list-body #full_list li {
|
|
1466
|
+
color: var(--kward-muted);
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
.kward-full-list-body #full_list li.odd,
|
|
1470
|
+
.kward-full-list-body #full_list li.even {
|
|
1471
|
+
background: transparent;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
.kward-full-list-body #full_list li .item {
|
|
1475
|
+
border-radius: 8px;
|
|
1476
|
+
padding-bottom: 7px;
|
|
1477
|
+
padding-top: 7px;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
.kward-full-list-body #full_list .item:hover {
|
|
1481
|
+
background: rgba(156, 175, 53, 0.13);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
.kward-full-list-body #full_list a,
|
|
1485
|
+
.kward-full-list-body #full_list a:visited {
|
|
1486
|
+
color: var(--kward-ink);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
.kward-full-list-body #full_list a:hover {
|
|
1490
|
+
color: var(--kward-accent-bright);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
.kward-full-list-body #full_list li.clicked > .item {
|
|
1494
|
+
background: rgba(156, 175, 53, 0.22);
|
|
1495
|
+
color: var(--kward-ink);
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
.kward-full-list-body #full_list li.clicked > .item a,
|
|
1499
|
+
.kward-full-list-body #full_list li.clicked > .item a:visited {
|
|
1500
|
+
color: var(--kward-accent-bright);
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
.kward-full-list-body #noresults {
|
|
1504
|
+
background: transparent;
|
|
1505
|
+
color: var(--kward-muted);
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1260
1508
|
/* Pages no longer use YARD's iframe/sidebar layout. */
|
|
1261
1509
|
.kward-page {
|
|
1262
1510
|
box-sizing: border-box;
|
|
@@ -1588,8 +1836,9 @@ body.kward-docs #filecontents table {
|
|
|
1588
1836
|
border-collapse: collapse;
|
|
1589
1837
|
color: var(--kward-ink);
|
|
1590
1838
|
display: block;
|
|
1839
|
+
max-width: 100%;
|
|
1591
1840
|
overflow-x: auto;
|
|
1592
|
-
width:
|
|
1841
|
+
width: fit-content;
|
|
1593
1842
|
}
|
|
1594
1843
|
|
|
1595
1844
|
body.kward-docs #content th,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html <%= "lang=\"#{html_lang}\"" unless html_lang.nil? %>>
|
|
3
|
+
<head>
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5
|
+
<meta charset="<%= charset %>">
|
|
6
|
+
<% stylesheets_full_list.each do |stylesheet| %>
|
|
7
|
+
<link rel="stylesheet" href="<%= mtime_url(stylesheet) %>" type="text/css" media="screen">
|
|
8
|
+
<% end %>
|
|
9
|
+
|
|
10
|
+
<% javascripts_full_list.each do |javascript| %>
|
|
11
|
+
<script type="text/javascript" charset="utf-8" src="<%= mtime_url(javascript) %>"></script>
|
|
12
|
+
<% end %>
|
|
13
|
+
|
|
14
|
+
<title><%= @list_title %></title>
|
|
15
|
+
<base id="base_target" target="_parent">
|
|
16
|
+
</head>
|
|
17
|
+
<body class="kward-docs kward-content-body kward-full-list-body">
|
|
18
|
+
<a href="#content" class="kward-skip-link">Skip to content</a>
|
|
19
|
+
|
|
20
|
+
<header class="kward-topbar">
|
|
21
|
+
<a class="kward-brand" href="index.html">
|
|
22
|
+
<img class="kward-brand-logo" src="images/kward_logo.png" alt="" aria-hidden="true">
|
|
23
|
+
<span>
|
|
24
|
+
<strong>Kward</strong>
|
|
25
|
+
</span>
|
|
26
|
+
</a>
|
|
27
|
+
<button class="kward-nav-toggle" type="button" aria-expanded="false" aria-controls="kward-primary-nav" aria-label="Toggle navigation menu" onclick="document.body.classList.toggle('kward-nav-open'); this.setAttribute('aria-expanded', document.body.classList.contains('kward-nav-open'))">
|
|
28
|
+
<span class="kward-nav-toggle-bar"></span>
|
|
29
|
+
<span class="kward-nav-toggle-bar"></span>
|
|
30
|
+
<span class="kward-nav-toggle-bar"></span>
|
|
31
|
+
<span class="kward-sr-only">Menu</span>
|
|
32
|
+
</button>
|
|
33
|
+
<nav id="kward-primary-nav" class="kward-topnav" aria-label="Primary navigation">
|
|
34
|
+
<a href="index.html">Home</a>
|
|
35
|
+
<div class="kward-nav-menu">
|
|
36
|
+
<a class="kward-nav-menu-link" href="file.README.html">Guides</a>
|
|
37
|
+
<button class="kward-nav-menu-button" type="button" aria-label="Expand guides" aria-expanded="false">⌄</button>
|
|
38
|
+
<div class="kward-nav-dropdown">
|
|
39
|
+
<% guide_groups.each do |title, items| %>
|
|
40
|
+
<section>
|
|
41
|
+
<h2><%= h title %></h2>
|
|
42
|
+
<% items.each do |label, link| %>
|
|
43
|
+
<a href="<%= url_for(link) %>"><%= h label %></a>
|
|
44
|
+
<% end %>
|
|
45
|
+
</section>
|
|
46
|
+
<% end %>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="kward-nav-menu">
|
|
50
|
+
<a class="kward-nav-menu-link" href="file.extensibility.html">Advanced</a>
|
|
51
|
+
<button class="kward-nav-menu-button" type="button" aria-label="Expand advanced guides" aria-expanded="false">⌄</button>
|
|
52
|
+
<div class="kward-nav-dropdown kward-advanced-nav-dropdown">
|
|
53
|
+
<% extension_groups.each do |title, items| %>
|
|
54
|
+
<section>
|
|
55
|
+
<h2><%= h title %></h2>
|
|
56
|
+
<% items.each do |label, link| %>
|
|
57
|
+
<a href="<%= url_for(link) %>"><%= h label %></a>
|
|
58
|
+
<% end %>
|
|
59
|
+
</section>
|
|
60
|
+
<% end %>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="kward-nav-menu active">
|
|
64
|
+
<a class="kward-nav-menu-link" href="file.api.html">API Docs</a>
|
|
65
|
+
<button class="kward-nav-menu-button" type="button" aria-label="Expand API docs" aria-expanded="false">⌄</button>
|
|
66
|
+
<div class="kward-nav-dropdown kward-api-nav-dropdown">
|
|
67
|
+
<% api_groups.each do |title, items| %>
|
|
68
|
+
<section>
|
|
69
|
+
<h2><%= h title %></h2>
|
|
70
|
+
<% items.each do |label, link| %>
|
|
71
|
+
<a href="<%= url_for(link) %>"><%= h label %></a>
|
|
72
|
+
<% end %>
|
|
73
|
+
</section>
|
|
74
|
+
<% end %>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</nav>
|
|
78
|
+
<a class="kward-api-index-link" href="class_list.html">Search API index</a>
|
|
79
|
+
</header>
|
|
80
|
+
|
|
81
|
+
<main class="kward-page">
|
|
82
|
+
<div id="content" class="kward-content-page kward-api-page">
|
|
83
|
+
<div class="fixed_header">
|
|
84
|
+
<h1 id="full_list_header"><%= @list_title %></h1>
|
|
85
|
+
<div id="full_list_nav">
|
|
86
|
+
<% menu_lists.each do |list| %>
|
|
87
|
+
<span><a target="_self" href="<%= url_for_list list[:type] %>">
|
|
88
|
+
<%= list[:title] %>
|
|
89
|
+
</a></span>
|
|
90
|
+
<% end %>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div id="search">
|
|
94
|
+
<label for="search-class">Search:</label>
|
|
95
|
+
<input id="search-class" type="text">
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<ul id="full_list" class="<%= @list_class || @list_type %>">
|
|
100
|
+
<%= erb "full_list_#{@list_type}" %>
|
|
101
|
+
</ul>
|
|
102
|
+
</div>
|
|
103
|
+
</main>
|
|
104
|
+
|
|
105
|
+
<script type="text/javascript" charset="utf-8" src="js/kward.js"></script>
|
|
106
|
+
</body>
|
|
107
|
+
</html>
|