fix: issue #20 cmd-J panel tab strip visibility and output panel parity

This commit is contained in:
hugo committed 2026-07-17 20:51:42 +02:00
1 parent 6c9dd9605b
commit dd53ca3fbc
28 files changed
+1451 -666

No files matched your search

+25
View File
@@ -40,6 +40,7 @@ local meta = bds.meta.get_project_metadata()
- [app.get_default_project_path](#appget_default_project_path)
- [app.get_system_language](#appget_system_language)
- [app.get_title_bar_metrics](#appget_title_bar_metrics)
- [app.log](#applog)
- [app.notify_renderer_ready](#appnotify_renderer_ready)
- [app.open_folder](#appopen_folder)
- [app.read_project_metadata](#appread_project_metadata)
@@ -202,6 +203,30 @@ nil -- or
local result = bds.app.get_title_bar_metrics()
```
### app.log
Append a line to the script output stream. Multiple arguments are joined with spaces. Output appears in the desktop app's Output panel (and on stdout in the CLI); Lua's global `print` is routed the same way.
**Parameters**
- text (string, required)
**Response specification**
- Return type: `boolean`
**Example response**
```lua
true
```
**Example call**
```lua
local result = bds.app.log("value")
```
### app.notify_renderer_ready
Notify the host application that the renderer is ready.
-10
View File
@@ -794,13 +794,3 @@
padding: 16px;
}
.sidebar-header,
.assistant-header,
.panel-header {
display: flex;
justify-content: space-between;
gap: 12px;
padding: 16px 18px;
border-bottom: 1px solid var(--line);
}
+5
View File
@@ -19,6 +19,7 @@ import {
} from "../utils/shortcuts.js";
import { syncTitlebarOverlayInsets } from "../bridges/titlebar_overlay.js";
import { runMenuRuntimeCommand } from "../bridges/menu_runtime.js";
import { copyTextToClipboard } from "../utils/clipboard.js";
export const AppShell = {
mounted() {
@@ -179,6 +180,10 @@ export const AppShell = {
}
});
this.handleEvent("clipboard", ({ text }) => {
copyTextToClipboard(text || "");
});
window.addEventListener("bds:native-menu-action", this.handleNativeMenuAction);
window.addEventListener("keydown", this.handleShortcutKeyDown, true);
this.el.addEventListener("load", this.handleThumbnailLoad, true);
+27
View File
@@ -0,0 +1,27 @@
// Copies text to the system clipboard, mirroring the old app's behavior:
// navigator.clipboard when available, with a hidden-textarea fallback for
// webviews that lack the async clipboard API.
export const copyTextToClipboard = async (text) => {
if (typeof navigator !== "undefined" && navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
await navigator.clipboard.writeText(text);
return;
}
if (typeof document === "undefined" || typeof document.createElement !== "function") {
return;
}
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.setAttribute("readonly", "");
textArea.style.position = "absolute";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.select();
if (typeof document.execCommand === "function") {
document.execCommand("copy");
}
document.body.removeChild(textArea);
};
+2 -1
View File
@@ -555,7 +555,8 @@ defmodule BDS.CLI.Commands do
script.entrypoint || "main",
args,
timeout: Keyword.get(scripting_config, :job_timeout, :infinity),
max_reductions: Keyword.get(scripting_config, :job_max_reductions, :none)
max_reductions: Keyword.get(scripting_config, :job_max_reductions, :none),
on_output: fn text -> IO.puts(text) end
) do
{:ok, nil} -> {:ok, "Script finished"}
{:ok, result} -> {:ok, "Script finished: #{format_reason(result)}"}
+83 -17
View File
@@ -182,6 +182,7 @@ defmodule BDS.Desktop.ShellLive do
|> assign(:shell_overlay, nil)
|> assign(:git_run, nil)
|> assign(:output_entries, [])
|> assign(:collapsed_task_groups, MapSet.new())
|> assign(:panel_post_links, %{backlinks: [], outlinks: []})
|> assign(:panel_git_entries, [])
|> assign(:auto_save_timers, %{})
@@ -226,6 +227,38 @@ defmodule BDS.Desktop.ShellLive do
{:noreply, refresh_layout(socket, workbench)}
end
# Copy-all for the Output panel: entries are stored newest-first, so flip
# them back to chronological order before joining (old-app behavior).
def handle_event("copy_output", _params, socket) do
text =
socket.assigns.output_entries
|> Enum.reverse()
|> Enum.map_join("\n\n", & &1.message)
{:noreply, push_event(socket, "clipboard", %{text: text})}
end
def handle_event("toggle_task_group", %{"group" => group_id}, socket) do
collapsed = socket.assigns[:collapsed_task_groups] || MapSet.new()
collapsed =
if MapSet.member?(collapsed, group_id),
do: MapSet.delete(collapsed, group_id),
else: MapSet.put(collapsed, group_id)
{:noreply, assign(socket, :collapsed_task_groups, collapsed)}
end
def handle_event("cancel_task", %{"id" => task_id}, socket) do
_ = BDS.Tasks.cancel_task(task_id)
task_status =
BDS.Tasks.status_snapshot()
|> BDS.Desktop.ShellLive.TaskLocalization.localize_task_status(socket.assigns.page_language)
{:noreply, assign(socket, :task_status, task_status)}
end
def handle_event("open_sidebar_item", %{"route" => _route, "id" => _id} = params, socket) do
{:noreply, open_sidebar_item(socket, params, :preview)}
end
@@ -860,33 +893,66 @@ defmodule BDS.Desktop.ShellLive do
end
defp import_blogmark(socket, project_id, url, title) do
case Blogmark.receive_deep_link(project_id, url) do
{:ok, %{post: post, toasts: toasts, errors: errors}} ->
socket
|> reload_shell(socket.assigns.workbench)
|> open_sidebar_item(
%{
"route" => "post",
"id" => post.id,
"title" => post.title,
"subtitle" => post.slug
},
:pin
)
|> append_blogmark_toasts(title, toasts)
|> append_blogmark_errors(title, errors)
# Transform scripts run in the sandbox process; collect anything they
# print/log so it lands in the Output panel like in the old app.
{:ok, output_sink} = Agent.start_link(fn -> [] end)
{:error, reason} ->
append_output_entry(socket, title, inspect(reason), url, "error")
sink = fn text -> Agent.update(output_sink, fn lines -> [text | lines] end) end
try do
case Blogmark.receive_deep_link(project_id, url, on_output: sink) do
{:ok, %{post: post, toasts: toasts, errors: errors}} ->
script_output = Agent.get(output_sink, &Enum.reverse/1)
socket
|> reload_shell(socket.assigns.workbench)
|> open_sidebar_item(
%{
"route" => "post",
"id" => post.id,
"title" => post.title,
"subtitle" => post.slug
},
:pin
)
|> append_blogmark_script_output(title, script_output)
|> append_blogmark_toasts(title, toasts)
|> append_blogmark_errors(title, errors)
|> open_output_panel_when(script_output != [] or errors != [])
{:error, reason} ->
append_output_entry(socket, title, inspect(reason), url, "error")
end
after
Agent.stop(output_sink)
end
end
defp append_blogmark_script_output(socket, title, lines) do
Enum.reduce(lines, socket, fn line, acc ->
append_output_entry(acc, title, line, nil, "info")
end)
end
defp append_blogmark_toasts(socket, title, toasts) do
Enum.reduce(toasts, socket, fn message, acc ->
append_output_entry(acc, title, message, nil, "info")
end)
end
# Old-app parity: transform errors or streamed script output open the
# bottom panel on the Output tab so the user actually sees them.
defp open_output_panel_when(socket, true) do
workbench =
socket.assigns.workbench
|> Workbench.set_panel_visible(true)
|> Workbench.set_panel_tab(:output)
refresh_layout(socket, workbench)
end
defp open_output_panel_when(socket, false), do: socket
defp append_blogmark_errors(socket, title, errors) do
Enum.reduce(errors, socket, fn %{slug: slug, reason: reason}, acc ->
append_output_entry(acc, title, inspect(reason), slug, "error")
+11
View File
@@ -20,6 +20,17 @@ defmodule BDS.Desktop.ShellLive.Notify do
:ok
end
@doc """
Sends an output entry to a specific LiveView process. Needed when the
caller runs in a different process than the shell — e.g. script output
callbacks invoked inside the sandboxed script process.
"""
@spec output_to(pid(), String.t(), String.t(), String.t() | nil, String.t()) :: :ok
def output_to(pid, title, message, detail, level) when is_pid(pid) do
send(pid, {:editor_output, title, message, detail, level})
:ok
end
@spec alert(String.t(), String.t()) :: :ok
def alert(title, message) do
send(self(), {:shell_alert, title, message})
+114 -15
View File
@@ -10,6 +10,7 @@ defmodule BDS.Desktop.ShellLive.PanelRenderer do
alias BDS.PostLinks
alias BDS.Posts
alias BDS.Posts.Post
alias BDS.UI.TaskGrouping
use Gettext, backend: BDS.Gettext
@doc "Render the active panel tab body."
@@ -48,34 +49,122 @@ defmodule BDS.Desktop.ShellLive.PanelRenderer do
end
defp render_task_entries(assigns) do
entries = TaskGrouping.build_task_entries(Map.get(assigns.task_status, :tasks, []))
collapsed = Map.get(assigns, :collapsed_task_groups) || MapSet.new()
assigns =
assigns
|> assign(:task_entries, entries)
|> assign(:collapsed_task_groups, collapsed)
~H"""
<%= if Enum.empty?(Map.get(@task_status, :tasks, [])) do %>
<%= if Enum.empty?(@task_entries) do %>
<div class="panel-entry ui-panel-entry panel-empty-state ui-empty-state">
<strong><%= dgettext("ui", "Tasks") %></strong>
<span><%= dgettext("ui", "No background tasks running") %></span>
</div>
<% else %>
<div class="task-list flex flex-col gap-2">
<%= for task <- Map.get(@task_status, :tasks, []) do %>
<div class="panel-entry ui-panel-entry task-entry flex flex-col gap-2">
<div class="task-entry-header flex items-center justify-between gap-2">
<strong><%= task.name %></strong>
<span class={"task-status task-status-#{task.status}"}><%= Map.get(task, :status_label, task.status |> to_string() |> String.capitalize()) %></span>
</div>
<span><%= task.message || task.group_name || "" %></span>
<%= if is_number(task.progress) do %>
<div class="task-progress-row">
<progress max="1" value={task.progress}></progress>
<span><%= Map.get(task, :progress_label, progress_percent(task.progress)) %></span>
</div>
<% end %>
</div>
<%= for entry <- @task_entries do %>
<%= case entry do %>
<% {:single, task} -> %>
{render_task_row(assigns, task, false)}
<% {:group, group_id, group_name, tasks} -> %>
{render_task_group(assigns, group_id, group_name, tasks)}
<% end %>
<% end %>
</div>
<% end %>
"""
end
defp render_task_group(assigns, group_id, group_name, tasks) do
summary = TaskGrouping.summarize_task_group(tasks)
expanded = not MapSet.member?(assigns.collapsed_task_groups, group_id)
assigns =
assigns
|> assign(:group_id, group_id)
|> assign(:group_name, group_name)
|> assign(:group_tasks, tasks)
|> assign(:group_expanded, expanded)
|> assign(:group_meta, task_group_meta(summary))
~H"""
<div class="task-group flex flex-col">
<button
class="panel-entry ui-panel-entry task-entry task-group-toggle flex w-full items-center gap-2 text-left"
type="button"
phx-click="toggle_task_group"
phx-value-group={@group_id}
aria-expanded={to_string(@group_expanded)}
>
<span class="task-group-chevron">{if @group_expanded, do: "▾", else: "▸"}</span>
<strong class="task-group-title"><%= @group_name %> (<%= length(@group_tasks) %>)</strong>
<span class="task-group-meta text-muted text-xs"><%= @group_meta %></span>
</button>
<%= if @group_expanded do %>
<%= for task <- @group_tasks do %>
{render_task_row(assigns, task, true)}
<% end %>
<% end %>
</div>
"""
end
defp render_task_row(assigns, task, is_child) do
assigns =
assigns
|> assign(:task, task)
|> assign(:task_child?, is_child)
~H"""
<div class={["panel-entry", "ui-panel-entry", "task-entry", "flex flex-col gap-2", if(@task_child?, do: "ml-4")]}>
<div class="task-entry-header flex items-center justify-between gap-2">
<strong><%= @task.name %></strong>
<span class={"task-status task-status-#{@task.status}"}><%= Map.get(@task, :status_label, @task.status |> to_string() |> String.capitalize()) %></span>
</div>
<span><%= @task.message || @task.group_name || "" %></span>
<%= if is_number(@task.progress) do %>
<div class="task-progress-row">
<progress max="1" value={@task.progress}></progress>
<span><%= Map.get(@task, :progress_label, progress_percent(@task.progress)) %></span>
</div>
<% end %>
<%= if @task.status == :running do %>
<div class="task-entry-actions flex justify-end">
<button
class="ui-button ui-button-secondary inline-flex items-center px-2 py-1 text-xs"
data-testid="cancel-task-button"
type="button"
phx-click="cancel_task"
phx-value-id={@task.id}
>
<%= dgettext("ui", "Cancel") %>
</button>
</div>
<% end %>
</div>
"""
end
# "NN% · X Running · Y Pending" — the breakdown only lists non-zero counts,
# like the old app's summarizeTaskGroup rendering.
defp task_group_meta(summary) do
parts =
[]
|> maybe_append_breakdown(summary.running, dgettext("ui", "Running"))
|> maybe_append_breakdown(summary.pending, dgettext("ui", "Pending"))
suffix = if parts == [], do: "", else: " · " <> Enum.join(parts, " · ")
progress_percent(summary.progress) <> suffix
end
defp maybe_append_breakdown(parts, count, _label) when count <= 0, do: parts
defp maybe_append_breakdown(parts, count, label),
do: parts ++ ["#{count} #{label}"]
defp render_output_entries(assigns) do
~H"""
<%= if Enum.empty?(@output_entries) do %>
@@ -84,6 +173,16 @@ defmodule BDS.Desktop.ShellLive.PanelRenderer do
<span><%= dgettext("ui", "No shell output yet") %></span>
</div>
<% else %>
<div class="output-toolbar flex shrink-0 justify-end">
<button
class="ui-button ui-button-secondary inline-flex items-center px-2 py-1 text-xs"
data-testid="copy-output-button"
type="button"
phx-click="copy_output"
>
<%= dgettext("ui", "Copy") %>
</button>
</div>
<div class="output-list flex flex-col gap-2">
<%= for entry <- @output_entries do %>
<div class={[
+7 -1
View File
@@ -206,11 +206,17 @@ defmodule BDS.Desktop.ShellLive.ScriptEditor do
%Script{} = script ->
draft = current_draft(socket.assigns, script)
# The sandbox runs in its own process, so streamed script output is
# routed back to this LiveView explicitly.
live_view = self()
title = dgettext("ui", "Scripts")
case Scripting.execute_project_script(
script.project_id,
draft["content"] || "",
draft["entrypoint"] || "main",
[]
[],
on_output: fn text -> Notify.output_to(live_view, title, text, nil, "info") end
) do
{:ok, result} ->
notify_output(socket, dgettext("ui", "Scripts"), inspect(result))
+8
View File
@@ -50,6 +50,14 @@ defmodule BDS.Scripting.ApiDocs do
params: [],
returns: "table | nil"
},
%{
module: "app",
name: "log",
description:
"Append a line to the script output stream. Multiple arguments are joined with spaces. Output appears in the desktop app's Output panel (and on stdout in the CLI); Lua's global `print` is routed the same way.",
params: [%{name: "text", type: "string", required: true}],
returns: "boolean"
},
%{
module: "app",
name: "notify_renderer_ready",
+1
View File
@@ -49,6 +49,7 @@ defmodule BDS.Scripting.Capabilities do
get_system_language: zero_or_one_arg(fn _args -> I18n.current_ui_locale() end),
get_default_project_path: zero_or_one_arg(fn _args -> project_path(project_id) end),
get_title_bar_metrics: zero_or_one_arg(fn _args -> title_bar_metrics(opts) end),
log: BDS.Scripting.Lua.output_function(opts, [true]),
notify_renderer_ready: zero_or_one_arg(fn _args -> notify_renderer_ready(opts) end),
open_folder: one_arg(fn folder_path -> open_folder(folder_path, opts) end),
read_project_metadata: one_arg(fn folder_path -> read_project_metadata(folder_path) end),
+66
View File
@@ -6,16 +6,20 @@ defmodule BDS.Scripting.Lua do
and opt-in.
"""
require Logger
@type source :: String.t()
@type entrypoint :: String.t()
@type args :: [term()]
@type progress_event :: map()
@type progress_callback :: (progress_event() -> any())
@type output_callback :: (String.t() -> any())
@type execution_option ::
{:timeout, non_neg_integer() | :infinity}
| {:max_reductions, pos_integer() | :none}
| {:spawn_opts, [term()]}
| {:on_progress, progress_callback()}
| {:on_output, output_callback()}
| {:capabilities, map()}
@callback validate(source()) :: :ok | {:error, term()}
@@ -48,12 +52,65 @@ defmodule BDS.Scripting.Lua do
end
end
@doc """
Returns the sink script output (`print`, `bds.app.log`) is routed to: the
`:on_output` callback when given, otherwise a Logger-based default so script
output never leaks onto the console (where it would corrupt the TUI).
"""
@spec output_sink(keyword()) :: output_callback()
def output_sink(opts) when is_list(opts) do
case Keyword.get(opts, :on_output) do
callback when is_function(callback, 1) ->
callback
_other ->
fn text -> Logger.debug("script output: #{text}") end
end
end
@doc """
Builds the Lua-callable function shared by the global `print` override and
the `bds.app.log` capability: joins all arguments with spaces and forwards
the line to the output sink.
"""
@spec output_function(keyword(), [term()]) :: (list(), lua_state() -> {list(), lua_state()})
def output_function(opts, return_values \\ []) when is_list(opts) and is_list(return_values) do
sink = output_sink(opts)
fn args, current_state ->
line =
args
|> :luerl.decode_list(current_state)
|> Enum.map_join(" ", &format_lua_value/1)
sink.(line)
:luerl.encode_list(return_values, current_state)
end
end
@doc "Formats a decoded Lua value the way Lua's `tostring` would present it."
@spec format_lua_value(term()) :: String.t()
def format_lua_value(nil), do: "nil"
def format_lua_value(true), do: "true"
def format_lua_value(false), do: "false"
def format_lua_value(value) when is_binary(value), do: value
def format_lua_value(value) when is_float(value) do
if Float.round(value, 0) == value,
do: "#{trunc(value)}.0",
else: to_string(value)
end
def format_lua_value(value) when is_integer(value), do: Integer.to_string(value)
def format_lua_value(value), do: inspect(value)
defp initial_state(opts) do
state = :luerl_sandbox.init()
capabilities = Keyword.get(opts, :capabilities, %{})
with {:ok, state} <- :luerl.set_table_keys_dec(["bds"], %{}, state),
{:ok, state} <- install_progress_callback(state, Keyword.get(opts, :on_progress)),
{:ok, state} <- install_print_override(state, opts),
{:ok, state} <- install_capabilities(state, capabilities) do
{:ok, state}
end
@@ -85,6 +142,15 @@ defmodule BDS.Scripting.Lua do
defp install_progress_callback(_state, callback),
do: {:error, {:invalid_progress_callback, callback}}
# Replaces the built-in `print` (which would write straight to the BEAM
# console) with a function routed to the output sink.
defp install_print_override(state, opts) do
case :luerl.set_table_keys_dec(["print"], output_function(opts), state) do
{:ok, next_state} -> {:ok, next_state}
error -> {:error, {:print_override_install_failed, error}}
end
end
defp install_capabilities(state, capabilities) when capabilities in [%{}, []], do: {:ok, state}
defp install_capabilities(state, capabilities) when is_map(capabilities) do
+91
View File
@@ -0,0 +1,91 @@
defmodule BDS.UI.TaskGrouping do
@moduledoc """
Groups task snapshot entries for the bottom panel's Tasks tab, mirroring the
old app's `taskGrouping.ts`: tasks sharing a `group_id` collapse into one
group entry (ordered by first appearance), everything else stays a single
entry. Groups summarize to per-status counts plus an aggregate progress in
the 0.0..1.0 range.
"""
@type task :: map()
@type entry :: {:single, task()} | {:group, String.t(), String.t(), [task()]}
@type summary :: %{
total: non_neg_integer(),
running: non_neg_integer(),
pending: non_neg_integer(),
completed: non_neg_integer(),
failed: non_neg_integer(),
cancelled: non_neg_integer(),
progress: float()
}
@spec build_task_entries([task()]) :: [entry()]
def build_task_entries(tasks) when is_list(tasks) do
{singles, groups} =
tasks
|> Enum.with_index()
|> Enum.reduce({[], %{}}, fn {task, index}, {singles, groups} ->
case Map.get(task, :group_id) do
nil ->
{[{index, task} | singles], groups}
group_id ->
groups =
Map.update(groups, group_id, {index, Map.get(task, :group_name) || group_id, [task]}, fn {first_index, name, grouped} ->
{first_index, name, [task | grouped]}
end)
{singles, groups}
end
end)
single_entries = Enum.map(singles, fn {index, task} -> {index, {:single, task}} end)
group_entries =
Enum.map(groups, fn {group_id, {index, name, grouped}} ->
{index, {:group, group_id, name, Enum.reverse(grouped)}}
end)
(single_entries ++ group_entries)
|> Enum.sort_by(fn {index, _entry} -> index end)
|> Enum.map(fn {_index, entry} -> entry end)
end
@spec summarize_task_group([task()]) :: summary()
def summarize_task_group(tasks) when is_list(tasks) do
base = %{total: 0, running: 0, pending: 0, completed: 0, failed: 0, cancelled: 0, progress: 0.0}
summary =
Enum.reduce(tasks, base, fn task, acc ->
status = Map.get(task, :status)
acc
|> Map.update!(:total, &(&1 + 1))
|> count_status(status)
|> Map.update!(:progress, &(&1 + progress_contribution(task)))
end)
if summary.total > 0 do
%{summary | progress: summary.progress / summary.total}
else
summary
end
end
defp count_status(acc, status) when status in [:running, :pending, :completed, :failed, :cancelled],
do: Map.update!(acc, status, &(&1 + 1))
defp count_status(acc, _status), do: acc
# Finished tasks count as fully done no matter their outcome, pending tasks
# contribute nothing yet (old-app getProgressContribution).
defp progress_contribution(%{status: status}) when status in [:completed, :failed, :cancelled],
do: 1.0
defp progress_contribution(%{status: :pending}), do: 0.0
defp progress_contribution(%{progress: progress}) when is_number(progress),
do: progress |> max(0.0) |> min(1.0)
defp progress_contribution(_task), do: 0.0
end
+115 -102
View File
@@ -86,7 +86,7 @@ msgstr "KI-Einstellungen"
#: lib/bds/tui.ex:1175
#: lib/bds/tui.ex:1178
#: lib/bds/tui.ex:1186
#: lib/bds/tui.ex:2035
#: lib/bds/tui.ex:2037
#, elixir-autogen, elixir-format
msgid "AI Suggestions"
msgstr "KI-Vorschlaege"
@@ -343,7 +343,7 @@ msgstr "Autor"
msgid "Auto"
msgstr "Automatisch"
#: lib/bds/desktop/shell_live.ex:445
#: lib/bds/desktop/shell_live.ex:478
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -368,7 +368,7 @@ msgstr "Automatisierungshilfen"
msgid "Available languages"
msgstr "Verfuegbare Sprachen"
#: lib/bds/desktop/shell_live/panel_renderer.ex:124
#: lib/bds/desktop/shell_live/panel_renderer.ex:223
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:313
#, elixir-autogen, elixir-format
msgid "Backlinks"
@@ -441,6 +441,7 @@ msgstr "Die Bookmarklet-Kopierfunktion ist über die Desktop-Laufzeit und die ö
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#: lib/bds/desktop/shell_live/panel_renderer.ex:143
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Abbrechen"
@@ -494,7 +495,7 @@ msgstr "Kategorie-Standards, Render-Flags und Template-Zuordnung"
msgid "Category name is required"
msgstr "Kategoriename ist erforderlich"
#: lib/bds/desktop/shell_live.ex:791
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -575,7 +576,7 @@ msgid "Collapse unchanged diff hunks"
msgstr "Unveränderte Diff-Blöcke einklappen"
#: lib/bds/desktop/shell_live/overlay_manager.ex:423
#: lib/bds/tui.ex:2131
#: lib/bds/tui.ex:2133
#, elixir-autogen, elixir-format
msgid "Command completed"
msgstr "Befehl abgeschlossen"
@@ -593,7 +594,7 @@ msgstr "Bestaetigen"
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:375
#: lib/bds/desktop/shell_live/script_editor_html/script_editor.html.heex:34
#: lib/bds/desktop/shell_live/template_editor_html/template_editor.html.heex:32
#: lib/bds/tui.ex:1468
#: lib/bds/tui.ex:1467
#: lib/bds/ui/settings_form.ex:137
#: lib/bds/ui/sidebar.ex:801
#, elixir-autogen, elixir-format
@@ -606,6 +607,7 @@ msgid "Content Categories"
msgstr "Inhaltskategorien"
#: lib/bds/desktop/menu_bar.ex:226
#: lib/bds/desktop/shell_live/panel_renderer.ex:183
#, elixir-autogen, elixir-format
msgid "Copy"
msgstr "Kopieren"
@@ -1040,7 +1042,7 @@ msgid "Filename"
msgstr "Dateiname"
#: lib/bds/desktop/menu_bar.ex:254
#: lib/bds/tui.ex:2095
#: lib/bds/tui.ex:2097
#, elixir-autogen, elixir-format
msgid "Fill Missing Translations"
msgstr "Fehlende Übersetzungen ergänzen"
@@ -1051,7 +1053,7 @@ msgid "Find"
msgstr "Suchen"
#: lib/bds/desktop/menu_bar.ex:255
#: lib/bds/tui.ex:2098
#: lib/bds/tui.ex:2100
#, elixir-autogen, elixir-format
msgid "Find Duplicate Posts"
msgstr "Doppelte Beiträge finden"
@@ -1078,14 +1080,14 @@ msgid "Gallery"
msgstr "Galerie"
#: lib/bds/desktop/menu_bar.ex:256
#: lib/bds/tui.ex:2079
#: lib/bds/tui.ex:2081
#, elixir-autogen, elixir-format
msgid "Generate Site"
msgstr "Website generieren"
#: lib/bds/desktop/shell_live.ex:792
#: lib/bds/desktop/shell_live.ex:825
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/tui.ex:1944
#: lib/bds/tui.ex:1946
#: lib/bds/ui/sidebar.ex:826
#, elixir-autogen, elixir-format
msgid "Git"
@@ -1098,8 +1100,8 @@ msgid "Git Diff"
msgstr "Git-Diff"
#: lib/bds/desktop/shell_data.ex:228
#: lib/bds/desktop/shell_live.ex:788
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#: lib/bds/desktop/shell_live.ex:821
#: lib/bds/desktop/shell_live/panel_renderer.ex:270
#, elixir-autogen, elixir-format
msgid "Git Log"
msgstr "Git-Protokoll"
@@ -1222,9 +1224,9 @@ msgstr "Importdefinitionen"
msgid "Import failed: %{error}"
msgstr "Import fehlgeschlagen: %{error}"
#: lib/bds/desktop/shell_live.ex:608
#: lib/bds/desktop/shell_live.ex:904
#: lib/bds/desktop/shell_live.ex:910
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:970
#: lib/bds/desktop/shell_live.ex:976
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1325,7 +1327,7 @@ msgstr "Verknüpfte Medien"
msgid "Linked Posts"
msgstr "Verknüpfte Beiträge"
#: lib/bds/desktop/shell_live/panel_renderer.ex:142
#: lib/bds/desktop/shell_live/panel_renderer.ex:241
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:325
#, elixir-autogen, elixir-format
msgid "Links To"
@@ -1404,9 +1406,9 @@ msgstr "Maximale Beiträge pro Seite"
#: lib/bds/desktop/shell_live/misc_editor.ex:762
#: lib/bds/desktop/shell_live/sidebar_components.ex:654
#: lib/bds/desktop/shell_live/sidebar_delete.ex:175
#: lib/bds/tui.ex:1939
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:1941
#: lib/bds/tui.ex:2162
#: lib/bds/tui.ex:2165
#: lib/bds/ui/registry.ex:30
#: lib/bds/ui/registry.ex:100
#: lib/bds/ui/sidebar.ex:578
@@ -1435,7 +1437,7 @@ msgid "Merge"
msgstr "Zusammenführen"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:78
#: lib/bds/tui.ex:1926
#: lib/bds/tui.ex:1928
#: lib/bds/ui/sidebar.ex:787
#, elixir-autogen, elixir-format
msgid "Merge Tags"
@@ -1453,8 +1455,8 @@ msgstr "Metadaten"
#: lib/bds/tui.ex:285
#: lib/bds/tui.ex:291
#: lib/bds/tui.ex:302
#: lib/bds/tui.ex:1663
#: lib/bds/tui.ex:2076
#: lib/bds/tui.ex:1665
#: lib/bds/tui.ex:2078
#: lib/bds/ui/registry.ex:111
#, elixir-autogen, elixir-format
msgid "Metadata Diff"
@@ -1532,12 +1534,12 @@ msgstr "Neue Vorlage"
msgid "No Template"
msgstr "Kein Template"
#: lib/bds/desktop/shell_live/panel_renderer.ex:55
#: lib/bds/desktop/shell_live/panel_renderer.ex:64
#, elixir-autogen, elixir-format
msgid "No background tasks running"
msgstr "Keine Hintergrundaufgaben aktiv"
#: lib/bds/desktop/shell_live/panel_renderer.ex:179
#: lib/bds/desktop/shell_live/panel_renderer.ex:278
#, elixir-autogen, elixir-format
msgid "No commit subject"
msgstr "Kein Commit-Betreff"
@@ -1547,7 +1549,7 @@ msgstr "Kein Commit-Betreff"
msgid "No folder selected"
msgstr "Kein Ordner ausgewählt"
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#: lib/bds/desktop/shell_live/panel_renderer.ex:271
#, elixir-autogen, elixir-format
msgid "No git history yet"
msgstr "Noch keine Git-Historie"
@@ -1607,7 +1609,7 @@ msgstr "Keine verwaisten Dateien ausgewählt"
msgid "No pages yet"
msgstr "Noch keine Seiten"
#: lib/bds/desktop/shell_live/panel_renderer.ex:119
#: lib/bds/desktop/shell_live/panel_renderer.ex:218
#, elixir-autogen, elixir-format
msgid "No post links yet"
msgstr "Noch keine Beitragsverweise"
@@ -1632,7 +1634,7 @@ msgstr "Keine Reparaturaktion verfügbar"
msgid "No settings match the current search"
msgstr "Keine Einstellungen entsprechen der aktuellen Suche"
#: lib/bds/desktop/shell_live/panel_renderer.ex:84
#: lib/bds/desktop/shell_live/panel_renderer.ex:173
#, elixir-autogen, elixir-format
msgid "No shell output yet"
msgstr "Noch keine Shell-Ausgabe"
@@ -1801,7 +1803,7 @@ msgid "Open Settings"
msgstr "Einstellungen öffnen"
#: lib/bds/desktop/menu_bar.ex:217
#: lib/bds/tui.ex:2100
#: lib/bds/tui.ex:2102
#, elixir-autogen, elixir-format
msgid "Open in Browser"
msgstr "Im Browser öffnen"
@@ -1832,8 +1834,8 @@ msgstr "Sonstige"
msgid "Other (%{count})"
msgstr "Andere (%{count})"
#: lib/bds/desktop/shell_live.ex:787
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#: lib/bds/desktop/shell_live.ex:820
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#, elixir-autogen, elixir-format
msgid "Output"
msgstr "Ausgabe"
@@ -1915,7 +1917,7 @@ msgid "Post"
msgstr "Beitrag"
#: lib/bds/desktop/shell_data.ex:231
#: lib/bds/desktop/shell_live/panel_renderer.ex:118
#: lib/bds/desktop/shell_live/panel_renderer.ex:217
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:310
#, elixir-autogen, elixir-format
msgid "Post Links"
@@ -1950,8 +1952,8 @@ msgstr "Beitrag gespeichert"
#: lib/bds/desktop/menu_bar.ex:233
#: lib/bds/desktop/shell_live/misc_editor.ex:664
#: lib/bds/desktop/shell_live/misc_editor.ex:761
#: lib/bds/tui.ex:1938
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1955
#: lib/bds/ui/registry.ex:14
#: lib/bds/ui/sidebar.ex:271
#, elixir-autogen, elixir-format
@@ -2081,14 +2083,14 @@ msgstr "Bereit zum Import:"
#: lib/bds/desktop/menu_bar.ex:248
#: lib/bds/tui.ex:1016
#: lib/bds/tui.ex:2080
#: lib/bds/tui.ex:2082
#, elixir-autogen, elixir-format
msgid "Rebuild Database"
msgstr "Datenbank neu aufbauen"
#: lib/bds/desktop/menu_bar.ex:250
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:381
#: lib/bds/tui.ex:2084
#: lib/bds/tui.ex:2086
#, elixir-autogen, elixir-format
msgid "Rebuild Embedding Index"
msgstr "Embedding-Index neu aufbauen"
@@ -2146,7 +2148,7 @@ msgid "Refresh Translation"
msgstr "Übersetzung aktualisieren"
#: lib/bds/desktop/menu_bar.ex:252
#: lib/bds/tui.ex:2087
#: lib/bds/tui.ex:2089
#, elixir-autogen, elixir-format
msgid "Regenerate Calendar"
msgstr "Kalender neu erzeugen"
@@ -2157,7 +2159,7 @@ msgid "Regenerate Missing Thumbnails"
msgstr "Fehlende Vorschaubilder neu erzeugen"
#: lib/bds/desktop/menu_bar.ex:249
#: lib/bds/tui.ex:2081
#: lib/bds/tui.ex:2083
#, elixir-autogen, elixir-format
msgid "Reindex Text"
msgstr "Text neu indizieren"
@@ -2342,10 +2344,11 @@ msgstr "Scripting-Funktionen werden in der Neufassung auf Anwendungsebene konfig
#: lib/bds/desktop/shell_live/script_editor.ex:175
#: lib/bds/desktop/shell_live/script_editor.ex:191
#: lib/bds/desktop/shell_live/script_editor.ex:194
#: lib/bds/desktop/shell_live/script_editor.ex:216
#: lib/bds/desktop/shell_live/script_editor.ex:219
#: lib/bds/desktop/shell_live/script_editor.ex:234
#: lib/bds/tui.ex:1941
#: lib/bds/desktop/shell_live/script_editor.ex:212
#: lib/bds/desktop/shell_live/script_editor.ex:222
#: lib/bds/desktop/shell_live/script_editor.ex:225
#: lib/bds/desktop/shell_live/script_editor.ex:240
#: lib/bds/tui.ex:1943
#: lib/bds/ui/registry.ex:38
#: lib/bds/ui/sidebar.ex:63
#: lib/bds/ui/sidebar.ex:115
@@ -2452,7 +2455,7 @@ msgstr "Semantische Ähnlichkeit"
#: lib/bds/desktop/shell_live/settings_editor/project_settings.ex:60
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:11
#: lib/bds/tui.ex:1943
#: lib/bds/tui.ex:1945
#: lib/bds/ui/registry.ex:86
#: lib/bds/ui/registry.ex:101
#: lib/bds/ui/sidebar.ex:795
@@ -2478,7 +2481,7 @@ msgstr "Website"
#: lib/bds/desktop/shell_live/misc_editor.ex:412
#: lib/bds/tui.ex:318
#: lib/bds/tui.ex:320
#: lib/bds/tui.ex:1668
#: lib/bds/tui.ex:1670
#: lib/bds/ui/registry.ex:125
#, elixir-autogen, elixir-format
msgid "Site Validation"
@@ -2575,7 +2578,7 @@ msgid "System Prompt"
msgstr "System-Prompt"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:16
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#: lib/bds/ui/sidebar.ex:785
#, elixir-autogen, elixir-format
msgid "Tag Cloud"
@@ -2602,8 +2605,8 @@ msgstr "Schlagwortname"
#: lib/bds/desktop/shell_live/tags_editor.ex:217
#: lib/bds/desktop/shell_live/tags_editor.ex:248
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:11
#: lib/bds/tui.ex:1920
#: lib/bds/tui.ex:1942
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1944
#: lib/bds/ui/registry.ex:54
#: lib/bds/ui/registry.ex:103
#: lib/bds/ui/sidebar.ex:289
@@ -2613,8 +2616,8 @@ msgstr "Schlagwortname"
msgid "Tags"
msgstr "Tags"
#: lib/bds/desktop/shell_live.ex:786
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#: lib/bds/desktop/shell_live.ex:819
#: lib/bds/desktop/shell_live/panel_renderer.ex:63
#: lib/bds/tui.ex:1220
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -2661,7 +2664,7 @@ msgstr "Template-Syntax ist gültig"
#: lib/bds/desktop/shell_live/template_editor.ex:171
#: lib/bds/desktop/shell_live/template_editor.ex:176
#: lib/bds/desktop/shell_live/template_editor.ex:191
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1942
#: lib/bds/ui/registry.ex:46
#: lib/bds/ui/sidebar.ex:71
#: lib/bds/ui/sidebar.ex:122
@@ -2670,7 +2673,7 @@ msgstr "Template-Syntax ist gültig"
msgid "Templates"
msgstr "Vorlagen"
#: lib/bds/desktop/shell_live/panel_renderer.ex:194
#: lib/bds/desktop/shell_live/panel_renderer.ex:293
#, elixir-autogen, elixir-format
msgid "The shared lower panel is available for tasks, output, git details, and editor-specific diagnostics."
msgstr "Das gemeinsame untere Panel steht für Aufgaben, Ausgabe, Git-Details und editorbezogene Diagnosen bereit."
@@ -2885,7 +2888,7 @@ msgid "Updated URLs"
msgstr "Aktualisierte URLs"
#: lib/bds/desktop/menu_bar.ex:259
#: lib/bds/tui.ex:2099
#: lib/bds/tui.ex:2101
#, elixir-autogen, elixir-format
msgid "Upload Site"
msgstr "Website hochladen"
@@ -2913,13 +2916,13 @@ msgid "Validate"
msgstr "Validieren"
#: lib/bds/desktop/menu_bar.ex:258
#: lib/bds/tui.ex:2077
#: lib/bds/tui.ex:2079
#, elixir-autogen, elixir-format
msgid "Validate Site"
msgstr "Website validieren"
#: lib/bds/desktop/menu_bar.ex:253
#: lib/bds/tui.ex:2090
#: lib/bds/tui.ex:2092
#, elixir-autogen, elixir-format
msgid "Validate Translations"
msgstr "Übersetzungen validieren"
@@ -3301,12 +3304,12 @@ msgstr "Willkommen beim KI-Assistenten"
msgid "Comparing database and filesystem metadata"
msgstr "Vergleicht Datenbank- und Dateisystem-Metadaten"
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:717
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} Bilder zum Beitrag hinzugefügt"
#: lib/bds/desktop/shell_live.ex:652
#: lib/bds/desktop/shell_live.ex:685
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} hinzugefügt"
@@ -3327,18 +3330,18 @@ msgstr "Endbenutzer-Anleitung für redaktionelle Arbeitsabläufe, Medien, Vorlag
msgid "Image Import Concurrency"
msgstr "Gleichzeitige Bildimporte"
#: lib/bds/desktop/shell_live.ex:444
#: lib/bds/desktop/shell_live.ex:457
#: lib/bds/desktop/shell_live.ex:651
#: lib/bds/desktop/shell_live.ex:683
#: lib/bds/desktop/shell_live.ex:694
#: lib/bds/desktop/shell_live.ex:705
#: lib/bds/desktop/shell_live.ex:477
#: lib/bds/desktop/shell_live.ex:490
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:716
#: lib/bds/desktop/shell_live.ex:727
#: lib/bds/desktop/shell_live.ex:738
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Galerie-Bilder hinzufügen"
#: lib/bds/desktop/shell_live.ex:706
#: lib/bds/desktop/shell_live.ex:739
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "%{path} konnte nicht verarbeitet werden: %{reason}"
@@ -3400,7 +3403,7 @@ msgid "Commit"
msgstr "Commit"
#: lib/bds/desktop/shell_live/sidebar_components.ex:555
#: lib/bds/tui.ex:1490
#: lib/bds/tui.ex:1492
#, elixir-autogen, elixir-format
msgid "Commit message"
msgstr "Commit-Nachricht"
@@ -3536,12 +3539,12 @@ msgstr "umbenannt"
msgid "untracked"
msgstr "nicht verfolgt"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:845
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:855
#: lib/bds/desktop/shell_live.ex:888
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Öffnen Sie ein Projekt, bevor Sie ein Blogmark importieren."
@@ -3582,7 +3585,7 @@ msgstr "Tag löschen"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Bookmarklet konnte nicht in die Zwischenablage kopiert werden"
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live.ex:857
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "Das Projekt, auf das dieses Blogmark verweist, existiert hier nicht."
@@ -3593,7 +3596,7 @@ msgid "Suggested tags"
msgstr "Vorgeschlagene Tags"
#: lib/bds/desktop/menu_bar.ex:257
#: lib/bds/tui.ex:2078
#: lib/bds/tui.ex:2080
#, elixir-autogen, elixir-format
msgid "Force Render Site"
msgstr "Website vollständig neu generieren"
@@ -3690,12 +3693,12 @@ msgstr "OK"
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "Der Endpunkt hat keine Modelle zurückgegeben. Sie können einen Modellnamen weiterhin manuell eingeben."
#: lib/bds/tui.ex:2036
#: lib/bds/tui.ex:2038
#, elixir-autogen, elixir-format
msgid "AI is unavailable in airplane mode without a local endpoint."
msgstr "KI ist im Flugmodus ohne lokalen Endpunkt nicht verfügbar."
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:2165
#, elixir-autogen, elixir-format
msgid "Could not load this file."
msgstr "Diese Datei konnte nicht geladen werden."
@@ -3710,12 +3713,12 @@ msgstr "Die Bearbeitung dieses Eintrags ist in der Terminal-Oberfläche noch nic
msgid "No suggestions returned."
msgstr "Keine Vorschläge erhalten."
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2162
#, elixir-autogen, elixir-format
msgid "Only images can be previewed."
msgstr "Nur Bilder können in der Vorschau angezeigt werden."
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1955
#, elixir-autogen, elixir-format
msgid "Post not found."
msgstr "Beitrag nicht gefunden."
@@ -3725,18 +3728,18 @@ msgstr "Beitrag nicht gefunden."
msgid "Press enter to preview %{name}."
msgstr "Drücken Sie Enter, um %{name} in der Vorschau anzuzeigen."
#: lib/bds/tui.ex:2006
#: lib/bds/tui.ex:2008
#, elixir-autogen, elixir-format
msgid "Published."
msgstr "Veröffentlicht."
#: lib/bds/tui.ex:2022
#: lib/bds/tui.ex:2024
#, elixir-autogen, elixir-format
msgid "Save before switching languages."
msgstr "Speichern Sie vor dem Sprachwechsel."
#: lib/bds/tui.ex:540
#: lib/bds/tui.ex:2007
#: lib/bds/tui.ex:2009
#, elixir-autogen, elixir-format
msgid "Saved."
msgstr "Gespeichert."
@@ -3761,18 +3764,18 @@ msgstr "Titel (Strg+T zum Bearbeiten)"
msgid "Title (editing — enter to confirm)"
msgstr "Titel (Bearbeitung — Enter zum Bestätigen)"
#: lib/bds/tui.ex:1492
#: lib/bds/tui.ex:1494
#, elixir-autogen, elixir-format
msgid "Working…"
msgstr "Wird bearbeitet…"
#: lib/bds/tui.ex:1514
#: lib/bds/tui.ex:1516
#, elixir-autogen, elixir-format
msgid "esc to close"
msgstr "Esc zum Schließen"
#: lib/bds/desktop/menu_bar.ex:83
#: lib/bds/desktop/shell_live.ex:1110
#: lib/bds/desktop/shell_live.ex:1176
#, elixir-autogen, elixir-format
msgid "Connect to Server"
msgstr "Mit Server verbinden"
@@ -3793,7 +3796,7 @@ msgid "Disconnect from Server"
msgstr "Verbindung zum Server trennen"
#: lib/bds/desktop/menu_bar.ex:72
#: lib/bds/desktop/shell_live.ex:1097
#: lib/bds/desktop/shell_live.ex:1163
#, elixir-autogen, elixir-format
msgid "Server address (user@host or user@host:port), public-key auth:"
msgstr "Serveradresse (user@host oder user@host:port), Public-Key-Authentifizierung:"
@@ -3803,12 +3806,12 @@ msgstr "Serveradresse (user@host oder user@host:port), Public-Key-Authentifizier
msgid "Use the form user@host or user@host:port."
msgstr "Verwenden Sie das Format user@host oder user@host:port."
#: lib/bds/tui.ex:1457
#: lib/bds/tui.ex:1456
#, elixir-autogen, elixir-format
msgid "Preview (ctrl+e to edit)"
msgstr "Vorschau (ctrl+e zum Bearbeiten)"
#: lib/bds/tui.ex:1771
#: lib/bds/tui.ex:1773
#, elixir-autogen, elixir-format
msgid "ctrl+s save · ctrl+p publish · ctrl+e preview · ctrl+t title · ctrl+l language · ctrl+g AI · esc back"
msgstr "Strg+S Speichern · Strg+P Veröffentlichen · Strg+E Vorschau · Strg+T Titel · Strg+L Sprache · Strg+G KI · Esc Zurück"
@@ -3818,7 +3821,7 @@ msgstr "Strg+S Speichern · Strg+P Veröffentlichen · Strg+E Vorschau · Strg+T
msgid "All tasks finished."
msgstr "Alle Aufgaben abgeschlossen."
#: lib/bds/tui.ex:1540
#: lib/bds/tui.ex:1542
#, elixir-autogen, elixir-format
msgid "Commands — esc to close"
msgstr "Befehle — Esc zum Schließen"
@@ -3828,27 +3831,27 @@ msgstr "Befehle — Esc zum Schließen"
msgid "Unknown command."
msgstr "Unbekannter Befehl."
#: lib/bds/tui.ex:1530
#: lib/bds/tui.ex:1532
#, elixir-autogen, elixir-format
msgid "[report/apply in GUI]"
msgstr "[Bericht/Anwenden in der GUI]"
#: lib/bds/tui.ex:1679
#: lib/bds/tui.ex:1681
#, elixir-autogen, elixir-format
msgid "%{diffs} differences · %{orphans} orphan files"
msgstr "%{diffs} Unterschiede · %{orphans} verwaiste Dateien"
#: lib/bds/tui.ex:1711
#: lib/bds/tui.ex:1713
#, elixir-autogen, elixir-format
msgid "Expected %{expected} · Existing %{existing}"
msgstr "Erwartet %{expected} · Vorhanden %{existing}"
#: lib/bds/tui.ex:1728
#: lib/bds/tui.ex:1730
#, elixir-autogen, elixir-format
msgid "Extra files (will be removed):"
msgstr "Überzählige Dateien (werden entfernt):"
#: lib/bds/tui.ex:1724
#: lib/bds/tui.ex:1726
#, elixir-autogen, elixir-format
msgid "Missing pages (will be rendered):"
msgstr "Fehlende Seiten (werden gerendert):"
@@ -3863,27 +3866,27 @@ msgstr "Nichts anzuwenden."
msgid "Nothing to repair."
msgstr "Nichts zu reparieren."
#: lib/bds/tui.ex:1702
#: lib/bds/tui.ex:1704
#, elixir-autogen, elixir-format
msgid "Orphan files (not in database):"
msgstr "Verwaiste Dateien (nicht in der Datenbank):"
#: lib/bds/tui.ex:1718
#: lib/bds/tui.ex:1720
#, elixir-autogen, elixir-format
msgid "Sitemap changed."
msgstr "Sitemap geändert."
#: lib/bds/tui.ex:1732
#: lib/bds/tui.ex:1734
#, elixir-autogen, elixir-format
msgid "Updated posts (will be re-rendered):"
msgstr "Aktualisierte Beiträge (werden neu gerendert):"
#: lib/bds/tui.ex:1669
#: lib/bds/tui.ex:1671
#, elixir-autogen, elixir-format
msgid "enter apply changes · esc close"
msgstr "Enter Änderungen anwenden · Esc Schließen"
#: lib/bds/tui.ex:1664
#: lib/bds/tui.ex:1666
#, elixir-autogen, elixir-format
msgid "enter repair all from files · esc close"
msgstr "Enter alles aus Dateien reparieren · Esc Schließen"
@@ -3898,7 +3901,7 @@ msgstr "Importierter Blog"
msgid "Not a folder: %{path}"
msgstr "Kein Ordner: %{path}"
#: lib/bds/tui.ex:1606
#: lib/bds/tui.ex:1608
#, elixir-autogen, elixir-format
msgid "Projects — enter switch · o open existing · esc close"
msgstr "Projekte — Enter Wechseln · O Bestehenden öffnen · Esc Schließen"
@@ -3908,12 +3911,12 @@ msgstr "Projekte — Enter Wechseln · O Bestehenden öffnen · Esc Schließen"
msgid "Switched to %{name}."
msgstr "Zu %{name} gewechselt."
#: lib/bds/tui.ex:1634
#: lib/bds/tui.ex:1636
#, elixir-autogen, elixir-format
msgid "Matching folders"
msgstr "Passende Ordner"
#: lib/bds/tui.ex:1572
#: lib/bds/tui.ex:1574
#, elixir-autogen, elixir-format
msgid "Open Existing Blog — type a folder path · tab complete · enter open · esc back"
msgstr "Bestehenden Blog öffnen — Ordnerpfad eingeben · Tab Vervollständigen · Enter Öffnen · Esc Zurück"
@@ -3933,7 +3936,7 @@ msgstr "Commit erstellt."
msgid "Diff (pgup/pgdn scroll)"
msgstr "Diff (Bild↑/Bild↓ blättern)"
#: lib/bds/tui.ex:1799
#: lib/bds/tui.ex:1801
#, elixir-autogen, elixir-format
msgid "No changes."
msgstr "Keine Änderungen."
@@ -4044,7 +4047,7 @@ msgstr "Theme"
msgid "enter edit · ctrl+s save · esc close"
msgstr "Enter Bearbeiten · Strg+S Speichern · Esc Schließen"
#: lib/bds/tui.ex:1750
#: lib/bds/tui.ex:1752
#, elixir-autogen, elixir-format
msgid "enter edit/toggle/cycle · ctrl+s save · esc close · ctrl+q quit"
msgstr "Enter Bearbeiten/Umschalten/Wechseln · Strg+S Speichern · Esc Schließen · Strg+Q Beenden"
@@ -4054,12 +4057,12 @@ msgstr "Enter Bearbeiten/Umschalten/Wechseln · Strg+S Speichern · Esc Schließ
msgid "not supported yet"
msgstr "noch nicht unterstützt"
#: lib/bds/tui.ex:1757
#: lib/bds/tui.ex:1759
#, elixir-autogen, elixir-format
msgid "c commit · u pull · s push · enter jump to file · pgup/pgdn scroll diff · 1-7 views · ctrl+q quit"
msgstr "C Commit · U Pull · S Push · Enter Zur Datei springen · Bild↑/Bild↓ Diff blättern · 1-7 Ansichten · Strg+Q Beenden"
#: lib/bds/tui.ex:1764
#: lib/bds/tui.ex:1766
#, elixir-autogen, elixir-format
msgid "enter open · n new post · 1-7 views · p projects · / search · : commands (:? help) · r refresh · ctrl+q quit"
msgstr "Enter Öffnen · N Neuer Beitrag · 1-7 Ansichten · P Projekte · / Suche · : Befehle (:? Hilfe) · R Aktualisieren · Strg+Q Beenden"
@@ -4191,12 +4194,12 @@ msgstr "Das Ziel der Zusammenführung muss eines der markierten Schlagwörter se
msgid "default"
msgstr "Standard"
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#, elixir-autogen, elixir-format
msgid "esc close"
msgstr "Esc schließen"
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1924
#, elixir-autogen, elixir-format
msgid "n new · enter rename · c colour · t template · d delete · s sync · esc close"
msgstr "n neu · Enter umbenennen · c Farbe · t Vorlage · d löschen · s synchronisieren · Esc schließen"
@@ -4206,7 +4209,17 @@ msgstr "n neu · Enter umbenennen · c Farbe · t Vorlage · d löschen · s syn
msgid "none"
msgstr "keine"
#: lib/bds/tui.ex:1927
#: lib/bds/tui.ex:1929
#, elixir-autogen, elixir-format
msgid "space mark · m merge into selected · esc close"
msgstr "Leertaste markieren · m in Auswahl zusammenführen · Esc schließen"
#: lib/bds/desktop/shell_live/panel_renderer.ex:157
#, elixir-autogen, elixir-format
msgid "Pending"
msgstr "Ausstehend"
#: lib/bds/desktop/shell_live/panel_renderer.ex:156
#, elixir-autogen, elixir-format
msgid "Running"
msgstr "Läuft"
+115 -102
View File
@@ -86,7 +86,7 @@ msgstr ""
#: lib/bds/tui.ex:1175
#: lib/bds/tui.ex:1178
#: lib/bds/tui.ex:1186
#: lib/bds/tui.ex:2035
#: lib/bds/tui.ex:2037
#, elixir-autogen, elixir-format
msgid "AI Suggestions"
msgstr ""
@@ -343,7 +343,7 @@ msgstr ""
msgid "Auto"
msgstr ""
#: lib/bds/desktop/shell_live.ex:445
#: lib/bds/desktop/shell_live.ex:478
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -368,7 +368,7 @@ msgstr ""
msgid "Available languages"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:124
#: lib/bds/desktop/shell_live/panel_renderer.ex:223
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:313
#, elixir-autogen, elixir-format
msgid "Backlinks"
@@ -441,6 +441,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#: lib/bds/desktop/shell_live/panel_renderer.ex:143
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr ""
@@ -494,7 +495,7 @@ msgstr ""
msgid "Category name is required"
msgstr ""
#: lib/bds/desktop/shell_live.ex:791
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -575,7 +576,7 @@ msgid "Collapse unchanged diff hunks"
msgstr ""
#: lib/bds/desktop/shell_live/overlay_manager.ex:423
#: lib/bds/tui.ex:2131
#: lib/bds/tui.ex:2133
#, elixir-autogen, elixir-format
msgid "Command completed"
msgstr ""
@@ -593,7 +594,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:375
#: lib/bds/desktop/shell_live/script_editor_html/script_editor.html.heex:34
#: lib/bds/desktop/shell_live/template_editor_html/template_editor.html.heex:32
#: lib/bds/tui.ex:1468
#: lib/bds/tui.ex:1467
#: lib/bds/ui/settings_form.ex:137
#: lib/bds/ui/sidebar.ex:801
#, elixir-autogen, elixir-format
@@ -606,6 +607,7 @@ msgid "Content Categories"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:226
#: lib/bds/desktop/shell_live/panel_renderer.ex:183
#, elixir-autogen, elixir-format
msgid "Copy"
msgstr ""
@@ -1040,7 +1042,7 @@ msgid "Filename"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:254
#: lib/bds/tui.ex:2095
#: lib/bds/tui.ex:2097
#, elixir-autogen, elixir-format
msgid "Fill Missing Translations"
msgstr ""
@@ -1051,7 +1053,7 @@ msgid "Find"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:255
#: lib/bds/tui.ex:2098
#: lib/bds/tui.ex:2100
#, elixir-autogen, elixir-format
msgid "Find Duplicate Posts"
msgstr ""
@@ -1078,14 +1080,14 @@ msgid "Gallery"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:256
#: lib/bds/tui.ex:2079
#: lib/bds/tui.ex:2081
#, elixir-autogen, elixir-format
msgid "Generate Site"
msgstr ""
#: lib/bds/desktop/shell_live.ex:792
#: lib/bds/desktop/shell_live.ex:825
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/tui.ex:1944
#: lib/bds/tui.ex:1946
#: lib/bds/ui/sidebar.ex:826
#, elixir-autogen, elixir-format
msgid "Git"
@@ -1098,8 +1100,8 @@ msgid "Git Diff"
msgstr ""
#: lib/bds/desktop/shell_data.ex:228
#: lib/bds/desktop/shell_live.ex:788
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#: lib/bds/desktop/shell_live.ex:821
#: lib/bds/desktop/shell_live/panel_renderer.ex:270
#, elixir-autogen, elixir-format
msgid "Git Log"
msgstr ""
@@ -1222,9 +1224,9 @@ msgstr ""
msgid "Import failed: %{error}"
msgstr ""
#: lib/bds/desktop/shell_live.ex:608
#: lib/bds/desktop/shell_live.ex:904
#: lib/bds/desktop/shell_live.ex:910
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:970
#: lib/bds/desktop/shell_live.ex:976
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1325,7 +1327,7 @@ msgstr ""
msgid "Linked Posts"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:142
#: lib/bds/desktop/shell_live/panel_renderer.ex:241
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:325
#, elixir-autogen, elixir-format
msgid "Links To"
@@ -1404,9 +1406,9 @@ msgstr ""
#: lib/bds/desktop/shell_live/misc_editor.ex:762
#: lib/bds/desktop/shell_live/sidebar_components.ex:654
#: lib/bds/desktop/shell_live/sidebar_delete.ex:175
#: lib/bds/tui.ex:1939
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:1941
#: lib/bds/tui.ex:2162
#: lib/bds/tui.ex:2165
#: lib/bds/ui/registry.ex:30
#: lib/bds/ui/registry.ex:100
#: lib/bds/ui/sidebar.ex:578
@@ -1435,7 +1437,7 @@ msgid "Merge"
msgstr ""
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:78
#: lib/bds/tui.ex:1926
#: lib/bds/tui.ex:1928
#: lib/bds/ui/sidebar.ex:787
#, elixir-autogen, elixir-format
msgid "Merge Tags"
@@ -1453,8 +1455,8 @@ msgstr ""
#: lib/bds/tui.ex:285
#: lib/bds/tui.ex:291
#: lib/bds/tui.ex:302
#: lib/bds/tui.ex:1663
#: lib/bds/tui.ex:2076
#: lib/bds/tui.ex:1665
#: lib/bds/tui.ex:2078
#: lib/bds/ui/registry.ex:111
#, elixir-autogen, elixir-format
msgid "Metadata Diff"
@@ -1532,12 +1534,12 @@ msgstr ""
msgid "No Template"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:55
#: lib/bds/desktop/shell_live/panel_renderer.ex:64
#, elixir-autogen, elixir-format
msgid "No background tasks running"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:179
#: lib/bds/desktop/shell_live/panel_renderer.ex:278
#, elixir-autogen, elixir-format
msgid "No commit subject"
msgstr ""
@@ -1547,7 +1549,7 @@ msgstr ""
msgid "No folder selected"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#: lib/bds/desktop/shell_live/panel_renderer.ex:271
#, elixir-autogen, elixir-format
msgid "No git history yet"
msgstr ""
@@ -1607,7 +1609,7 @@ msgstr ""
msgid "No pages yet"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:119
#: lib/bds/desktop/shell_live/panel_renderer.ex:218
#, elixir-autogen, elixir-format
msgid "No post links yet"
msgstr ""
@@ -1632,7 +1634,7 @@ msgstr ""
msgid "No settings match the current search"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:84
#: lib/bds/desktop/shell_live/panel_renderer.ex:173
#, elixir-autogen, elixir-format
msgid "No shell output yet"
msgstr ""
@@ -1801,7 +1803,7 @@ msgid "Open Settings"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:217
#: lib/bds/tui.ex:2100
#: lib/bds/tui.ex:2102
#, elixir-autogen, elixir-format
msgid "Open in Browser"
msgstr ""
@@ -1832,8 +1834,8 @@ msgstr ""
msgid "Other (%{count})"
msgstr ""
#: lib/bds/desktop/shell_live.ex:787
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#: lib/bds/desktop/shell_live.ex:820
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#, elixir-autogen, elixir-format
msgid "Output"
msgstr ""
@@ -1915,7 +1917,7 @@ msgid "Post"
msgstr ""
#: lib/bds/desktop/shell_data.ex:231
#: lib/bds/desktop/shell_live/panel_renderer.ex:118
#: lib/bds/desktop/shell_live/panel_renderer.ex:217
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:310
#, elixir-autogen, elixir-format
msgid "Post Links"
@@ -1950,8 +1952,8 @@ msgstr ""
#: lib/bds/desktop/menu_bar.ex:233
#: lib/bds/desktop/shell_live/misc_editor.ex:664
#: lib/bds/desktop/shell_live/misc_editor.ex:761
#: lib/bds/tui.ex:1938
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1955
#: lib/bds/ui/registry.ex:14
#: lib/bds/ui/sidebar.ex:271
#, elixir-autogen, elixir-format
@@ -2081,14 +2083,14 @@ msgstr ""
#: lib/bds/desktop/menu_bar.ex:248
#: lib/bds/tui.ex:1016
#: lib/bds/tui.ex:2080
#: lib/bds/tui.ex:2082
#, elixir-autogen, elixir-format
msgid "Rebuild Database"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:250
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:381
#: lib/bds/tui.ex:2084
#: lib/bds/tui.ex:2086
#, elixir-autogen, elixir-format
msgid "Rebuild Embedding Index"
msgstr ""
@@ -2146,7 +2148,7 @@ msgid "Refresh Translation"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:252
#: lib/bds/tui.ex:2087
#: lib/bds/tui.ex:2089
#, elixir-autogen, elixir-format
msgid "Regenerate Calendar"
msgstr ""
@@ -2157,7 +2159,7 @@ msgid "Regenerate Missing Thumbnails"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:249
#: lib/bds/tui.ex:2081
#: lib/bds/tui.ex:2083
#, elixir-autogen, elixir-format
msgid "Reindex Text"
msgstr ""
@@ -2342,10 +2344,11 @@ msgstr ""
#: lib/bds/desktop/shell_live/script_editor.ex:175
#: lib/bds/desktop/shell_live/script_editor.ex:191
#: lib/bds/desktop/shell_live/script_editor.ex:194
#: lib/bds/desktop/shell_live/script_editor.ex:216
#: lib/bds/desktop/shell_live/script_editor.ex:219
#: lib/bds/desktop/shell_live/script_editor.ex:234
#: lib/bds/tui.ex:1941
#: lib/bds/desktop/shell_live/script_editor.ex:212
#: lib/bds/desktop/shell_live/script_editor.ex:222
#: lib/bds/desktop/shell_live/script_editor.ex:225
#: lib/bds/desktop/shell_live/script_editor.ex:240
#: lib/bds/tui.ex:1943
#: lib/bds/ui/registry.ex:38
#: lib/bds/ui/sidebar.ex:63
#: lib/bds/ui/sidebar.ex:115
@@ -2452,7 +2455,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/project_settings.ex:60
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:11
#: lib/bds/tui.ex:1943
#: lib/bds/tui.ex:1945
#: lib/bds/ui/registry.ex:86
#: lib/bds/ui/registry.ex:101
#: lib/bds/ui/sidebar.ex:795
@@ -2478,7 +2481,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/misc_editor.ex:412
#: lib/bds/tui.ex:318
#: lib/bds/tui.ex:320
#: lib/bds/tui.ex:1668
#: lib/bds/tui.ex:1670
#: lib/bds/ui/registry.ex:125
#, elixir-autogen, elixir-format
msgid "Site Validation"
@@ -2575,7 +2578,7 @@ msgid "System Prompt"
msgstr ""
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:16
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#: lib/bds/ui/sidebar.ex:785
#, elixir-autogen, elixir-format
msgid "Tag Cloud"
@@ -2602,8 +2605,8 @@ msgstr ""
#: lib/bds/desktop/shell_live/tags_editor.ex:217
#: lib/bds/desktop/shell_live/tags_editor.ex:248
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:11
#: lib/bds/tui.ex:1920
#: lib/bds/tui.ex:1942
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1944
#: lib/bds/ui/registry.ex:54
#: lib/bds/ui/registry.ex:103
#: lib/bds/ui/sidebar.ex:289
@@ -2613,8 +2616,8 @@ msgstr ""
msgid "Tags"
msgstr ""
#: lib/bds/desktop/shell_live.ex:786
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#: lib/bds/desktop/shell_live.ex:819
#: lib/bds/desktop/shell_live/panel_renderer.ex:63
#: lib/bds/tui.ex:1220
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -2661,7 +2664,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/template_editor.ex:171
#: lib/bds/desktop/shell_live/template_editor.ex:176
#: lib/bds/desktop/shell_live/template_editor.ex:191
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1942
#: lib/bds/ui/registry.ex:46
#: lib/bds/ui/sidebar.ex:71
#: lib/bds/ui/sidebar.ex:122
@@ -2670,7 +2673,7 @@ msgstr ""
msgid "Templates"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:194
#: lib/bds/desktop/shell_live/panel_renderer.ex:293
#, elixir-autogen, elixir-format
msgid "The shared lower panel is available for tasks, output, git details, and editor-specific diagnostics."
msgstr ""
@@ -2885,7 +2888,7 @@ msgid "Updated URLs"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:259
#: lib/bds/tui.ex:2099
#: lib/bds/tui.ex:2101
#, elixir-autogen, elixir-format
msgid "Upload Site"
msgstr ""
@@ -2913,13 +2916,13 @@ msgid "Validate"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:258
#: lib/bds/tui.ex:2077
#: lib/bds/tui.ex:2079
#, elixir-autogen, elixir-format
msgid "Validate Site"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:253
#: lib/bds/tui.ex:2090
#: lib/bds/tui.ex:2092
#, elixir-autogen, elixir-format
msgid "Validate Translations"
msgstr ""
@@ -3301,12 +3304,12 @@ msgstr ""
msgid "Comparing database and filesystem metadata"
msgstr "Comparing database and filesystem metadata"
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:717
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "Added %{count} images to post"
#: lib/bds/desktop/shell_live.ex:652
#: lib/bds/desktop/shell_live.ex:685
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "Added %{title}"
@@ -3327,18 +3330,18 @@ msgstr ""
msgid "Image Import Concurrency"
msgstr "Image Import Concurrency"
#: lib/bds/desktop/shell_live.ex:444
#: lib/bds/desktop/shell_live.ex:457
#: lib/bds/desktop/shell_live.ex:651
#: lib/bds/desktop/shell_live.ex:683
#: lib/bds/desktop/shell_live.ex:694
#: lib/bds/desktop/shell_live.ex:705
#: lib/bds/desktop/shell_live.ex:477
#: lib/bds/desktop/shell_live.ex:490
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:716
#: lib/bds/desktop/shell_live.ex:727
#: lib/bds/desktop/shell_live.ex:738
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Add Gallery Images"
#: lib/bds/desktop/shell_live.ex:706
#: lib/bds/desktop/shell_live.ex:739
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "Failed to process %{path}: %{reason}"
@@ -3400,7 +3403,7 @@ msgid "Commit"
msgstr ""
#: lib/bds/desktop/shell_live/sidebar_components.ex:555
#: lib/bds/tui.ex:1490
#: lib/bds/tui.ex:1492
#, elixir-autogen, elixir-format
msgid "Commit message"
msgstr ""
@@ -3536,12 +3539,12 @@ msgstr ""
msgid "untracked"
msgstr ""
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:845
#, elixir-autogen, elixir-format, fuzzy
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:855
#: lib/bds/desktop/shell_live.ex:888
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr ""
@@ -3582,7 +3585,7 @@ msgstr ""
msgid "Failed to copy bookmarklet to clipboard"
msgstr ""
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live.ex:857
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr ""
@@ -3593,7 +3596,7 @@ msgid "Suggested tags"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:257
#: lib/bds/tui.ex:2078
#: lib/bds/tui.ex:2080
#, elixir-autogen, elixir-format
msgid "Force Render Site"
msgstr ""
@@ -3690,12 +3693,12 @@ msgstr ""
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr ""
#: lib/bds/tui.ex:2036
#: lib/bds/tui.ex:2038
#, elixir-autogen, elixir-format
msgid "AI is unavailable in airplane mode without a local endpoint."
msgstr ""
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:2165
#, elixir-autogen, elixir-format, fuzzy
msgid "Could not load this file."
msgstr ""
@@ -3710,12 +3713,12 @@ msgstr ""
msgid "No suggestions returned."
msgstr ""
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2162
#, elixir-autogen, elixir-format
msgid "Only images can be previewed."
msgstr ""
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1955
#, elixir-autogen, elixir-format
msgid "Post not found."
msgstr ""
@@ -3725,18 +3728,18 @@ msgstr ""
msgid "Press enter to preview %{name}."
msgstr ""
#: lib/bds/tui.ex:2006
#: lib/bds/tui.ex:2008
#, elixir-autogen, elixir-format, fuzzy
msgid "Published."
msgstr ""
#: lib/bds/tui.ex:2022
#: lib/bds/tui.ex:2024
#, elixir-autogen, elixir-format
msgid "Save before switching languages."
msgstr ""
#: lib/bds/tui.ex:540
#: lib/bds/tui.ex:2007
#: lib/bds/tui.ex:2009
#, elixir-autogen, elixir-format, fuzzy
msgid "Saved."
msgstr ""
@@ -3761,18 +3764,18 @@ msgstr ""
msgid "Title (editing — enter to confirm)"
msgstr ""
#: lib/bds/tui.ex:1492
#: lib/bds/tui.ex:1494
#, elixir-autogen, elixir-format, fuzzy
msgid "Working…"
msgstr ""
#: lib/bds/tui.ex:1514
#: lib/bds/tui.ex:1516
#, elixir-autogen, elixir-format
msgid "esc to close"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:83
#: lib/bds/desktop/shell_live.ex:1110
#: lib/bds/desktop/shell_live.ex:1176
#, elixir-autogen, elixir-format
msgid "Connect to Server"
msgstr ""
@@ -3793,7 +3796,7 @@ msgid "Disconnect from Server"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:72
#: lib/bds/desktop/shell_live.ex:1097
#: lib/bds/desktop/shell_live.ex:1163
#, elixir-autogen, elixir-format
msgid "Server address (user@host or user@host:port), public-key auth:"
msgstr ""
@@ -3803,12 +3806,12 @@ msgstr ""
msgid "Use the form user@host or user@host:port."
msgstr ""
#: lib/bds/tui.ex:1457
#: lib/bds/tui.ex:1456
#, elixir-autogen, elixir-format
msgid "Preview (ctrl+e to edit)"
msgstr ""
#: lib/bds/tui.ex:1771
#: lib/bds/tui.ex:1773
#, elixir-autogen, elixir-format, fuzzy
msgid "ctrl+s save · ctrl+p publish · ctrl+e preview · ctrl+t title · ctrl+l language · ctrl+g AI · esc back"
msgstr ""
@@ -3818,7 +3821,7 @@ msgstr ""
msgid "All tasks finished."
msgstr ""
#: lib/bds/tui.ex:1540
#: lib/bds/tui.ex:1542
#, elixir-autogen, elixir-format
msgid "Commands — esc to close"
msgstr ""
@@ -3828,27 +3831,27 @@ msgstr ""
msgid "Unknown command."
msgstr ""
#: lib/bds/tui.ex:1530
#: lib/bds/tui.ex:1532
#, elixir-autogen, elixir-format
msgid "[report/apply in GUI]"
msgstr ""
#: lib/bds/tui.ex:1679
#: lib/bds/tui.ex:1681
#, elixir-autogen, elixir-format
msgid "%{diffs} differences · %{orphans} orphan files"
msgstr ""
#: lib/bds/tui.ex:1711
#: lib/bds/tui.ex:1713
#, elixir-autogen, elixir-format
msgid "Expected %{expected} · Existing %{existing}"
msgstr ""
#: lib/bds/tui.ex:1728
#: lib/bds/tui.ex:1730
#, elixir-autogen, elixir-format
msgid "Extra files (will be removed):"
msgstr ""
#: lib/bds/tui.ex:1724
#: lib/bds/tui.ex:1726
#, elixir-autogen, elixir-format
msgid "Missing pages (will be rendered):"
msgstr ""
@@ -3863,27 +3866,27 @@ msgstr ""
msgid "Nothing to repair."
msgstr ""
#: lib/bds/tui.ex:1702
#: lib/bds/tui.ex:1704
#, elixir-autogen, elixir-format
msgid "Orphan files (not in database):"
msgstr ""
#: lib/bds/tui.ex:1718
#: lib/bds/tui.ex:1720
#, elixir-autogen, elixir-format
msgid "Sitemap changed."
msgstr ""
#: lib/bds/tui.ex:1732
#: lib/bds/tui.ex:1734
#, elixir-autogen, elixir-format
msgid "Updated posts (will be re-rendered):"
msgstr ""
#: lib/bds/tui.ex:1669
#: lib/bds/tui.ex:1671
#, elixir-autogen, elixir-format
msgid "enter apply changes · esc close"
msgstr ""
#: lib/bds/tui.ex:1664
#: lib/bds/tui.ex:1666
#, elixir-autogen, elixir-format
msgid "enter repair all from files · esc close"
msgstr ""
@@ -3898,7 +3901,7 @@ msgstr ""
msgid "Not a folder: %{path}"
msgstr ""
#: lib/bds/tui.ex:1606
#: lib/bds/tui.ex:1608
#, elixir-autogen, elixir-format
msgid "Projects — enter switch · o open existing · esc close"
msgstr ""
@@ -3908,12 +3911,12 @@ msgstr ""
msgid "Switched to %{name}."
msgstr ""
#: lib/bds/tui.ex:1634
#: lib/bds/tui.ex:1636
#, elixir-autogen, elixir-format
msgid "Matching folders"
msgstr ""
#: lib/bds/tui.ex:1572
#: lib/bds/tui.ex:1574
#, elixir-autogen, elixir-format, fuzzy
msgid "Open Existing Blog — type a folder path · tab complete · enter open · esc back"
msgstr ""
@@ -3933,7 +3936,7 @@ msgstr ""
msgid "Diff (pgup/pgdn scroll)"
msgstr ""
#: lib/bds/tui.ex:1799
#: lib/bds/tui.ex:1801
#, elixir-autogen, elixir-format, fuzzy
msgid "No changes."
msgstr ""
@@ -4044,7 +4047,7 @@ msgstr ""
msgid "enter edit · ctrl+s save · esc close"
msgstr ""
#: lib/bds/tui.ex:1750
#: lib/bds/tui.ex:1752
#, elixir-autogen, elixir-format
msgid "enter edit/toggle/cycle · ctrl+s save · esc close · ctrl+q quit"
msgstr ""
@@ -4054,12 +4057,12 @@ msgstr ""
msgid "not supported yet"
msgstr ""
#: lib/bds/tui.ex:1757
#: lib/bds/tui.ex:1759
#, elixir-autogen, elixir-format, fuzzy
msgid "c commit · u pull · s push · enter jump to file · pgup/pgdn scroll diff · 1-7 views · ctrl+q quit"
msgstr ""
#: lib/bds/tui.ex:1764
#: lib/bds/tui.ex:1766
#, elixir-autogen, elixir-format, fuzzy
msgid "enter open · n new post · 1-7 views · p projects · / search · : commands (:? help) · r refresh · ctrl+q quit"
msgstr ""
@@ -4191,12 +4194,12 @@ msgstr ""
msgid "default"
msgstr ""
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#, elixir-autogen, elixir-format, fuzzy
msgid "esc close"
msgstr ""
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1924
#, elixir-autogen, elixir-format
msgid "n new · enter rename · c colour · t template · d delete · s sync · esc close"
msgstr ""
@@ -4206,7 +4209,17 @@ msgstr ""
msgid "none"
msgstr ""
#: lib/bds/tui.ex:1927
#: lib/bds/tui.ex:1929
#, elixir-autogen, elixir-format
msgid "space mark · m merge into selected · esc close"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:157
#, elixir-autogen, elixir-format
msgid "Pending"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:156
#, elixir-autogen, elixir-format, fuzzy
msgid "Running"
msgstr ""
+115 -102
View File
@@ -86,7 +86,7 @@ msgstr "Configuración de IA"
#: lib/bds/tui.ex:1175
#: lib/bds/tui.ex:1178
#: lib/bds/tui.ex:1186
#: lib/bds/tui.ex:2035
#: lib/bds/tui.ex:2037
#, elixir-autogen, elixir-format
msgid "AI Suggestions"
msgstr "Sugerencias de IA"
@@ -343,7 +343,7 @@ msgstr "Autor"
msgid "Auto"
msgstr "Automático"
#: lib/bds/desktop/shell_live.ex:445
#: lib/bds/desktop/shell_live.ex:478
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -368,7 +368,7 @@ msgstr "Ayudas de automatización"
msgid "Available languages"
msgstr "Idiomas disponibles"
#: lib/bds/desktop/shell_live/panel_renderer.ex:124
#: lib/bds/desktop/shell_live/panel_renderer.ex:223
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:313
#, elixir-autogen, elixir-format
msgid "Backlinks"
@@ -441,6 +441,7 @@ msgstr "La copia del bookmarklet está conectada mediante el entorno de escritor
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#: lib/bds/desktop/shell_live/panel_renderer.ex:143
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Cancelar"
@@ -494,7 +495,7 @@ msgstr "Valores predeterminados de categoría, opciones de renderizado y conexi
msgid "Category name is required"
msgstr "El nombre de la categoría es obligatorio"
#: lib/bds/desktop/shell_live.ex:791
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -575,7 +576,7 @@ msgid "Collapse unchanged diff hunks"
msgstr "Contraer bloques de diff sin cambios"
#: lib/bds/desktop/shell_live/overlay_manager.ex:423
#: lib/bds/tui.ex:2131
#: lib/bds/tui.ex:2133
#, elixir-autogen, elixir-format
msgid "Command completed"
msgstr "Comando completado"
@@ -593,7 +594,7 @@ msgstr "Confirmar"
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:375
#: lib/bds/desktop/shell_live/script_editor_html/script_editor.html.heex:34
#: lib/bds/desktop/shell_live/template_editor_html/template_editor.html.heex:32
#: lib/bds/tui.ex:1468
#: lib/bds/tui.ex:1467
#: lib/bds/ui/settings_form.ex:137
#: lib/bds/ui/sidebar.ex:801
#, elixir-autogen, elixir-format
@@ -606,6 +607,7 @@ msgid "Content Categories"
msgstr "Categorías de contenido"
#: lib/bds/desktop/menu_bar.ex:226
#: lib/bds/desktop/shell_live/panel_renderer.ex:183
#, elixir-autogen, elixir-format
msgid "Copy"
msgstr "Copiar"
@@ -1040,7 +1042,7 @@ msgid "Filename"
msgstr "Nombre de archivo"
#: lib/bds/desktop/menu_bar.ex:254
#: lib/bds/tui.ex:2095
#: lib/bds/tui.ex:2097
#, elixir-autogen, elixir-format
msgid "Fill Missing Translations"
msgstr "Completar traducciones faltantes"
@@ -1051,7 +1053,7 @@ msgid "Find"
msgstr "Buscar"
#: lib/bds/desktop/menu_bar.ex:255
#: lib/bds/tui.ex:2098
#: lib/bds/tui.ex:2100
#, elixir-autogen, elixir-format
msgid "Find Duplicate Posts"
msgstr "Buscar entradas duplicadas"
@@ -1078,14 +1080,14 @@ msgid "Gallery"
msgstr "Galeria"
#: lib/bds/desktop/menu_bar.ex:256
#: lib/bds/tui.ex:2079
#: lib/bds/tui.ex:2081
#, elixir-autogen, elixir-format
msgid "Generate Site"
msgstr "Generar sitio"
#: lib/bds/desktop/shell_live.ex:792
#: lib/bds/desktop/shell_live.ex:825
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/tui.ex:1944
#: lib/bds/tui.ex:1946
#: lib/bds/ui/sidebar.ex:826
#, elixir-autogen, elixir-format
msgid "Git"
@@ -1098,8 +1100,8 @@ msgid "Git Diff"
msgstr "Diff de Git"
#: lib/bds/desktop/shell_data.ex:228
#: lib/bds/desktop/shell_live.ex:788
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#: lib/bds/desktop/shell_live.ex:821
#: lib/bds/desktop/shell_live/panel_renderer.ex:270
#, elixir-autogen, elixir-format
msgid "Git Log"
msgstr "Registro Git"
@@ -1222,9 +1224,9 @@ msgstr "Definiciones de importación"
msgid "Import failed: %{error}"
msgstr "La importación falló: %{error}"
#: lib/bds/desktop/shell_live.ex:608
#: lib/bds/desktop/shell_live.ex:904
#: lib/bds/desktop/shell_live.ex:910
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:970
#: lib/bds/desktop/shell_live.ex:976
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1325,7 +1327,7 @@ msgstr "Medios vinculados"
msgid "Linked Posts"
msgstr "Publicaciones enlazadas"
#: lib/bds/desktop/shell_live/panel_renderer.ex:142
#: lib/bds/desktop/shell_live/panel_renderer.ex:241
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:325
#, elixir-autogen, elixir-format
msgid "Links To"
@@ -1404,9 +1406,9 @@ msgstr "Máximo de publicaciones por página"
#: lib/bds/desktop/shell_live/misc_editor.ex:762
#: lib/bds/desktop/shell_live/sidebar_components.ex:654
#: lib/bds/desktop/shell_live/sidebar_delete.ex:175
#: lib/bds/tui.ex:1939
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:1941
#: lib/bds/tui.ex:2162
#: lib/bds/tui.ex:2165
#: lib/bds/ui/registry.ex:30
#: lib/bds/ui/registry.ex:100
#: lib/bds/ui/sidebar.ex:578
@@ -1435,7 +1437,7 @@ msgid "Merge"
msgstr "Fusionar"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:78
#: lib/bds/tui.ex:1926
#: lib/bds/tui.ex:1928
#: lib/bds/ui/sidebar.ex:787
#, elixir-autogen, elixir-format
msgid "Merge Tags"
@@ -1453,8 +1455,8 @@ msgstr "Metadatos"
#: lib/bds/tui.ex:285
#: lib/bds/tui.ex:291
#: lib/bds/tui.ex:302
#: lib/bds/tui.ex:1663
#: lib/bds/tui.ex:2076
#: lib/bds/tui.ex:1665
#: lib/bds/tui.ex:2078
#: lib/bds/ui/registry.ex:111
#, elixir-autogen, elixir-format
msgid "Metadata Diff"
@@ -1532,12 +1534,12 @@ msgstr "Nueva plantilla"
msgid "No Template"
msgstr "Sin plantilla"
#: lib/bds/desktop/shell_live/panel_renderer.ex:55
#: lib/bds/desktop/shell_live/panel_renderer.ex:64
#, elixir-autogen, elixir-format
msgid "No background tasks running"
msgstr "No hay tareas en segundo plano en ejecución"
#: lib/bds/desktop/shell_live/panel_renderer.ex:179
#: lib/bds/desktop/shell_live/panel_renderer.ex:278
#, elixir-autogen, elixir-format
msgid "No commit subject"
msgstr "Sin asunto de commit"
@@ -1547,7 +1549,7 @@ msgstr "Sin asunto de commit"
msgid "No folder selected"
msgstr "Ninguna carpeta seleccionada"
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#: lib/bds/desktop/shell_live/panel_renderer.ex:271
#, elixir-autogen, elixir-format
msgid "No git history yet"
msgstr "Aún no hay historial de Git"
@@ -1607,7 +1609,7 @@ msgstr "No hay archivos huérfanos seleccionados"
msgid "No pages yet"
msgstr "Aún no hay páginas"
#: lib/bds/desktop/shell_live/panel_renderer.ex:119
#: lib/bds/desktop/shell_live/panel_renderer.ex:218
#, elixir-autogen, elixir-format
msgid "No post links yet"
msgstr "Aún no hay enlaces a artículos"
@@ -1632,7 +1634,7 @@ msgstr "No hay ninguna acción de reparación disponible"
msgid "No settings match the current search"
msgstr "Ninguna configuración coincide con la búsqueda actual"
#: lib/bds/desktop/shell_live/panel_renderer.ex:84
#: lib/bds/desktop/shell_live/panel_renderer.ex:173
#, elixir-autogen, elixir-format
msgid "No shell output yet"
msgstr "Aún no hay salida del shell"
@@ -1801,7 +1803,7 @@ msgid "Open Settings"
msgstr "Abrir Ajustes"
#: lib/bds/desktop/menu_bar.ex:217
#: lib/bds/tui.ex:2100
#: lib/bds/tui.ex:2102
#, elixir-autogen, elixir-format
msgid "Open in Browser"
msgstr "Abrir en el navegador"
@@ -1832,8 +1834,8 @@ msgstr "Otros"
msgid "Other (%{count})"
msgstr "Otros (%{count})"
#: lib/bds/desktop/shell_live.ex:787
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#: lib/bds/desktop/shell_live.ex:820
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#, elixir-autogen, elixir-format
msgid "Output"
msgstr "Salida"
@@ -1915,7 +1917,7 @@ msgid "Post"
msgstr "Publicación"
#: lib/bds/desktop/shell_data.ex:231
#: lib/bds/desktop/shell_live/panel_renderer.ex:118
#: lib/bds/desktop/shell_live/panel_renderer.ex:217
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:310
#, elixir-autogen, elixir-format
msgid "Post Links"
@@ -1950,8 +1952,8 @@ msgstr "Artículo guardado"
#: lib/bds/desktop/menu_bar.ex:233
#: lib/bds/desktop/shell_live/misc_editor.ex:664
#: lib/bds/desktop/shell_live/misc_editor.ex:761
#: lib/bds/tui.ex:1938
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1955
#: lib/bds/ui/registry.ex:14
#: lib/bds/ui/sidebar.ex:271
#, elixir-autogen, elixir-format
@@ -2081,14 +2083,14 @@ msgstr "Listo para importar:"
#: lib/bds/desktop/menu_bar.ex:248
#: lib/bds/tui.ex:1016
#: lib/bds/tui.ex:2080
#: lib/bds/tui.ex:2082
#, elixir-autogen, elixir-format
msgid "Rebuild Database"
msgstr "Reconstruir base de datos"
#: lib/bds/desktop/menu_bar.ex:250
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:381
#: lib/bds/tui.ex:2084
#: lib/bds/tui.ex:2086
#, elixir-autogen, elixir-format
msgid "Rebuild Embedding Index"
msgstr "Reconstruir índice de embeddings"
@@ -2146,7 +2148,7 @@ msgid "Refresh Translation"
msgstr "Actualizar traducción"
#: lib/bds/desktop/menu_bar.ex:252
#: lib/bds/tui.ex:2087
#: lib/bds/tui.ex:2089
#, elixir-autogen, elixir-format
msgid "Regenerate Calendar"
msgstr "Regenerar calendario"
@@ -2157,7 +2159,7 @@ msgid "Regenerate Missing Thumbnails"
msgstr "Regenerar miniaturas faltantes"
#: lib/bds/desktop/menu_bar.ex:249
#: lib/bds/tui.ex:2081
#: lib/bds/tui.ex:2083
#, elixir-autogen, elixir-format
msgid "Reindex Text"
msgstr "Reindexar texto"
@@ -2342,10 +2344,11 @@ msgstr "Las capacidades de scripts se configuran en la capa de aplicación en la
#: lib/bds/desktop/shell_live/script_editor.ex:175
#: lib/bds/desktop/shell_live/script_editor.ex:191
#: lib/bds/desktop/shell_live/script_editor.ex:194
#: lib/bds/desktop/shell_live/script_editor.ex:216
#: lib/bds/desktop/shell_live/script_editor.ex:219
#: lib/bds/desktop/shell_live/script_editor.ex:234
#: lib/bds/tui.ex:1941
#: lib/bds/desktop/shell_live/script_editor.ex:212
#: lib/bds/desktop/shell_live/script_editor.ex:222
#: lib/bds/desktop/shell_live/script_editor.ex:225
#: lib/bds/desktop/shell_live/script_editor.ex:240
#: lib/bds/tui.ex:1943
#: lib/bds/ui/registry.ex:38
#: lib/bds/ui/sidebar.ex:63
#: lib/bds/ui/sidebar.ex:115
@@ -2452,7 +2455,7 @@ msgstr "Similitud semántica"
#: lib/bds/desktop/shell_live/settings_editor/project_settings.ex:60
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:11
#: lib/bds/tui.ex:1943
#: lib/bds/tui.ex:1945
#: lib/bds/ui/registry.ex:86
#: lib/bds/ui/registry.ex:101
#: lib/bds/ui/sidebar.ex:795
@@ -2478,7 +2481,7 @@ msgstr "Sitio"
#: lib/bds/desktop/shell_live/misc_editor.ex:412
#: lib/bds/tui.ex:318
#: lib/bds/tui.ex:320
#: lib/bds/tui.ex:1668
#: lib/bds/tui.ex:1670
#: lib/bds/ui/registry.ex:125
#, elixir-autogen, elixir-format
msgid "Site Validation"
@@ -2575,7 +2578,7 @@ msgid "System Prompt"
msgstr "Prompt del sistema"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:16
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#: lib/bds/ui/sidebar.ex:785
#, elixir-autogen, elixir-format
msgid "Tag Cloud"
@@ -2602,8 +2605,8 @@ msgstr "Nombre de la etiqueta"
#: lib/bds/desktop/shell_live/tags_editor.ex:217
#: lib/bds/desktop/shell_live/tags_editor.ex:248
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:11
#: lib/bds/tui.ex:1920
#: lib/bds/tui.ex:1942
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1944
#: lib/bds/ui/registry.ex:54
#: lib/bds/ui/registry.ex:103
#: lib/bds/ui/sidebar.ex:289
@@ -2613,8 +2616,8 @@ msgstr "Nombre de la etiqueta"
msgid "Tags"
msgstr "Etiquetas"
#: lib/bds/desktop/shell_live.ex:786
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#: lib/bds/desktop/shell_live.ex:819
#: lib/bds/desktop/shell_live/panel_renderer.ex:63
#: lib/bds/tui.ex:1220
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -2661,7 +2664,7 @@ msgstr "La sintaxis de la plantilla es válida"
#: lib/bds/desktop/shell_live/template_editor.ex:171
#: lib/bds/desktop/shell_live/template_editor.ex:176
#: lib/bds/desktop/shell_live/template_editor.ex:191
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1942
#: lib/bds/ui/registry.ex:46
#: lib/bds/ui/sidebar.ex:71
#: lib/bds/ui/sidebar.ex:122
@@ -2670,7 +2673,7 @@ msgstr "La sintaxis de la plantilla es válida"
msgid "Templates"
msgstr "Plantillas"
#: lib/bds/desktop/shell_live/panel_renderer.ex:194
#: lib/bds/desktop/shell_live/panel_renderer.ex:293
#, elixir-autogen, elixir-format
msgid "The shared lower panel is available for tasks, output, git details, and editor-specific diagnostics."
msgstr "El panel inferior compartido está disponible para tareas, salida, detalles de Git y diagnósticos específicos del editor."
@@ -2885,7 +2888,7 @@ msgid "Updated URLs"
msgstr "URLs actualizadas"
#: lib/bds/desktop/menu_bar.ex:259
#: lib/bds/tui.ex:2099
#: lib/bds/tui.ex:2101
#, elixir-autogen, elixir-format
msgid "Upload Site"
msgstr "Subir sitio"
@@ -2913,13 +2916,13 @@ msgid "Validate"
msgstr "Validar"
#: lib/bds/desktop/menu_bar.ex:258
#: lib/bds/tui.ex:2077
#: lib/bds/tui.ex:2079
#, elixir-autogen, elixir-format
msgid "Validate Site"
msgstr "Validar sitio"
#: lib/bds/desktop/menu_bar.ex:253
#: lib/bds/tui.ex:2090
#: lib/bds/tui.ex:2092
#, elixir-autogen, elixir-format
msgid "Validate Translations"
msgstr "Validar traducciones"
@@ -3301,12 +3304,12 @@ msgstr "Bienvenido al asistente de IA"
msgid "Comparing database and filesystem metadata"
msgstr "Comparando metadatos de la base de datos y del sistema de archivos"
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:717
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} imágenes añadidas a la publicación"
#: lib/bds/desktop/shell_live.ex:652
#: lib/bds/desktop/shell_live.ex:685
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} añadido"
@@ -3327,18 +3330,18 @@ msgstr "Guía del usuario para flujos editoriales, medios, plantillas, traducci
msgid "Image Import Concurrency"
msgstr "Importación simultánea de imágenes"
#: lib/bds/desktop/shell_live.ex:444
#: lib/bds/desktop/shell_live.ex:457
#: lib/bds/desktop/shell_live.ex:651
#: lib/bds/desktop/shell_live.ex:683
#: lib/bds/desktop/shell_live.ex:694
#: lib/bds/desktop/shell_live.ex:705
#: lib/bds/desktop/shell_live.ex:477
#: lib/bds/desktop/shell_live.ex:490
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:716
#: lib/bds/desktop/shell_live.ex:727
#: lib/bds/desktop/shell_live.ex:738
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Añadir imágenes a la galería"
#: lib/bds/desktop/shell_live.ex:706
#: lib/bds/desktop/shell_live.ex:739
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "No se pudo procesar %{path}: %{reason}"
@@ -3400,7 +3403,7 @@ msgid "Commit"
msgstr "Commit"
#: lib/bds/desktop/shell_live/sidebar_components.ex:555
#: lib/bds/tui.ex:1490
#: lib/bds/tui.ex:1492
#, elixir-autogen, elixir-format
msgid "Commit message"
msgstr "Mensaje de commit"
@@ -3536,12 +3539,12 @@ msgstr "renombrado"
msgid "untracked"
msgstr "sin seguimiento"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:845
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:855
#: lib/bds/desktop/shell_live.ex:888
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Abre un proyecto antes de importar un blogmark."
@@ -3582,7 +3585,7 @@ msgstr "Eliminar etiqueta"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Error al copiar el bookmarklet al portapapeles"
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live.ex:857
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "El proyecto al que apunta este blogmark no existe aquí."
@@ -3593,7 +3596,7 @@ msgid "Suggested tags"
msgstr "Etiquetas sugeridas"
#: lib/bds/desktop/menu_bar.ex:257
#: lib/bds/tui.ex:2078
#: lib/bds/tui.ex:2080
#, elixir-autogen, elixir-format
msgid "Force Render Site"
msgstr "Forzar la regeneración del sitio"
@@ -3690,12 +3693,12 @@ msgstr "OK"
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "El endpoint no devolvió ningún modelo. Aún puedes escribir el nombre de un modelo manualmente."
#: lib/bds/tui.ex:2036
#: lib/bds/tui.ex:2038
#, elixir-autogen, elixir-format
msgid "AI is unavailable in airplane mode without a local endpoint."
msgstr "La IA no está disponible en modo avión sin un punto de conexión local."
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:2165
#, elixir-autogen, elixir-format
msgid "Could not load this file."
msgstr "No se pudo cargar este archivo."
@@ -3710,12 +3713,12 @@ msgstr "La edición de este elemento aún no está disponible en la interfaz de
msgid "No suggestions returned."
msgstr "No se recibieron sugerencias."
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2162
#, elixir-autogen, elixir-format
msgid "Only images can be previewed."
msgstr "Solo se pueden previsualizar imágenes."
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1955
#, elixir-autogen, elixir-format
msgid "Post not found."
msgstr "Entrada no encontrada."
@@ -3725,18 +3728,18 @@ msgstr "Entrada no encontrada."
msgid "Press enter to preview %{name}."
msgstr "Pulsa Intro para previsualizar %{name}."
#: lib/bds/tui.ex:2006
#: lib/bds/tui.ex:2008
#, elixir-autogen, elixir-format
msgid "Published."
msgstr "Publicado."
#: lib/bds/tui.ex:2022
#: lib/bds/tui.ex:2024
#, elixir-autogen, elixir-format
msgid "Save before switching languages."
msgstr "Guarda antes de cambiar de idioma."
#: lib/bds/tui.ex:540
#: lib/bds/tui.ex:2007
#: lib/bds/tui.ex:2009
#, elixir-autogen, elixir-format
msgid "Saved."
msgstr "Guardado."
@@ -3761,18 +3764,18 @@ msgstr "Título (ctrl+t para editar)"
msgid "Title (editing — enter to confirm)"
msgstr "Título (edición — Intro para confirmar)"
#: lib/bds/tui.ex:1492
#: lib/bds/tui.ex:1494
#, elixir-autogen, elixir-format
msgid "Working…"
msgstr "Procesando…"
#: lib/bds/tui.ex:1514
#: lib/bds/tui.ex:1516
#, elixir-autogen, elixir-format
msgid "esc to close"
msgstr "esc para cerrar"
#: lib/bds/desktop/menu_bar.ex:83
#: lib/bds/desktop/shell_live.ex:1110
#: lib/bds/desktop/shell_live.ex:1176
#, elixir-autogen, elixir-format
msgid "Connect to Server"
msgstr "Conectar al servidor"
@@ -3793,7 +3796,7 @@ msgid "Disconnect from Server"
msgstr "Desconectar del servidor"
#: lib/bds/desktop/menu_bar.ex:72
#: lib/bds/desktop/shell_live.ex:1097
#: lib/bds/desktop/shell_live.ex:1163
#, elixir-autogen, elixir-format
msgid "Server address (user@host or user@host:port), public-key auth:"
msgstr "Dirección del servidor (user@host o user@host:port), autenticación de clave pública:"
@@ -3803,12 +3806,12 @@ msgstr "Dirección del servidor (user@host o user@host:port), autenticación de
msgid "Use the form user@host or user@host:port."
msgstr "Usa el formato user@host o user@host:port."
#: lib/bds/tui.ex:1457
#: lib/bds/tui.ex:1456
#, elixir-autogen, elixir-format
msgid "Preview (ctrl+e to edit)"
msgstr "Vista previa (ctrl+e para editar)"
#: lib/bds/tui.ex:1771
#: lib/bds/tui.ex:1773
#, elixir-autogen, elixir-format
msgid "ctrl+s save · ctrl+p publish · ctrl+e preview · ctrl+t title · ctrl+l language · ctrl+g AI · esc back"
msgstr "ctrl+s guardar · ctrl+p publicar · ctrl+e vista previa · ctrl+t título · ctrl+l idioma · ctrl+g IA · esc volver"
@@ -3818,7 +3821,7 @@ msgstr "ctrl+s guardar · ctrl+p publicar · ctrl+e vista previa · ctrl+t títu
msgid "All tasks finished."
msgstr "Todas las tareas han terminado."
#: lib/bds/tui.ex:1540
#: lib/bds/tui.ex:1542
#, elixir-autogen, elixir-format
msgid "Commands — esc to close"
msgstr "Comandos — esc para cerrar"
@@ -3828,27 +3831,27 @@ msgstr "Comandos — esc para cerrar"
msgid "Unknown command."
msgstr "Comando desconocido."
#: lib/bds/tui.ex:1530
#: lib/bds/tui.ex:1532
#, elixir-autogen, elixir-format
msgid "[report/apply in GUI]"
msgstr "[informe/aplicación en la GUI]"
#: lib/bds/tui.ex:1679
#: lib/bds/tui.ex:1681
#, elixir-autogen, elixir-format
msgid "%{diffs} differences · %{orphans} orphan files"
msgstr "%{diffs} diferencias · %{orphans} archivos huérfanos"
#: lib/bds/tui.ex:1711
#: lib/bds/tui.ex:1713
#, elixir-autogen, elixir-format
msgid "Expected %{expected} · Existing %{existing}"
msgstr "Esperados %{expected} · Existentes %{existing}"
#: lib/bds/tui.ex:1728
#: lib/bds/tui.ex:1730
#, elixir-autogen, elixir-format
msgid "Extra files (will be removed):"
msgstr "Archivos sobrantes (se eliminarán):"
#: lib/bds/tui.ex:1724
#: lib/bds/tui.ex:1726
#, elixir-autogen, elixir-format
msgid "Missing pages (will be rendered):"
msgstr "Páginas faltantes (se generarán):"
@@ -3863,27 +3866,27 @@ msgstr "Nada que aplicar."
msgid "Nothing to repair."
msgstr "Nada que reparar."
#: lib/bds/tui.ex:1702
#: lib/bds/tui.ex:1704
#, elixir-autogen, elixir-format
msgid "Orphan files (not in database):"
msgstr "Archivos huérfanos (no están en la base de datos):"
#: lib/bds/tui.ex:1718
#: lib/bds/tui.ex:1720
#, elixir-autogen, elixir-format
msgid "Sitemap changed."
msgstr "Sitemap modificado."
#: lib/bds/tui.ex:1732
#: lib/bds/tui.ex:1734
#, elixir-autogen, elixir-format
msgid "Updated posts (will be re-rendered):"
msgstr "Entradas actualizadas (se volverán a generar):"
#: lib/bds/tui.ex:1669
#: lib/bds/tui.ex:1671
#, elixir-autogen, elixir-format
msgid "enter apply changes · esc close"
msgstr "intro aplicar cambios · esc cerrar"
#: lib/bds/tui.ex:1664
#: lib/bds/tui.ex:1666
#, elixir-autogen, elixir-format
msgid "enter repair all from files · esc close"
msgstr "intro reparar todo desde archivos · esc cerrar"
@@ -3898,7 +3901,7 @@ msgstr "Blog importado"
msgid "Not a folder: %{path}"
msgstr "No es una carpeta: %{path}"
#: lib/bds/tui.ex:1606
#: lib/bds/tui.ex:1608
#, elixir-autogen, elixir-format
msgid "Projects — enter switch · o open existing · esc close"
msgstr "Proyectos — intro cambiar · o abrir existente · esc cerrar"
@@ -3908,12 +3911,12 @@ msgstr "Proyectos — intro cambiar · o abrir existente · esc cerrar"
msgid "Switched to %{name}."
msgstr "Cambiado a %{name}."
#: lib/bds/tui.ex:1634
#: lib/bds/tui.ex:1636
#, elixir-autogen, elixir-format
msgid "Matching folders"
msgstr "Carpetas coincidentes"
#: lib/bds/tui.ex:1572
#: lib/bds/tui.ex:1574
#, elixir-autogen, elixir-format
msgid "Open Existing Blog — type a folder path · tab complete · enter open · esc back"
msgstr "Abrir blog existente — escribe la ruta de una carpeta · tab completar · intro abrir · esc volver"
@@ -3933,7 +3936,7 @@ msgstr "Commit realizado."
msgid "Diff (pgup/pgdn scroll)"
msgstr "Diff (pgup/pgdn para desplazar)"
#: lib/bds/tui.ex:1799
#: lib/bds/tui.ex:1801
#, elixir-autogen, elixir-format
msgid "No changes."
msgstr "Sin cambios."
@@ -4044,7 +4047,7 @@ msgstr "Tema"
msgid "enter edit · ctrl+s save · esc close"
msgstr "intro editar · ctrl+s guardar · esc cerrar"
#: lib/bds/tui.ex:1750
#: lib/bds/tui.ex:1752
#, elixir-autogen, elixir-format
msgid "enter edit/toggle/cycle · ctrl+s save · esc close · ctrl+q quit"
msgstr "intro editar/alternar/ciclar · ctrl+s guardar · esc cerrar · ctrl+q salir"
@@ -4054,12 +4057,12 @@ msgstr "intro editar/alternar/ciclar · ctrl+s guardar · esc cerrar · ctrl+q s
msgid "not supported yet"
msgstr "aún no compatible"
#: lib/bds/tui.ex:1757
#: lib/bds/tui.ex:1759
#, elixir-autogen, elixir-format
msgid "c commit · u pull · s push · enter jump to file · pgup/pgdn scroll diff · 1-7 views · ctrl+q quit"
msgstr "c commit · u pull · s push · intro ir al archivo · pgup/pgdn desplazar el diff · 1-7 vistas · ctrl+q salir"
#: lib/bds/tui.ex:1764
#: lib/bds/tui.ex:1766
#, elixir-autogen, elixir-format
msgid "enter open · n new post · 1-7 views · p projects · / search · : commands (:? help) · r refresh · ctrl+q quit"
msgstr "intro abrir · n nueva entrada · 1-7 vistas · p proyectos · / buscar · : comandos (:? ayuda) · r actualizar · ctrl+q salir"
@@ -4191,12 +4194,12 @@ msgstr "El destino de la combinación debe ser una de las etiquetas marcadas"
msgid "default"
msgstr "predeterminado"
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#, elixir-autogen, elixir-format
msgid "esc close"
msgstr "esc cerrar"
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1924
#, elixir-autogen, elixir-format
msgid "n new · enter rename · c colour · t template · d delete · s sync · esc close"
msgstr "n nuevo · intro renombrar · c color · t plantilla · d eliminar · s sincronizar · esc cerrar"
@@ -4206,7 +4209,17 @@ msgstr "n nuevo · intro renombrar · c color · t plantilla · d eliminar · s
msgid "none"
msgstr "ninguno"
#: lib/bds/tui.ex:1927
#: lib/bds/tui.ex:1929
#, elixir-autogen, elixir-format
msgid "space mark · m merge into selected · esc close"
msgstr "espacio marcar · m combinar en la selección · esc cerrar"
#: lib/bds/desktop/shell_live/panel_renderer.ex:157
#, elixir-autogen, elixir-format
msgid "Pending"
msgstr "Pendiente"
#: lib/bds/desktop/shell_live/panel_renderer.ex:156
#, elixir-autogen, elixir-format
msgid "Running"
msgstr "En curso"
+115 -102
View File
@@ -86,7 +86,7 @@ msgstr "Paramètres IA"
#: lib/bds/tui.ex:1175
#: lib/bds/tui.ex:1178
#: lib/bds/tui.ex:1186
#: lib/bds/tui.ex:2035
#: lib/bds/tui.ex:2037
#, elixir-autogen, elixir-format
msgid "AI Suggestions"
msgstr "Suggestions IA"
@@ -343,7 +343,7 @@ msgstr "Auteur"
msgid "Auto"
msgstr "Automatique"
#: lib/bds/desktop/shell_live.ex:445
#: lib/bds/desktop/shell_live.ex:478
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -368,7 +368,7 @@ msgstr "Aides d’automatisation"
msgid "Available languages"
msgstr "Langues disponibles"
#: lib/bds/desktop/shell_live/panel_renderer.ex:124
#: lib/bds/desktop/shell_live/panel_renderer.ex:223
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:313
#, elixir-autogen, elixir-format
msgid "Backlinks"
@@ -441,6 +441,7 @@ msgstr "La copie du bookmarklet est reliée via l’environnement desktop et l
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#: lib/bds/desktop/shell_live/panel_renderer.ex:143
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Annuler"
@@ -494,7 +495,7 @@ msgstr "Valeurs par défaut des catégories, options de rendu et liaison des mod
msgid "Category name is required"
msgstr "Le nom de la catégorie est requis"
#: lib/bds/desktop/shell_live.ex:791
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -575,7 +576,7 @@ msgid "Collapse unchanged diff hunks"
msgstr "Réduire les blocs de diff inchangés"
#: lib/bds/desktop/shell_live/overlay_manager.ex:423
#: lib/bds/tui.ex:2131
#: lib/bds/tui.ex:2133
#, elixir-autogen, elixir-format
msgid "Command completed"
msgstr "Commande terminée"
@@ -593,7 +594,7 @@ msgstr "Confirmer"
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:375
#: lib/bds/desktop/shell_live/script_editor_html/script_editor.html.heex:34
#: lib/bds/desktop/shell_live/template_editor_html/template_editor.html.heex:32
#: lib/bds/tui.ex:1468
#: lib/bds/tui.ex:1467
#: lib/bds/ui/settings_form.ex:137
#: lib/bds/ui/sidebar.ex:801
#, elixir-autogen, elixir-format
@@ -606,6 +607,7 @@ msgid "Content Categories"
msgstr "Catégories de contenu"
#: lib/bds/desktop/menu_bar.ex:226
#: lib/bds/desktop/shell_live/panel_renderer.ex:183
#, elixir-autogen, elixir-format
msgid "Copy"
msgstr "Copier"
@@ -1040,7 +1042,7 @@ msgid "Filename"
msgstr "Nom de fichier"
#: lib/bds/desktop/menu_bar.ex:254
#: lib/bds/tui.ex:2095
#: lib/bds/tui.ex:2097
#, elixir-autogen, elixir-format
msgid "Fill Missing Translations"
msgstr "Compléter les traductions manquantes"
@@ -1051,7 +1053,7 @@ msgid "Find"
msgstr "Rechercher"
#: lib/bds/desktop/menu_bar.ex:255
#: lib/bds/tui.ex:2098
#: lib/bds/tui.ex:2100
#, elixir-autogen, elixir-format
msgid "Find Duplicate Posts"
msgstr "Trouver les doublons"
@@ -1078,14 +1080,14 @@ msgid "Gallery"
msgstr "Galerie"
#: lib/bds/desktop/menu_bar.ex:256
#: lib/bds/tui.ex:2079
#: lib/bds/tui.ex:2081
#, elixir-autogen, elixir-format
msgid "Generate Site"
msgstr "Générer le site"
#: lib/bds/desktop/shell_live.ex:792
#: lib/bds/desktop/shell_live.ex:825
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/tui.ex:1944
#: lib/bds/tui.ex:1946
#: lib/bds/ui/sidebar.ex:826
#, elixir-autogen, elixir-format
msgid "Git"
@@ -1098,8 +1100,8 @@ msgid "Git Diff"
msgstr "Diff Git"
#: lib/bds/desktop/shell_data.ex:228
#: lib/bds/desktop/shell_live.ex:788
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#: lib/bds/desktop/shell_live.ex:821
#: lib/bds/desktop/shell_live/panel_renderer.ex:270
#, elixir-autogen, elixir-format
msgid "Git Log"
msgstr "Journal Git"
@@ -1222,9 +1224,9 @@ msgstr "Définitions d’import"
msgid "Import failed: %{error}"
msgstr "Échec de l’import : %{error}"
#: lib/bds/desktop/shell_live.ex:608
#: lib/bds/desktop/shell_live.ex:904
#: lib/bds/desktop/shell_live.ex:910
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:970
#: lib/bds/desktop/shell_live.ex:976
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1325,7 +1327,7 @@ msgstr "Médias liés"
msgid "Linked Posts"
msgstr "Articles liés"
#: lib/bds/desktop/shell_live/panel_renderer.ex:142
#: lib/bds/desktop/shell_live/panel_renderer.ex:241
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:325
#, elixir-autogen, elixir-format
msgid "Links To"
@@ -1404,9 +1406,9 @@ msgstr "Nombre maximal d’articles par page"
#: lib/bds/desktop/shell_live/misc_editor.ex:762
#: lib/bds/desktop/shell_live/sidebar_components.ex:654
#: lib/bds/desktop/shell_live/sidebar_delete.ex:175
#: lib/bds/tui.ex:1939
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:1941
#: lib/bds/tui.ex:2162
#: lib/bds/tui.ex:2165
#: lib/bds/ui/registry.ex:30
#: lib/bds/ui/registry.ex:100
#: lib/bds/ui/sidebar.ex:578
@@ -1435,7 +1437,7 @@ msgid "Merge"
msgstr "Fusionner"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:78
#: lib/bds/tui.ex:1926
#: lib/bds/tui.ex:1928
#: lib/bds/ui/sidebar.ex:787
#, elixir-autogen, elixir-format
msgid "Merge Tags"
@@ -1453,8 +1455,8 @@ msgstr "Métadonnées"
#: lib/bds/tui.ex:285
#: lib/bds/tui.ex:291
#: lib/bds/tui.ex:302
#: lib/bds/tui.ex:1663
#: lib/bds/tui.ex:2076
#: lib/bds/tui.ex:1665
#: lib/bds/tui.ex:2078
#: lib/bds/ui/registry.ex:111
#, elixir-autogen, elixir-format
msgid "Metadata Diff"
@@ -1532,12 +1534,12 @@ msgstr "Nouveau modèle"
msgid "No Template"
msgstr "Aucun template"
#: lib/bds/desktop/shell_live/panel_renderer.ex:55
#: lib/bds/desktop/shell_live/panel_renderer.ex:64
#, elixir-autogen, elixir-format
msgid "No background tasks running"
msgstr "Aucune tâche d’arrière-plan en cours"
#: lib/bds/desktop/shell_live/panel_renderer.ex:179
#: lib/bds/desktop/shell_live/panel_renderer.ex:278
#, elixir-autogen, elixir-format
msgid "No commit subject"
msgstr "Pas de sujet de commit"
@@ -1547,7 +1549,7 @@ msgstr "Pas de sujet de commit"
msgid "No folder selected"
msgstr "Aucun dossier sélectionné"
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#: lib/bds/desktop/shell_live/panel_renderer.ex:271
#, elixir-autogen, elixir-format
msgid "No git history yet"
msgstr "Pas encore d'historique Git"
@@ -1607,7 +1609,7 @@ msgstr "Aucun fichier orphelin sélectionné"
msgid "No pages yet"
msgstr "Aucune page pour le moment"
#: lib/bds/desktop/shell_live/panel_renderer.ex:119
#: lib/bds/desktop/shell_live/panel_renderer.ex:218
#, elixir-autogen, elixir-format
msgid "No post links yet"
msgstr "Pas encore de liens vers des articles"
@@ -1632,7 +1634,7 @@ msgstr "Aucune action de réparation disponible"
msgid "No settings match the current search"
msgstr "Aucun paramètre ne correspond à la recherche actuelle"
#: lib/bds/desktop/shell_live/panel_renderer.ex:84
#: lib/bds/desktop/shell_live/panel_renderer.ex:173
#, elixir-autogen, elixir-format
msgid "No shell output yet"
msgstr "Aucune sortie du shell pour l’instant"
@@ -1801,7 +1803,7 @@ msgid "Open Settings"
msgstr "Ouvrir les Réglages"
#: lib/bds/desktop/menu_bar.ex:217
#: lib/bds/tui.ex:2100
#: lib/bds/tui.ex:2102
#, elixir-autogen, elixir-format
msgid "Open in Browser"
msgstr "Ouvrir dans le navigateur"
@@ -1832,8 +1834,8 @@ msgstr "Autre"
msgid "Other (%{count})"
msgstr "Autres (%{count})"
#: lib/bds/desktop/shell_live.ex:787
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#: lib/bds/desktop/shell_live.ex:820
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#, elixir-autogen, elixir-format
msgid "Output"
msgstr "Sortie"
@@ -1915,7 +1917,7 @@ msgid "Post"
msgstr "Article"
#: lib/bds/desktop/shell_data.ex:231
#: lib/bds/desktop/shell_live/panel_renderer.ex:118
#: lib/bds/desktop/shell_live/panel_renderer.ex:217
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:310
#, elixir-autogen, elixir-format
msgid "Post Links"
@@ -1950,8 +1952,8 @@ msgstr "Article enregistré"
#: lib/bds/desktop/menu_bar.ex:233
#: lib/bds/desktop/shell_live/misc_editor.ex:664
#: lib/bds/desktop/shell_live/misc_editor.ex:761
#: lib/bds/tui.ex:1938
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1955
#: lib/bds/ui/registry.ex:14
#: lib/bds/ui/sidebar.ex:271
#, elixir-autogen, elixir-format
@@ -2081,14 +2083,14 @@ msgstr "Prêt à importer :"
#: lib/bds/desktop/menu_bar.ex:248
#: lib/bds/tui.ex:1016
#: lib/bds/tui.ex:2080
#: lib/bds/tui.ex:2082
#, elixir-autogen, elixir-format
msgid "Rebuild Database"
msgstr "Reconstruire la base de données"
#: lib/bds/desktop/menu_bar.ex:250
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:381
#: lib/bds/tui.ex:2084
#: lib/bds/tui.ex:2086
#, elixir-autogen, elixir-format
msgid "Rebuild Embedding Index"
msgstr "Reconstruire l’index d’embeddings"
@@ -2146,7 +2148,7 @@ msgid "Refresh Translation"
msgstr "Actualiser la traduction"
#: lib/bds/desktop/menu_bar.ex:252
#: lib/bds/tui.ex:2087
#: lib/bds/tui.ex:2089
#, elixir-autogen, elixir-format
msgid "Regenerate Calendar"
msgstr "Régénérer le calendrier"
@@ -2157,7 +2159,7 @@ msgid "Regenerate Missing Thumbnails"
msgstr "Régénérer les vignettes manquantes"
#: lib/bds/desktop/menu_bar.ex:249
#: lib/bds/tui.ex:2081
#: lib/bds/tui.ex:2083
#, elixir-autogen, elixir-format
msgid "Reindex Text"
msgstr "Réindexer le texte"
@@ -2342,10 +2344,11 @@ msgstr "Les capacités de script sont configurées au niveau de l’application
#: lib/bds/desktop/shell_live/script_editor.ex:175
#: lib/bds/desktop/shell_live/script_editor.ex:191
#: lib/bds/desktop/shell_live/script_editor.ex:194
#: lib/bds/desktop/shell_live/script_editor.ex:216
#: lib/bds/desktop/shell_live/script_editor.ex:219
#: lib/bds/desktop/shell_live/script_editor.ex:234
#: lib/bds/tui.ex:1941
#: lib/bds/desktop/shell_live/script_editor.ex:212
#: lib/bds/desktop/shell_live/script_editor.ex:222
#: lib/bds/desktop/shell_live/script_editor.ex:225
#: lib/bds/desktop/shell_live/script_editor.ex:240
#: lib/bds/tui.ex:1943
#: lib/bds/ui/registry.ex:38
#: lib/bds/ui/sidebar.ex:63
#: lib/bds/ui/sidebar.ex:115
@@ -2452,7 +2455,7 @@ msgstr "Similarité sémantique"
#: lib/bds/desktop/shell_live/settings_editor/project_settings.ex:60
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:11
#: lib/bds/tui.ex:1943
#: lib/bds/tui.ex:1945
#: lib/bds/ui/registry.ex:86
#: lib/bds/ui/registry.ex:101
#: lib/bds/ui/sidebar.ex:795
@@ -2478,7 +2481,7 @@ msgstr "Site"
#: lib/bds/desktop/shell_live/misc_editor.ex:412
#: lib/bds/tui.ex:318
#: lib/bds/tui.ex:320
#: lib/bds/tui.ex:1668
#: lib/bds/tui.ex:1670
#: lib/bds/ui/registry.ex:125
#, elixir-autogen, elixir-format
msgid "Site Validation"
@@ -2575,7 +2578,7 @@ msgid "System Prompt"
msgstr "Prompt système"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:16
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#: lib/bds/ui/sidebar.ex:785
#, elixir-autogen, elixir-format
msgid "Tag Cloud"
@@ -2602,8 +2605,8 @@ msgstr "Nom du mot-clé"
#: lib/bds/desktop/shell_live/tags_editor.ex:217
#: lib/bds/desktop/shell_live/tags_editor.ex:248
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:11
#: lib/bds/tui.ex:1920
#: lib/bds/tui.ex:1942
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1944
#: lib/bds/ui/registry.ex:54
#: lib/bds/ui/registry.ex:103
#: lib/bds/ui/sidebar.ex:289
@@ -2613,8 +2616,8 @@ msgstr "Nom du mot-clé"
msgid "Tags"
msgstr "Tags"
#: lib/bds/desktop/shell_live.ex:786
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#: lib/bds/desktop/shell_live.ex:819
#: lib/bds/desktop/shell_live/panel_renderer.ex:63
#: lib/bds/tui.ex:1220
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -2661,7 +2664,7 @@ msgstr "La syntaxe du template est valide"
#: lib/bds/desktop/shell_live/template_editor.ex:171
#: lib/bds/desktop/shell_live/template_editor.ex:176
#: lib/bds/desktop/shell_live/template_editor.ex:191
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1942
#: lib/bds/ui/registry.ex:46
#: lib/bds/ui/sidebar.ex:71
#: lib/bds/ui/sidebar.ex:122
@@ -2670,7 +2673,7 @@ msgstr "La syntaxe du template est valide"
msgid "Templates"
msgstr "Modèles"
#: lib/bds/desktop/shell_live/panel_renderer.ex:194
#: lib/bds/desktop/shell_live/panel_renderer.ex:293
#, elixir-autogen, elixir-format
msgid "The shared lower panel is available for tasks, output, git details, and editor-specific diagnostics."
msgstr "Le panneau inférieur partagé est disponible pour les tâches, la sortie, les détails Git et les diagnostics spécifiques à l’éditeur."
@@ -2885,7 +2888,7 @@ msgid "Updated URLs"
msgstr "URLs mises à jour"
#: lib/bds/desktop/menu_bar.ex:259
#: lib/bds/tui.ex:2099
#: lib/bds/tui.ex:2101
#, elixir-autogen, elixir-format
msgid "Upload Site"
msgstr "Téléverser le site"
@@ -2913,13 +2916,13 @@ msgid "Validate"
msgstr "Valider"
#: lib/bds/desktop/menu_bar.ex:258
#: lib/bds/tui.ex:2077
#: lib/bds/tui.ex:2079
#, elixir-autogen, elixir-format
msgid "Validate Site"
msgstr "Valider le site"
#: lib/bds/desktop/menu_bar.ex:253
#: lib/bds/tui.ex:2090
#: lib/bds/tui.ex:2092
#, elixir-autogen, elixir-format
msgid "Validate Translations"
msgstr "Valider les traductions"
@@ -3301,12 +3304,12 @@ msgstr "Bienvenue dans l’assistant IA"
msgid "Comparing database and filesystem metadata"
msgstr "Comparaison des métadonnées entre la base et le système de fichiers"
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:717
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} images ajoutées à l'article"
#: lib/bds/desktop/shell_live.ex:652
#: lib/bds/desktop/shell_live.ex:685
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} ajouté"
@@ -3327,18 +3330,18 @@ msgstr "Guide utilisateur pour les flux éditoriaux, médias, modèles, traducti
msgid "Image Import Concurrency"
msgstr "Importation simultanée d'images"
#: lib/bds/desktop/shell_live.ex:444
#: lib/bds/desktop/shell_live.ex:457
#: lib/bds/desktop/shell_live.ex:651
#: lib/bds/desktop/shell_live.ex:683
#: lib/bds/desktop/shell_live.ex:694
#: lib/bds/desktop/shell_live.ex:705
#: lib/bds/desktop/shell_live.ex:477
#: lib/bds/desktop/shell_live.ex:490
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:716
#: lib/bds/desktop/shell_live.ex:727
#: lib/bds/desktop/shell_live.ex:738
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Ajouter des images à la galerie"
#: lib/bds/desktop/shell_live.ex:706
#: lib/bds/desktop/shell_live.ex:739
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "Impossible de traiter %{path} : %{reason}"
@@ -3400,7 +3403,7 @@ msgid "Commit"
msgstr "Commit"
#: lib/bds/desktop/shell_live/sidebar_components.ex:555
#: lib/bds/tui.ex:1490
#: lib/bds/tui.ex:1492
#, elixir-autogen, elixir-format
msgid "Commit message"
msgstr "Message de commit"
@@ -3536,12 +3539,12 @@ msgstr "renommé"
msgid "untracked"
msgstr "non suivi"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:845
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:855
#: lib/bds/desktop/shell_live.ex:888
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Ouvrez un projet avant d’importer un blogmark."
@@ -3582,7 +3585,7 @@ msgstr "Supprimer le tag"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Échec de la copie du bookmarklet dans le presse-papiers"
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live.ex:857
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "Le projet ciblé par ce blogmark n'existe pas ici."
@@ -3593,7 +3596,7 @@ msgid "Suggested tags"
msgstr "Tags suggérés"
#: lib/bds/desktop/menu_bar.ex:257
#: lib/bds/tui.ex:2078
#: lib/bds/tui.ex:2080
#, elixir-autogen, elixir-format
msgid "Force Render Site"
msgstr "Forcer la régénération du site"
@@ -3690,12 +3693,12 @@ msgstr "OK"
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "Le point de terminaison n'a renvoyé aucun modèle. Vous pouvez toujours saisir un nom de modèle manuellement."
#: lib/bds/tui.ex:2036
#: lib/bds/tui.ex:2038
#, elixir-autogen, elixir-format
msgid "AI is unavailable in airplane mode without a local endpoint."
msgstr "L'IA n'est pas disponible en mode avion sans point de terminaison local."
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:2165
#, elixir-autogen, elixir-format
msgid "Could not load this file."
msgstr "Impossible de charger ce fichier."
@@ -3710,12 +3713,12 @@ msgstr "La modification de cet élément n'est pas encore disponible dans l'inte
msgid "No suggestions returned."
msgstr "Aucune suggestion reçue."
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2162
#, elixir-autogen, elixir-format
msgid "Only images can be previewed."
msgstr "Seules les images peuvent être prévisualisées."
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1955
#, elixir-autogen, elixir-format
msgid "Post not found."
msgstr "Article introuvable."
@@ -3725,18 +3728,18 @@ msgstr "Article introuvable."
msgid "Press enter to preview %{name}."
msgstr "Appuyez sur Entrée pour prévisualiser %{name}."
#: lib/bds/tui.ex:2006
#: lib/bds/tui.ex:2008
#, elixir-autogen, elixir-format
msgid "Published."
msgstr "Publié."
#: lib/bds/tui.ex:2022
#: lib/bds/tui.ex:2024
#, elixir-autogen, elixir-format
msgid "Save before switching languages."
msgstr "Enregistrez avant de changer de langue."
#: lib/bds/tui.ex:540
#: lib/bds/tui.ex:2007
#: lib/bds/tui.ex:2009
#, elixir-autogen, elixir-format
msgid "Saved."
msgstr "Enregistré."
@@ -3761,18 +3764,18 @@ msgstr "Titre (ctrl+t pour modifier)"
msgid "Title (editing — enter to confirm)"
msgstr "Titre (édition — Entrée pour confirmer)"
#: lib/bds/tui.ex:1492
#: lib/bds/tui.ex:1494
#, elixir-autogen, elixir-format
msgid "Working…"
msgstr "Traitement en cours…"
#: lib/bds/tui.ex:1514
#: lib/bds/tui.ex:1516
#, elixir-autogen, elixir-format
msgid "esc to close"
msgstr "échap pour fermer"
#: lib/bds/desktop/menu_bar.ex:83
#: lib/bds/desktop/shell_live.ex:1110
#: lib/bds/desktop/shell_live.ex:1176
#, elixir-autogen, elixir-format
msgid "Connect to Server"
msgstr "Se connecter au serveur"
@@ -3793,7 +3796,7 @@ msgid "Disconnect from Server"
msgstr "Se déconnecter du serveur"
#: lib/bds/desktop/menu_bar.ex:72
#: lib/bds/desktop/shell_live.ex:1097
#: lib/bds/desktop/shell_live.ex:1163
#, elixir-autogen, elixir-format
msgid "Server address (user@host or user@host:port), public-key auth:"
msgstr "Adresse du serveur (user@host ou user@host:port), authentification par clé publique :"
@@ -3803,12 +3806,12 @@ msgstr "Adresse du serveur (user@host ou user@host:port), authentification par c
msgid "Use the form user@host or user@host:port."
msgstr "Utilisez le format user@host ou user@host:port."
#: lib/bds/tui.ex:1457
#: lib/bds/tui.ex:1456
#, elixir-autogen, elixir-format
msgid "Preview (ctrl+e to edit)"
msgstr "Aperçu (ctrl+e pour modifier)"
#: lib/bds/tui.ex:1771
#: lib/bds/tui.ex:1773
#, elixir-autogen, elixir-format
msgid "ctrl+s save · ctrl+p publish · ctrl+e preview · ctrl+t title · ctrl+l language · ctrl+g AI · esc back"
msgstr "ctrl+s enregistrer · ctrl+p publier · ctrl+e aperçu · ctrl+t titre · ctrl+l langue · ctrl+g IA · échap retour"
@@ -3818,7 +3821,7 @@ msgstr "ctrl+s enregistrer · ctrl+p publier · ctrl+e aperçu · ctrl+t titre
msgid "All tasks finished."
msgstr "Toutes les tâches sont terminées."
#: lib/bds/tui.ex:1540
#: lib/bds/tui.ex:1542
#, elixir-autogen, elixir-format
msgid "Commands — esc to close"
msgstr "Commandes — échap pour fermer"
@@ -3828,27 +3831,27 @@ msgstr "Commandes — échap pour fermer"
msgid "Unknown command."
msgstr "Commande inconnue."
#: lib/bds/tui.ex:1530
#: lib/bds/tui.ex:1532
#, elixir-autogen, elixir-format
msgid "[report/apply in GUI]"
msgstr "[rapport/application dans la GUI]"
#: lib/bds/tui.ex:1679
#: lib/bds/tui.ex:1681
#, elixir-autogen, elixir-format
msgid "%{diffs} differences · %{orphans} orphan files"
msgstr "%{diffs} différences · %{orphans} fichiers orphelins"
#: lib/bds/tui.ex:1711
#: lib/bds/tui.ex:1713
#, elixir-autogen, elixir-format
msgid "Expected %{expected} · Existing %{existing}"
msgstr "Attendu %{expected} · Existant %{existing}"
#: lib/bds/tui.ex:1728
#: lib/bds/tui.ex:1730
#, elixir-autogen, elixir-format
msgid "Extra files (will be removed):"
msgstr "Fichiers en trop (seront supprimés) :"
#: lib/bds/tui.ex:1724
#: lib/bds/tui.ex:1726
#, elixir-autogen, elixir-format
msgid "Missing pages (will be rendered):"
msgstr "Pages manquantes (seront rendues) :"
@@ -3863,27 +3866,27 @@ msgstr "Rien à appliquer."
msgid "Nothing to repair."
msgstr "Rien à réparer."
#: lib/bds/tui.ex:1702
#: lib/bds/tui.ex:1704
#, elixir-autogen, elixir-format
msgid "Orphan files (not in database):"
msgstr "Fichiers orphelins (absents de la base de données) :"
#: lib/bds/tui.ex:1718
#: lib/bds/tui.ex:1720
#, elixir-autogen, elixir-format
msgid "Sitemap changed."
msgstr "Sitemap modifié."
#: lib/bds/tui.ex:1732
#: lib/bds/tui.ex:1734
#, elixir-autogen, elixir-format
msgid "Updated posts (will be re-rendered):"
msgstr "Articles mis à jour (seront rendus à nouveau) :"
#: lib/bds/tui.ex:1669
#: lib/bds/tui.ex:1671
#, elixir-autogen, elixir-format
msgid "enter apply changes · esc close"
msgstr "entrée appliquer les modifications · échap fermer"
#: lib/bds/tui.ex:1664
#: lib/bds/tui.ex:1666
#, elixir-autogen, elixir-format
msgid "enter repair all from files · esc close"
msgstr "entrée tout réparer depuis les fichiers · échap fermer"
@@ -3898,7 +3901,7 @@ msgstr "Blog importé"
msgid "Not a folder: %{path}"
msgstr "Pas un dossier : %{path}"
#: lib/bds/tui.ex:1606
#: lib/bds/tui.ex:1608
#, elixir-autogen, elixir-format
msgid "Projects — enter switch · o open existing · esc close"
msgstr "Projets — entrée changer · o ouvrir existant · échap fermer"
@@ -3908,12 +3911,12 @@ msgstr "Projets — entrée changer · o ouvrir existant · échap fermer"
msgid "Switched to %{name}."
msgstr "Passage à %{name}."
#: lib/bds/tui.ex:1634
#: lib/bds/tui.ex:1636
#, elixir-autogen, elixir-format
msgid "Matching folders"
msgstr "Dossiers correspondants"
#: lib/bds/tui.ex:1572
#: lib/bds/tui.ex:1574
#, elixir-autogen, elixir-format
msgid "Open Existing Blog — type a folder path · tab complete · enter open · esc back"
msgstr "Ouvrir un blog existant — saisir le chemin d'un dossier · tab compléter · entrée ouvrir · échap retour"
@@ -3933,7 +3936,7 @@ msgstr "Commit effectué."
msgid "Diff (pgup/pgdn scroll)"
msgstr "Diff (pgup/pgdn pour défiler)"
#: lib/bds/tui.ex:1799
#: lib/bds/tui.ex:1801
#, elixir-autogen, elixir-format
msgid "No changes."
msgstr "Aucune modification."
@@ -4044,7 +4047,7 @@ msgstr "Thème"
msgid "enter edit · ctrl+s save · esc close"
msgstr "entrée modifier · ctrl+s enregistrer · échap fermer"
#: lib/bds/tui.ex:1750
#: lib/bds/tui.ex:1752
#, elixir-autogen, elixir-format
msgid "enter edit/toggle/cycle · ctrl+s save · esc close · ctrl+q quit"
msgstr "entrée modifier/basculer/parcourir · ctrl+s enregistrer · échap fermer · ctrl+q quitter"
@@ -4054,12 +4057,12 @@ msgstr "entrée modifier/basculer/parcourir · ctrl+s enregistrer · échap ferm
msgid "not supported yet"
msgstr "pas encore pris en charge"
#: lib/bds/tui.ex:1757
#: lib/bds/tui.ex:1759
#, elixir-autogen, elixir-format
msgid "c commit · u pull · s push · enter jump to file · pgup/pgdn scroll diff · 1-7 views · ctrl+q quit"
msgstr "c commit · u pull · s push · entrée aller au fichier · pgup/pgdn défiler le diff · 1-7 vues · ctrl+q quitter"
#: lib/bds/tui.ex:1764
#: lib/bds/tui.ex:1766
#, elixir-autogen, elixir-format
msgid "enter open · n new post · 1-7 views · p projects · / search · : commands (:? help) · r refresh · ctrl+q quit"
msgstr "entrée ouvrir · n nouvel article · 1-7 vues · p projets · / rechercher · : commandes (:? aide) · r actualiser · ctrl+q quitter"
@@ -4191,12 +4194,12 @@ msgstr "La cible de la fusion doit être l'un des mots-clés marqués"
msgid "default"
msgstr "par défaut"
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#, elixir-autogen, elixir-format
msgid "esc close"
msgstr "échap fermer"
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1924
#, elixir-autogen, elixir-format
msgid "n new · enter rename · c colour · t template · d delete · s sync · esc close"
msgstr "n nouveau · entrée renommer · c couleur · t modèle · d supprimer · s synchroniser · échap fermer"
@@ -4206,7 +4209,17 @@ msgstr "n nouveau · entrée renommer · c couleur · t modèle · d supprimer
msgid "none"
msgstr "aucune"
#: lib/bds/tui.ex:1927
#: lib/bds/tui.ex:1929
#, elixir-autogen, elixir-format
msgid "space mark · m merge into selected · esc close"
msgstr "espace marquer · m fusionner dans la sélection · échap fermer"
#: lib/bds/desktop/shell_live/panel_renderer.ex:157
#, elixir-autogen, elixir-format
msgid "Pending"
msgstr "En attente"
#: lib/bds/desktop/shell_live/panel_renderer.ex:156
#, elixir-autogen, elixir-format
msgid "Running"
msgstr "En cours"
+115 -102
View File
@@ -86,7 +86,7 @@ msgstr "Impostazioni IA"
#: lib/bds/tui.ex:1175
#: lib/bds/tui.ex:1178
#: lib/bds/tui.ex:1186
#: lib/bds/tui.ex:2035
#: lib/bds/tui.ex:2037
#, elixir-autogen, elixir-format
msgid "AI Suggestions"
msgstr "Suggerimenti IA"
@@ -343,7 +343,7 @@ msgstr "Autore"
msgid "Auto"
msgstr "Automatico"
#: lib/bds/desktop/shell_live.ex:445
#: lib/bds/desktop/shell_live.ex:478
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -368,7 +368,7 @@ msgstr "Strumenti di automazione"
msgid "Available languages"
msgstr "Lingue disponibili"
#: lib/bds/desktop/shell_live/panel_renderer.ex:124
#: lib/bds/desktop/shell_live/panel_renderer.ex:223
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:313
#, elixir-autogen, elixir-format
msgid "Backlinks"
@@ -441,6 +441,7 @@ msgstr "La copia del bookmarklet è collegata tramite il runtime desktop e l’U
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#: lib/bds/desktop/shell_live/panel_renderer.ex:143
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr "Annulla"
@@ -494,7 +495,7 @@ msgstr "Valori predefiniti delle categorie, opzioni di rendering e collegamento
msgid "Category name is required"
msgstr "Il nome della categoria è obbligatorio"
#: lib/bds/desktop/shell_live.ex:791
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -575,7 +576,7 @@ msgid "Collapse unchanged diff hunks"
msgstr "Comprimi i blocchi diff invariati"
#: lib/bds/desktop/shell_live/overlay_manager.ex:423
#: lib/bds/tui.ex:2131
#: lib/bds/tui.ex:2133
#, elixir-autogen, elixir-format
msgid "Command completed"
msgstr "Comando completato"
@@ -593,7 +594,7 @@ msgstr "Conferma"
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:375
#: lib/bds/desktop/shell_live/script_editor_html/script_editor.html.heex:34
#: lib/bds/desktop/shell_live/template_editor_html/template_editor.html.heex:32
#: lib/bds/tui.ex:1468
#: lib/bds/tui.ex:1467
#: lib/bds/ui/settings_form.ex:137
#: lib/bds/ui/sidebar.ex:801
#, elixir-autogen, elixir-format
@@ -606,6 +607,7 @@ msgid "Content Categories"
msgstr "Categorie di contenuto"
#: lib/bds/desktop/menu_bar.ex:226
#: lib/bds/desktop/shell_live/panel_renderer.ex:183
#, elixir-autogen, elixir-format
msgid "Copy"
msgstr "Copia"
@@ -1040,7 +1042,7 @@ msgid "Filename"
msgstr "Nome file"
#: lib/bds/desktop/menu_bar.ex:254
#: lib/bds/tui.ex:2095
#: lib/bds/tui.ex:2097
#, elixir-autogen, elixir-format
msgid "Fill Missing Translations"
msgstr "Completa traduzioni mancanti"
@@ -1051,7 +1053,7 @@ msgid "Find"
msgstr "Trova"
#: lib/bds/desktop/menu_bar.ex:255
#: lib/bds/tui.ex:2098
#: lib/bds/tui.ex:2100
#, elixir-autogen, elixir-format
msgid "Find Duplicate Posts"
msgstr "Trova post duplicati"
@@ -1078,14 +1080,14 @@ msgid "Gallery"
msgstr "Galleria"
#: lib/bds/desktop/menu_bar.ex:256
#: lib/bds/tui.ex:2079
#: lib/bds/tui.ex:2081
#, elixir-autogen, elixir-format
msgid "Generate Site"
msgstr "Genera sito"
#: lib/bds/desktop/shell_live.ex:792
#: lib/bds/desktop/shell_live.ex:825
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/tui.ex:1944
#: lib/bds/tui.ex:1946
#: lib/bds/ui/sidebar.ex:826
#, elixir-autogen, elixir-format
msgid "Git"
@@ -1098,8 +1100,8 @@ msgid "Git Diff"
msgstr "Diff Git"
#: lib/bds/desktop/shell_data.ex:228
#: lib/bds/desktop/shell_live.ex:788
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#: lib/bds/desktop/shell_live.ex:821
#: lib/bds/desktop/shell_live/panel_renderer.ex:270
#, elixir-autogen, elixir-format
msgid "Git Log"
msgstr "Log Git"
@@ -1222,9 +1224,9 @@ msgstr "Definizioni di importazione"
msgid "Import failed: %{error}"
msgstr "Importazione non riuscita: %{error}"
#: lib/bds/desktop/shell_live.ex:608
#: lib/bds/desktop/shell_live.ex:904
#: lib/bds/desktop/shell_live.ex:910
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:970
#: lib/bds/desktop/shell_live.ex:976
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1325,7 +1327,7 @@ msgstr "Media collegati"
msgid "Linked Posts"
msgstr "Post collegati"
#: lib/bds/desktop/shell_live/panel_renderer.ex:142
#: lib/bds/desktop/shell_live/panel_renderer.ex:241
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:325
#, elixir-autogen, elixir-format
msgid "Links To"
@@ -1404,9 +1406,9 @@ msgstr "Numero massimo di post per pagina"
#: lib/bds/desktop/shell_live/misc_editor.ex:762
#: lib/bds/desktop/shell_live/sidebar_components.ex:654
#: lib/bds/desktop/shell_live/sidebar_delete.ex:175
#: lib/bds/tui.ex:1939
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:1941
#: lib/bds/tui.ex:2162
#: lib/bds/tui.ex:2165
#: lib/bds/ui/registry.ex:30
#: lib/bds/ui/registry.ex:100
#: lib/bds/ui/sidebar.ex:578
@@ -1435,7 +1437,7 @@ msgid "Merge"
msgstr "Unisci"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:78
#: lib/bds/tui.ex:1926
#: lib/bds/tui.ex:1928
#: lib/bds/ui/sidebar.ex:787
#, elixir-autogen, elixir-format
msgid "Merge Tags"
@@ -1453,8 +1455,8 @@ msgstr "Metadati"
#: lib/bds/tui.ex:285
#: lib/bds/tui.ex:291
#: lib/bds/tui.ex:302
#: lib/bds/tui.ex:1663
#: lib/bds/tui.ex:2076
#: lib/bds/tui.ex:1665
#: lib/bds/tui.ex:2078
#: lib/bds/ui/registry.ex:111
#, elixir-autogen, elixir-format
msgid "Metadata Diff"
@@ -1532,12 +1534,12 @@ msgstr "Nuovo modello"
msgid "No Template"
msgstr "Nessun template"
#: lib/bds/desktop/shell_live/panel_renderer.ex:55
#: lib/bds/desktop/shell_live/panel_renderer.ex:64
#, elixir-autogen, elixir-format
msgid "No background tasks running"
msgstr "Nessuna attività in background in esecuzione"
#: lib/bds/desktop/shell_live/panel_renderer.ex:179
#: lib/bds/desktop/shell_live/panel_renderer.ex:278
#, elixir-autogen, elixir-format
msgid "No commit subject"
msgstr "Nessun oggetto del commit"
@@ -1547,7 +1549,7 @@ msgstr "Nessun oggetto del commit"
msgid "No folder selected"
msgstr "Nessuna cartella selezionata"
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#: lib/bds/desktop/shell_live/panel_renderer.ex:271
#, elixir-autogen, elixir-format
msgid "No git history yet"
msgstr "Nessuna cronologia Git"
@@ -1607,7 +1609,7 @@ msgstr "Nessun file orfano selezionato"
msgid "No pages yet"
msgstr "Nessuna pagina"
#: lib/bds/desktop/shell_live/panel_renderer.ex:119
#: lib/bds/desktop/shell_live/panel_renderer.ex:218
#, elixir-autogen, elixir-format
msgid "No post links yet"
msgstr "Nessun collegamento ad articoli"
@@ -1632,7 +1634,7 @@ msgstr "Nessuna azione di riparazione disponibile"
msgid "No settings match the current search"
msgstr "Nessuna impostazione corrisponde alla ricerca corrente"
#: lib/bds/desktop/shell_live/panel_renderer.ex:84
#: lib/bds/desktop/shell_live/panel_renderer.ex:173
#, elixir-autogen, elixir-format
msgid "No shell output yet"
msgstr "Nessun output della shell per ora"
@@ -1801,7 +1803,7 @@ msgid "Open Settings"
msgstr "Apri Impostazioni"
#: lib/bds/desktop/menu_bar.ex:217
#: lib/bds/tui.ex:2100
#: lib/bds/tui.ex:2102
#, elixir-autogen, elixir-format
msgid "Open in Browser"
msgstr "Apri nel browser"
@@ -1832,8 +1834,8 @@ msgstr "Altro"
msgid "Other (%{count})"
msgstr "Altro (%{count})"
#: lib/bds/desktop/shell_live.ex:787
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#: lib/bds/desktop/shell_live.ex:820
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#, elixir-autogen, elixir-format
msgid "Output"
msgstr "Output"
@@ -1915,7 +1917,7 @@ msgid "Post"
msgstr "Post"
#: lib/bds/desktop/shell_data.ex:231
#: lib/bds/desktop/shell_live/panel_renderer.ex:118
#: lib/bds/desktop/shell_live/panel_renderer.ex:217
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:310
#, elixir-autogen, elixir-format
msgid "Post Links"
@@ -1950,8 +1952,8 @@ msgstr "Articolo salvato"
#: lib/bds/desktop/menu_bar.ex:233
#: lib/bds/desktop/shell_live/misc_editor.ex:664
#: lib/bds/desktop/shell_live/misc_editor.ex:761
#: lib/bds/tui.ex:1938
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1955
#: lib/bds/ui/registry.ex:14
#: lib/bds/ui/sidebar.ex:271
#, elixir-autogen, elixir-format
@@ -2081,14 +2083,14 @@ msgstr "Pronto per importare:"
#: lib/bds/desktop/menu_bar.ex:248
#: lib/bds/tui.ex:1016
#: lib/bds/tui.ex:2080
#: lib/bds/tui.ex:2082
#, elixir-autogen, elixir-format
msgid "Rebuild Database"
msgstr "Ricostruisci database"
#: lib/bds/desktop/menu_bar.ex:250
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:381
#: lib/bds/tui.ex:2084
#: lib/bds/tui.ex:2086
#, elixir-autogen, elixir-format
msgid "Rebuild Embedding Index"
msgstr "Ricostruisci indice embeddings"
@@ -2146,7 +2148,7 @@ msgid "Refresh Translation"
msgstr "Aggiorna traduzione"
#: lib/bds/desktop/menu_bar.ex:252
#: lib/bds/tui.ex:2087
#: lib/bds/tui.ex:2089
#, elixir-autogen, elixir-format
msgid "Regenerate Calendar"
msgstr "Rigenera calendario"
@@ -2157,7 +2159,7 @@ msgid "Regenerate Missing Thumbnails"
msgstr "Rigenera miniature mancanti"
#: lib/bds/desktop/menu_bar.ex:249
#: lib/bds/tui.ex:2081
#: lib/bds/tui.ex:2083
#, elixir-autogen, elixir-format
msgid "Reindex Text"
msgstr "Reindicizza testo"
@@ -2342,10 +2344,11 @@ msgstr "Le capacità di scripting sono configurate a livello applicativo nella r
#: lib/bds/desktop/shell_live/script_editor.ex:175
#: lib/bds/desktop/shell_live/script_editor.ex:191
#: lib/bds/desktop/shell_live/script_editor.ex:194
#: lib/bds/desktop/shell_live/script_editor.ex:216
#: lib/bds/desktop/shell_live/script_editor.ex:219
#: lib/bds/desktop/shell_live/script_editor.ex:234
#: lib/bds/tui.ex:1941
#: lib/bds/desktop/shell_live/script_editor.ex:212
#: lib/bds/desktop/shell_live/script_editor.ex:222
#: lib/bds/desktop/shell_live/script_editor.ex:225
#: lib/bds/desktop/shell_live/script_editor.ex:240
#: lib/bds/tui.ex:1943
#: lib/bds/ui/registry.ex:38
#: lib/bds/ui/sidebar.ex:63
#: lib/bds/ui/sidebar.ex:115
@@ -2452,7 +2455,7 @@ msgstr "Somiglianza semantica"
#: lib/bds/desktop/shell_live/settings_editor/project_settings.ex:60
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:11
#: lib/bds/tui.ex:1943
#: lib/bds/tui.ex:1945
#: lib/bds/ui/registry.ex:86
#: lib/bds/ui/registry.ex:101
#: lib/bds/ui/sidebar.ex:795
@@ -2478,7 +2481,7 @@ msgstr "Sito"
#: lib/bds/desktop/shell_live/misc_editor.ex:412
#: lib/bds/tui.ex:318
#: lib/bds/tui.ex:320
#: lib/bds/tui.ex:1668
#: lib/bds/tui.ex:1670
#: lib/bds/ui/registry.ex:125
#, elixir-autogen, elixir-format
msgid "Site Validation"
@@ -2575,7 +2578,7 @@ msgid "System Prompt"
msgstr "Prompt di sistema"
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:16
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#: lib/bds/ui/sidebar.ex:785
#, elixir-autogen, elixir-format
msgid "Tag Cloud"
@@ -2602,8 +2605,8 @@ msgstr "Nome del tag"
#: lib/bds/desktop/shell_live/tags_editor.ex:217
#: lib/bds/desktop/shell_live/tags_editor.ex:248
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:11
#: lib/bds/tui.ex:1920
#: lib/bds/tui.ex:1942
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1944
#: lib/bds/ui/registry.ex:54
#: lib/bds/ui/registry.ex:103
#: lib/bds/ui/sidebar.ex:289
@@ -2613,8 +2616,8 @@ msgstr "Nome del tag"
msgid "Tags"
msgstr "Tag"
#: lib/bds/desktop/shell_live.ex:786
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#: lib/bds/desktop/shell_live.ex:819
#: lib/bds/desktop/shell_live/panel_renderer.ex:63
#: lib/bds/tui.ex:1220
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -2661,7 +2664,7 @@ msgstr "La sintassi del template è valida"
#: lib/bds/desktop/shell_live/template_editor.ex:171
#: lib/bds/desktop/shell_live/template_editor.ex:176
#: lib/bds/desktop/shell_live/template_editor.ex:191
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1942
#: lib/bds/ui/registry.ex:46
#: lib/bds/ui/sidebar.ex:71
#: lib/bds/ui/sidebar.ex:122
@@ -2670,7 +2673,7 @@ msgstr "La sintassi del template è valida"
msgid "Templates"
msgstr "Template"
#: lib/bds/desktop/shell_live/panel_renderer.ex:194
#: lib/bds/desktop/shell_live/panel_renderer.ex:293
#, elixir-autogen, elixir-format
msgid "The shared lower panel is available for tasks, output, git details, and editor-specific diagnostics."
msgstr "Il pannello inferiore condiviso è disponibile per attività, output, dettagli Git e diagnostica specifica dell’editor."
@@ -2885,7 +2888,7 @@ msgid "Updated URLs"
msgstr "URL aggiornati"
#: lib/bds/desktop/menu_bar.ex:259
#: lib/bds/tui.ex:2099
#: lib/bds/tui.ex:2101
#, elixir-autogen, elixir-format
msgid "Upload Site"
msgstr "Carica sito"
@@ -2913,13 +2916,13 @@ msgid "Validate"
msgstr "Valida"
#: lib/bds/desktop/menu_bar.ex:258
#: lib/bds/tui.ex:2077
#: lib/bds/tui.ex:2079
#, elixir-autogen, elixir-format
msgid "Validate Site"
msgstr "Valida sito"
#: lib/bds/desktop/menu_bar.ex:253
#: lib/bds/tui.ex:2090
#: lib/bds/tui.ex:2092
#, elixir-autogen, elixir-format
msgid "Validate Translations"
msgstr "Valida traduzioni"
@@ -3301,12 +3304,12 @@ msgstr "Benvenuto nell’assistente IA"
msgid "Comparing database and filesystem metadata"
msgstr "Confronto tra i metadati del database e del filesystem"
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:717
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr "%{count} immagini aggiunte al post"
#: lib/bds/desktop/shell_live.ex:652
#: lib/bds/desktop/shell_live.ex:685
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr "%{title} aggiunto"
@@ -3327,18 +3330,18 @@ msgstr "Guida per l'utente finale per flussi editoriali, media, modelli, traduzi
msgid "Image Import Concurrency"
msgstr "Importazione simultanea immagini"
#: lib/bds/desktop/shell_live.ex:444
#: lib/bds/desktop/shell_live.ex:457
#: lib/bds/desktop/shell_live.ex:651
#: lib/bds/desktop/shell_live.ex:683
#: lib/bds/desktop/shell_live.ex:694
#: lib/bds/desktop/shell_live.ex:705
#: lib/bds/desktop/shell_live.ex:477
#: lib/bds/desktop/shell_live.ex:490
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:716
#: lib/bds/desktop/shell_live.ex:727
#: lib/bds/desktop/shell_live.ex:738
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr "Aggiungi immagini alla galleria"
#: lib/bds/desktop/shell_live.ex:706
#: lib/bds/desktop/shell_live.ex:739
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr "Impossibile elaborare %{path}: %{reason}"
@@ -3400,7 +3403,7 @@ msgid "Commit"
msgstr "Commit"
#: lib/bds/desktop/shell_live/sidebar_components.ex:555
#: lib/bds/tui.ex:1490
#: lib/bds/tui.ex:1492
#, elixir-autogen, elixir-format
msgid "Commit message"
msgstr "Messaggio di commit"
@@ -3536,12 +3539,12 @@ msgstr "rinominato"
msgid "untracked"
msgstr "non tracciato"
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:845
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr "Blogmark"
#: lib/bds/desktop/shell_live.ex:855
#: lib/bds/desktop/shell_live.ex:888
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr "Apri un progetto prima di importare un blogmark."
@@ -3582,7 +3585,7 @@ msgstr "Elimina tag"
msgid "Failed to copy bookmarklet to clipboard"
msgstr "Impossibile copiare il bookmarklet negli appunti"
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live.ex:857
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr "Il progetto a cui punta questo blogmark non esiste qui."
@@ -3593,7 +3596,7 @@ msgid "Suggested tags"
msgstr "Tag suggeriti"
#: lib/bds/desktop/menu_bar.ex:257
#: lib/bds/tui.ex:2078
#: lib/bds/tui.ex:2080
#, elixir-autogen, elixir-format
msgid "Force Render Site"
msgstr "Forza la rigenerazione del sito"
@@ -3690,12 +3693,12 @@ msgstr "OK"
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr "L'endpoint non ha restituito alcun modello. Puoi comunque digitare manualmente il nome di un modello."
#: lib/bds/tui.ex:2036
#: lib/bds/tui.ex:2038
#, elixir-autogen, elixir-format
msgid "AI is unavailable in airplane mode without a local endpoint."
msgstr "L'IA non è disponibile in modalità aereo senza un endpoint locale."
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:2165
#, elixir-autogen, elixir-format
msgid "Could not load this file."
msgstr "Impossibile caricare questo file."
@@ -3710,12 +3713,12 @@ msgstr "La modifica di questo elemento non è ancora disponibile nell'interfacci
msgid "No suggestions returned."
msgstr "Nessun suggerimento ricevuto."
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2162
#, elixir-autogen, elixir-format
msgid "Only images can be previewed."
msgstr "Solo le immagini possono essere visualizzate in anteprima."
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1955
#, elixir-autogen, elixir-format
msgid "Post not found."
msgstr "Post non trovato."
@@ -3725,18 +3728,18 @@ msgstr "Post non trovato."
msgid "Press enter to preview %{name}."
msgstr "Premi Invio per l'anteprima di %{name}."
#: lib/bds/tui.ex:2006
#: lib/bds/tui.ex:2008
#, elixir-autogen, elixir-format
msgid "Published."
msgstr "Pubblicato."
#: lib/bds/tui.ex:2022
#: lib/bds/tui.ex:2024
#, elixir-autogen, elixir-format
msgid "Save before switching languages."
msgstr "Salva prima di cambiare lingua."
#: lib/bds/tui.ex:540
#: lib/bds/tui.ex:2007
#: lib/bds/tui.ex:2009
#, elixir-autogen, elixir-format
msgid "Saved."
msgstr "Salvato."
@@ -3761,18 +3764,18 @@ msgstr "Titolo (ctrl+t per modificare)"
msgid "Title (editing — enter to confirm)"
msgstr "Titolo (modifica — Invio per confermare)"
#: lib/bds/tui.ex:1492
#: lib/bds/tui.ex:1494
#, elixir-autogen, elixir-format
msgid "Working…"
msgstr "Elaborazione…"
#: lib/bds/tui.ex:1514
#: lib/bds/tui.ex:1516
#, elixir-autogen, elixir-format
msgid "esc to close"
msgstr "esc per chiudere"
#: lib/bds/desktop/menu_bar.ex:83
#: lib/bds/desktop/shell_live.ex:1110
#: lib/bds/desktop/shell_live.ex:1176
#, elixir-autogen, elixir-format
msgid "Connect to Server"
msgstr "Connetti al server"
@@ -3793,7 +3796,7 @@ msgid "Disconnect from Server"
msgstr "Disconnetti dal server"
#: lib/bds/desktop/menu_bar.ex:72
#: lib/bds/desktop/shell_live.ex:1097
#: lib/bds/desktop/shell_live.ex:1163
#, elixir-autogen, elixir-format
msgid "Server address (user@host or user@host:port), public-key auth:"
msgstr "Indirizzo del server (user@host o user@host:port), autenticazione a chiave pubblica:"
@@ -3803,12 +3806,12 @@ msgstr "Indirizzo del server (user@host o user@host:port), autenticazione a chia
msgid "Use the form user@host or user@host:port."
msgstr "Usa il formato user@host o user@host:port."
#: lib/bds/tui.ex:1457
#: lib/bds/tui.ex:1456
#, elixir-autogen, elixir-format
msgid "Preview (ctrl+e to edit)"
msgstr "Anteprima (ctrl+e per modificare)"
#: lib/bds/tui.ex:1771
#: lib/bds/tui.ex:1773
#, elixir-autogen, elixir-format
msgid "ctrl+s save · ctrl+p publish · ctrl+e preview · ctrl+t title · ctrl+l language · ctrl+g AI · esc back"
msgstr "ctrl+s salva · ctrl+p pubblica · ctrl+e anteprima · ctrl+t titolo · ctrl+l lingua · ctrl+g IA · esc indietro"
@@ -3818,7 +3821,7 @@ msgstr "ctrl+s salva · ctrl+p pubblica · ctrl+e anteprima · ctrl+t titolo ·
msgid "All tasks finished."
msgstr "Tutte le attività sono terminate."
#: lib/bds/tui.ex:1540
#: lib/bds/tui.ex:1542
#, elixir-autogen, elixir-format
msgid "Commands — esc to close"
msgstr "Comandi — esc per chiudere"
@@ -3828,27 +3831,27 @@ msgstr "Comandi — esc per chiudere"
msgid "Unknown command."
msgstr "Comando sconosciuto."
#: lib/bds/tui.ex:1530
#: lib/bds/tui.ex:1532
#, elixir-autogen, elixir-format
msgid "[report/apply in GUI]"
msgstr "[report/applicazione nella GUI]"
#: lib/bds/tui.ex:1679
#: lib/bds/tui.ex:1681
#, elixir-autogen, elixir-format
msgid "%{diffs} differences · %{orphans} orphan files"
msgstr "%{diffs} differenze · %{orphans} file orfani"
#: lib/bds/tui.ex:1711
#: lib/bds/tui.ex:1713
#, elixir-autogen, elixir-format
msgid "Expected %{expected} · Existing %{existing}"
msgstr "Attesi %{expected} · Esistenti %{existing}"
#: lib/bds/tui.ex:1728
#: lib/bds/tui.ex:1730
#, elixir-autogen, elixir-format
msgid "Extra files (will be removed):"
msgstr "File in eccesso (verranno rimossi):"
#: lib/bds/tui.ex:1724
#: lib/bds/tui.ex:1726
#, elixir-autogen, elixir-format
msgid "Missing pages (will be rendered):"
msgstr "Pagine mancanti (verranno generate):"
@@ -3863,27 +3866,27 @@ msgstr "Niente da applicare."
msgid "Nothing to repair."
msgstr "Niente da riparare."
#: lib/bds/tui.ex:1702
#: lib/bds/tui.ex:1704
#, elixir-autogen, elixir-format
msgid "Orphan files (not in database):"
msgstr "File orfani (non presenti nel database):"
#: lib/bds/tui.ex:1718
#: lib/bds/tui.ex:1720
#, elixir-autogen, elixir-format
msgid "Sitemap changed."
msgstr "Sitemap modificata."
#: lib/bds/tui.ex:1732
#: lib/bds/tui.ex:1734
#, elixir-autogen, elixir-format
msgid "Updated posts (will be re-rendered):"
msgstr "Post aggiornati (verranno rigenerati):"
#: lib/bds/tui.ex:1669
#: lib/bds/tui.ex:1671
#, elixir-autogen, elixir-format
msgid "enter apply changes · esc close"
msgstr "invio applica le modifiche · esc chiudi"
#: lib/bds/tui.ex:1664
#: lib/bds/tui.ex:1666
#, elixir-autogen, elixir-format
msgid "enter repair all from files · esc close"
msgstr "invio ripara tutto dai file · esc chiudi"
@@ -3898,7 +3901,7 @@ msgstr "Blog importato"
msgid "Not a folder: %{path}"
msgstr "Non è una cartella: %{path}"
#: lib/bds/tui.ex:1606
#: lib/bds/tui.ex:1608
#, elixir-autogen, elixir-format
msgid "Projects — enter switch · o open existing · esc close"
msgstr "Progetti — invio cambia · o apri esistente · esc chiudi"
@@ -3908,12 +3911,12 @@ msgstr "Progetti — invio cambia · o apri esistente · esc chiudi"
msgid "Switched to %{name}."
msgstr "Passato a %{name}."
#: lib/bds/tui.ex:1634
#: lib/bds/tui.ex:1636
#, elixir-autogen, elixir-format
msgid "Matching folders"
msgstr "Cartelle corrispondenti"
#: lib/bds/tui.ex:1572
#: lib/bds/tui.ex:1574
#, elixir-autogen, elixir-format
msgid "Open Existing Blog — type a folder path · tab complete · enter open · esc back"
msgstr "Apri blog esistente — digita il percorso di una cartella · tab completa · invio apri · esc indietro"
@@ -3933,7 +3936,7 @@ msgstr "Commit eseguito."
msgid "Diff (pgup/pgdn scroll)"
msgstr "Diff (pgup/pgdn per scorrere)"
#: lib/bds/tui.ex:1799
#: lib/bds/tui.ex:1801
#, elixir-autogen, elixir-format
msgid "No changes."
msgstr "Nessuna modifica."
@@ -4044,7 +4047,7 @@ msgstr "Tema"
msgid "enter edit · ctrl+s save · esc close"
msgstr "invio modifica · ctrl+s salva · esc chiudi"
#: lib/bds/tui.ex:1750
#: lib/bds/tui.ex:1752
#, elixir-autogen, elixir-format
msgid "enter edit/toggle/cycle · ctrl+s save · esc close · ctrl+q quit"
msgstr "invio modifica/attiva/cicla · ctrl+s salva · esc chiudi · ctrl+q esci"
@@ -4054,12 +4057,12 @@ msgstr "invio modifica/attiva/cicla · ctrl+s salva · esc chiudi · ctrl+q esci
msgid "not supported yet"
msgstr "non ancora supportato"
#: lib/bds/tui.ex:1757
#: lib/bds/tui.ex:1759
#, elixir-autogen, elixir-format
msgid "c commit · u pull · s push · enter jump to file · pgup/pgdn scroll diff · 1-7 views · ctrl+q quit"
msgstr "c commit · u pull · s push · invio vai al file · pgup/pgdn scorri il diff · 1-7 viste · ctrl+q esci"
#: lib/bds/tui.ex:1764
#: lib/bds/tui.ex:1766
#, elixir-autogen, elixir-format
msgid "enter open · n new post · 1-7 views · p projects · / search · : commands (:? help) · r refresh · ctrl+q quit"
msgstr "invio apri · n nuovo post · 1-7 viste · p progetti · / cerca · : comandi (:? aiuto) · r aggiorna · ctrl+q esci"
@@ -4191,12 +4194,12 @@ msgstr "La destinazione dell'unione deve essere uno dei tag contrassegnati"
msgid "default"
msgstr "predefinito"
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#, elixir-autogen, elixir-format
msgid "esc close"
msgstr "esc chiudi"
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1924
#, elixir-autogen, elixir-format
msgid "n new · enter rename · c colour · t template · d delete · s sync · esc close"
msgstr "n nuovo · invio rinomina · c colore · t template · d elimina · s sincronizza · esc chiudi"
@@ -4206,7 +4209,17 @@ msgstr "n nuovo · invio rinomina · c colore · t template · d elimina · s si
msgid "none"
msgstr "nessuno"
#: lib/bds/tui.ex:1927
#: lib/bds/tui.ex:1929
#, elixir-autogen, elixir-format
msgid "space mark · m merge into selected · esc close"
msgstr "spazio contrassegna · m unisci nel selezionato · esc chiudi"
#: lib/bds/desktop/shell_live/panel_renderer.ex:157
#, elixir-autogen, elixir-format
msgid "Pending"
msgstr "In attesa"
#: lib/bds/desktop/shell_live/panel_renderer.ex:156
#, elixir-autogen, elixir-format
msgid "Running"
msgstr "In corso"
+115 -102
View File
@@ -99,7 +99,7 @@ msgstr ""
#: lib/bds/tui.ex:1175
#: lib/bds/tui.ex:1178
#: lib/bds/tui.ex:1186
#: lib/bds/tui.ex:2035
#: lib/bds/tui.ex:2037
#, elixir-autogen, elixir-format
msgid "AI Suggestions"
msgstr ""
@@ -356,7 +356,7 @@ msgstr ""
msgid "Auto"
msgstr ""
#: lib/bds/desktop/shell_live.ex:445
#: lib/bds/desktop/shell_live.ex:478
#: lib/bds/desktop/shell_live/chat_editor.ex:234
#: lib/bds/desktop/shell_live/media_editor.ex:171
#: lib/bds/desktop/shell_live/media_editor.ex:364
@@ -381,7 +381,7 @@ msgstr ""
msgid "Available languages"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:124
#: lib/bds/desktop/shell_live/panel_renderer.ex:223
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:313
#, elixir-autogen, elixir-format
msgid "Backlinks"
@@ -454,6 +454,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:183
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:208
#: lib/bds/desktop/shell_live/overlay_html/shell_overlay.html.heex:225
#: lib/bds/desktop/shell_live/panel_renderer.ex:143
#, elixir-autogen, elixir-format
msgid "Cancel"
msgstr ""
@@ -507,7 +508,7 @@ msgstr ""
msgid "Category name is required"
msgstr ""
#: lib/bds/desktop/shell_live.ex:791
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live/chat_editor.ex:87
#: lib/bds/desktop/shell_live/chat_editor.ex:233
#: lib/bds/desktop/shell_live/chat_editor.ex:323
@@ -588,7 +589,7 @@ msgid "Collapse unchanged diff hunks"
msgstr ""
#: lib/bds/desktop/shell_live/overlay_manager.ex:423
#: lib/bds/tui.ex:2131
#: lib/bds/tui.ex:2133
#, elixir-autogen, elixir-format
msgid "Command completed"
msgstr ""
@@ -606,7 +607,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:375
#: lib/bds/desktop/shell_live/script_editor_html/script_editor.html.heex:34
#: lib/bds/desktop/shell_live/template_editor_html/template_editor.html.heex:32
#: lib/bds/tui.ex:1468
#: lib/bds/tui.ex:1467
#: lib/bds/ui/settings_form.ex:137
#: lib/bds/ui/sidebar.ex:801
#, elixir-autogen, elixir-format
@@ -619,6 +620,7 @@ msgid "Content Categories"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:226
#: lib/bds/desktop/shell_live/panel_renderer.ex:183
#, elixir-autogen, elixir-format
msgid "Copy"
msgstr ""
@@ -1053,7 +1055,7 @@ msgid "Filename"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:254
#: lib/bds/tui.ex:2095
#: lib/bds/tui.ex:2097
#, elixir-autogen, elixir-format
msgid "Fill Missing Translations"
msgstr ""
@@ -1064,7 +1066,7 @@ msgid "Find"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:255
#: lib/bds/tui.ex:2098
#: lib/bds/tui.ex:2100
#, elixir-autogen, elixir-format
msgid "Find Duplicate Posts"
msgstr ""
@@ -1091,14 +1093,14 @@ msgid "Gallery"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:256
#: lib/bds/tui.ex:2079
#: lib/bds/tui.ex:2081
#, elixir-autogen, elixir-format
msgid "Generate Site"
msgstr ""
#: lib/bds/desktop/shell_live.ex:792
#: lib/bds/desktop/shell_live.ex:825
#: lib/bds/desktop/shell_live/socket_state.ex:109
#: lib/bds/tui.ex:1944
#: lib/bds/tui.ex:1946
#: lib/bds/ui/sidebar.ex:826
#, elixir-autogen, elixir-format
msgid "Git"
@@ -1111,8 +1113,8 @@ msgid "Git Diff"
msgstr ""
#: lib/bds/desktop/shell_data.ex:228
#: lib/bds/desktop/shell_live.ex:788
#: lib/bds/desktop/shell_live/panel_renderer.ex:171
#: lib/bds/desktop/shell_live.ex:821
#: lib/bds/desktop/shell_live/panel_renderer.ex:270
#, elixir-autogen, elixir-format
msgid "Git Log"
msgstr ""
@@ -1235,9 +1237,9 @@ msgstr ""
msgid "Import failed: %{error}"
msgstr ""
#: lib/bds/desktop/shell_live.ex:608
#: lib/bds/desktop/shell_live.ex:904
#: lib/bds/desktop/shell_live.ex:910
#: lib/bds/desktop/shell_live.ex:641
#: lib/bds/desktop/shell_live.ex:970
#: lib/bds/desktop/shell_live.ex:976
#: lib/bds/desktop/shell_live/sidebar_create.ex:47
#, elixir-autogen, elixir-format
msgid "Import media"
@@ -1338,7 +1340,7 @@ msgstr ""
msgid "Linked Posts"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:142
#: lib/bds/desktop/shell_live/panel_renderer.ex:241
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:325
#, elixir-autogen, elixir-format
msgid "Links To"
@@ -1417,9 +1419,9 @@ msgstr ""
#: lib/bds/desktop/shell_live/misc_editor.ex:762
#: lib/bds/desktop/shell_live/sidebar_components.ex:654
#: lib/bds/desktop/shell_live/sidebar_delete.ex:175
#: lib/bds/tui.ex:1939
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:1941
#: lib/bds/tui.ex:2162
#: lib/bds/tui.ex:2165
#: lib/bds/ui/registry.ex:30
#: lib/bds/ui/registry.ex:100
#: lib/bds/ui/sidebar.ex:578
@@ -1448,7 +1450,7 @@ msgid "Merge"
msgstr ""
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:78
#: lib/bds/tui.ex:1926
#: lib/bds/tui.ex:1928
#: lib/bds/ui/sidebar.ex:787
#, elixir-autogen, elixir-format
msgid "Merge Tags"
@@ -1466,8 +1468,8 @@ msgstr ""
#: lib/bds/tui.ex:285
#: lib/bds/tui.ex:291
#: lib/bds/tui.ex:302
#: lib/bds/tui.ex:1663
#: lib/bds/tui.ex:2076
#: lib/bds/tui.ex:1665
#: lib/bds/tui.ex:2078
#: lib/bds/ui/registry.ex:111
#, elixir-autogen, elixir-format
msgid "Metadata Diff"
@@ -1545,12 +1547,12 @@ msgstr ""
msgid "No Template"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:55
#: lib/bds/desktop/shell_live/panel_renderer.ex:64
#, elixir-autogen, elixir-format
msgid "No background tasks running"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:179
#: lib/bds/desktop/shell_live/panel_renderer.ex:278
#, elixir-autogen, elixir-format
msgid "No commit subject"
msgstr ""
@@ -1560,7 +1562,7 @@ msgstr ""
msgid "No folder selected"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#: lib/bds/desktop/shell_live/panel_renderer.ex:271
#, elixir-autogen, elixir-format
msgid "No git history yet"
msgstr ""
@@ -1620,7 +1622,7 @@ msgstr ""
msgid "No pages yet"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:119
#: lib/bds/desktop/shell_live/panel_renderer.ex:218
#, elixir-autogen, elixir-format
msgid "No post links yet"
msgstr ""
@@ -1645,7 +1647,7 @@ msgstr ""
msgid "No settings match the current search"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:84
#: lib/bds/desktop/shell_live/panel_renderer.ex:173
#, elixir-autogen, elixir-format
msgid "No shell output yet"
msgstr ""
@@ -1814,7 +1816,7 @@ msgid "Open Settings"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:217
#: lib/bds/tui.ex:2100
#: lib/bds/tui.ex:2102
#, elixir-autogen, elixir-format
msgid "Open in Browser"
msgstr ""
@@ -1845,8 +1847,8 @@ msgstr ""
msgid "Other (%{count})"
msgstr ""
#: lib/bds/desktop/shell_live.ex:787
#: lib/bds/desktop/shell_live/panel_renderer.ex:83
#: lib/bds/desktop/shell_live.ex:820
#: lib/bds/desktop/shell_live/panel_renderer.ex:172
#, elixir-autogen, elixir-format
msgid "Output"
msgstr ""
@@ -1928,7 +1930,7 @@ msgid "Post"
msgstr ""
#: lib/bds/desktop/shell_data.ex:231
#: lib/bds/desktop/shell_live/panel_renderer.ex:118
#: lib/bds/desktop/shell_live/panel_renderer.ex:217
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:310
#, elixir-autogen, elixir-format
msgid "Post Links"
@@ -1963,8 +1965,8 @@ msgstr ""
#: lib/bds/desktop/menu_bar.ex:233
#: lib/bds/desktop/shell_live/misc_editor.ex:664
#: lib/bds/desktop/shell_live/misc_editor.ex:761
#: lib/bds/tui.ex:1938
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1955
#: lib/bds/ui/registry.ex:14
#: lib/bds/ui/sidebar.ex:271
#, elixir-autogen, elixir-format
@@ -2094,14 +2096,14 @@ msgstr ""
#: lib/bds/desktop/menu_bar.ex:248
#: lib/bds/tui.ex:1016
#: lib/bds/tui.ex:2080
#: lib/bds/tui.ex:2082
#, elixir-autogen, elixir-format
msgid "Rebuild Database"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:250
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:381
#: lib/bds/tui.ex:2084
#: lib/bds/tui.ex:2086
#, elixir-autogen, elixir-format
msgid "Rebuild Embedding Index"
msgstr ""
@@ -2159,7 +2161,7 @@ msgid "Refresh Translation"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:252
#: lib/bds/tui.ex:2087
#: lib/bds/tui.ex:2089
#, elixir-autogen, elixir-format
msgid "Regenerate Calendar"
msgstr ""
@@ -2170,7 +2172,7 @@ msgid "Regenerate Missing Thumbnails"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:249
#: lib/bds/tui.ex:2081
#: lib/bds/tui.ex:2083
#, elixir-autogen, elixir-format
msgid "Reindex Text"
msgstr ""
@@ -2355,10 +2357,11 @@ msgstr ""
#: lib/bds/desktop/shell_live/script_editor.ex:175
#: lib/bds/desktop/shell_live/script_editor.ex:191
#: lib/bds/desktop/shell_live/script_editor.ex:194
#: lib/bds/desktop/shell_live/script_editor.ex:216
#: lib/bds/desktop/shell_live/script_editor.ex:219
#: lib/bds/desktop/shell_live/script_editor.ex:234
#: lib/bds/tui.ex:1941
#: lib/bds/desktop/shell_live/script_editor.ex:212
#: lib/bds/desktop/shell_live/script_editor.ex:222
#: lib/bds/desktop/shell_live/script_editor.ex:225
#: lib/bds/desktop/shell_live/script_editor.ex:240
#: lib/bds/tui.ex:1943
#: lib/bds/ui/registry.ex:38
#: lib/bds/ui/sidebar.ex:63
#: lib/bds/ui/sidebar.ex:115
@@ -2465,7 +2468,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/settings_editor/project_settings.ex:60
#: lib/bds/desktop/shell_live/settings_editor_html/settings_editor.html.heex:11
#: lib/bds/tui.ex:1943
#: lib/bds/tui.ex:1945
#: lib/bds/ui/registry.ex:86
#: lib/bds/ui/registry.ex:101
#: lib/bds/ui/sidebar.ex:795
@@ -2491,7 +2494,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/misc_editor.ex:412
#: lib/bds/tui.ex:318
#: lib/bds/tui.ex:320
#: lib/bds/tui.ex:1668
#: lib/bds/tui.ex:1670
#: lib/bds/ui/registry.ex:125
#, elixir-autogen, elixir-format
msgid "Site Validation"
@@ -2588,7 +2591,7 @@ msgid "System Prompt"
msgstr ""
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:16
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#: lib/bds/ui/sidebar.ex:785
#, elixir-autogen, elixir-format
msgid "Tag Cloud"
@@ -2615,8 +2618,8 @@ msgstr ""
#: lib/bds/desktop/shell_live/tags_editor.ex:217
#: lib/bds/desktop/shell_live/tags_editor.ex:248
#: lib/bds/desktop/shell_live/tags_editor_html/tags_editor.html.heex:11
#: lib/bds/tui.ex:1920
#: lib/bds/tui.ex:1942
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1944
#: lib/bds/ui/registry.ex:54
#: lib/bds/ui/registry.ex:103
#: lib/bds/ui/sidebar.ex:289
@@ -2626,8 +2629,8 @@ msgstr ""
msgid "Tags"
msgstr ""
#: lib/bds/desktop/shell_live.ex:786
#: lib/bds/desktop/shell_live/panel_renderer.ex:54
#: lib/bds/desktop/shell_live.ex:819
#: lib/bds/desktop/shell_live/panel_renderer.ex:63
#: lib/bds/tui.ex:1220
#, elixir-autogen, elixir-format
msgid "Tasks"
@@ -2674,7 +2677,7 @@ msgstr ""
#: lib/bds/desktop/shell_live/template_editor.ex:171
#: lib/bds/desktop/shell_live/template_editor.ex:176
#: lib/bds/desktop/shell_live/template_editor.ex:191
#: lib/bds/tui.ex:1940
#: lib/bds/tui.ex:1942
#: lib/bds/ui/registry.ex:46
#: lib/bds/ui/sidebar.ex:71
#: lib/bds/ui/sidebar.ex:122
@@ -2683,7 +2686,7 @@ msgstr ""
msgid "Templates"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:194
#: lib/bds/desktop/shell_live/panel_renderer.ex:293
#, elixir-autogen, elixir-format
msgid "The shared lower panel is available for tasks, output, git details, and editor-specific diagnostics."
msgstr ""
@@ -2898,7 +2901,7 @@ msgid "Updated URLs"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:259
#: lib/bds/tui.ex:2099
#: lib/bds/tui.ex:2101
#, elixir-autogen, elixir-format
msgid "Upload Site"
msgstr ""
@@ -2926,13 +2929,13 @@ msgid "Validate"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:258
#: lib/bds/tui.ex:2077
#: lib/bds/tui.ex:2079
#, elixir-autogen, elixir-format
msgid "Validate Site"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:253
#: lib/bds/tui.ex:2090
#: lib/bds/tui.ex:2092
#, elixir-autogen, elixir-format
msgid "Validate Translations"
msgstr ""
@@ -3314,12 +3317,12 @@ msgstr ""
msgid "Comparing database and filesystem metadata"
msgstr ""
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:717
#, elixir-autogen, elixir-format
msgid "Added %{count} images to post"
msgstr ""
#: lib/bds/desktop/shell_live.ex:652
#: lib/bds/desktop/shell_live.ex:685
#, elixir-autogen, elixir-format
msgid "Added %{title}"
msgstr ""
@@ -3340,18 +3343,18 @@ msgstr ""
msgid "Image Import Concurrency"
msgstr ""
#: lib/bds/desktop/shell_live.ex:444
#: lib/bds/desktop/shell_live.ex:457
#: lib/bds/desktop/shell_live.ex:651
#: lib/bds/desktop/shell_live.ex:683
#: lib/bds/desktop/shell_live.ex:694
#: lib/bds/desktop/shell_live.ex:705
#: lib/bds/desktop/shell_live.ex:477
#: lib/bds/desktop/shell_live.ex:490
#: lib/bds/desktop/shell_live.ex:684
#: lib/bds/desktop/shell_live.ex:716
#: lib/bds/desktop/shell_live.ex:727
#: lib/bds/desktop/shell_live.ex:738
#: lib/bds/desktop/shell_live/post_editor_html/post_editor.html.heex:420
#, elixir-autogen, elixir-format
msgid "Add Gallery Images"
msgstr ""
#: lib/bds/desktop/shell_live.ex:706
#: lib/bds/desktop/shell_live.ex:739
#, elixir-autogen, elixir-format
msgid "Failed to process %{path}: %{reason}"
msgstr ""
@@ -3413,7 +3416,7 @@ msgid "Commit"
msgstr ""
#: lib/bds/desktop/shell_live/sidebar_components.ex:555
#: lib/bds/tui.ex:1490
#: lib/bds/tui.ex:1492
#, elixir-autogen, elixir-format
msgid "Commit message"
msgstr ""
@@ -3549,12 +3552,12 @@ msgstr ""
msgid "untracked"
msgstr ""
#: lib/bds/desktop/shell_live.ex:812
#: lib/bds/desktop/shell_live.ex:845
#, elixir-autogen, elixir-format
msgid "Blogmark"
msgstr ""
#: lib/bds/desktop/shell_live.ex:855
#: lib/bds/desktop/shell_live.ex:888
#, elixir-autogen, elixir-format
msgid "Open a project before importing a blogmark."
msgstr ""
@@ -3595,7 +3598,7 @@ msgstr ""
msgid "Failed to copy bookmarklet to clipboard"
msgstr ""
#: lib/bds/desktop/shell_live.ex:824
#: lib/bds/desktop/shell_live.ex:857
#, elixir-autogen, elixir-format
msgid "The project this blogmark targets does not exist here."
msgstr ""
@@ -3606,7 +3609,7 @@ msgid "Suggested tags"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:257
#: lib/bds/tui.ex:2078
#: lib/bds/tui.ex:2080
#, elixir-autogen, elixir-format
msgid "Force Render Site"
msgstr ""
@@ -3703,12 +3706,12 @@ msgstr ""
msgid "The endpoint returned no models. You can still type a model name manually."
msgstr ""
#: lib/bds/tui.ex:2036
#: lib/bds/tui.ex:2038
#, elixir-autogen, elixir-format
msgid "AI is unavailable in airplane mode without a local endpoint."
msgstr ""
#: lib/bds/tui.ex:2163
#: lib/bds/tui.ex:2165
#, elixir-autogen, elixir-format
msgid "Could not load this file."
msgstr ""
@@ -3723,12 +3726,12 @@ msgstr ""
msgid "No suggestions returned."
msgstr ""
#: lib/bds/tui.ex:2160
#: lib/bds/tui.ex:2162
#, elixir-autogen, elixir-format
msgid "Only images can be previewed."
msgstr ""
#: lib/bds/tui.ex:1953
#: lib/bds/tui.ex:1955
#, elixir-autogen, elixir-format
msgid "Post not found."
msgstr ""
@@ -3738,18 +3741,18 @@ msgstr ""
msgid "Press enter to preview %{name}."
msgstr ""
#: lib/bds/tui.ex:2006
#: lib/bds/tui.ex:2008
#, elixir-autogen, elixir-format
msgid "Published."
msgstr ""
#: lib/bds/tui.ex:2022
#: lib/bds/tui.ex:2024
#, elixir-autogen, elixir-format
msgid "Save before switching languages."
msgstr ""
#: lib/bds/tui.ex:540
#: lib/bds/tui.ex:2007
#: lib/bds/tui.ex:2009
#, elixir-autogen, elixir-format
msgid "Saved."
msgstr ""
@@ -3774,18 +3777,18 @@ msgstr ""
msgid "Title (editing — enter to confirm)"
msgstr ""
#: lib/bds/tui.ex:1492
#: lib/bds/tui.ex:1494
#, elixir-autogen, elixir-format
msgid "Working…"
msgstr ""
#: lib/bds/tui.ex:1514
#: lib/bds/tui.ex:1516
#, elixir-autogen, elixir-format
msgid "esc to close"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:83
#: lib/bds/desktop/shell_live.ex:1110
#: lib/bds/desktop/shell_live.ex:1176
#, elixir-autogen, elixir-format
msgid "Connect to Server"
msgstr ""
@@ -3806,7 +3809,7 @@ msgid "Disconnect from Server"
msgstr ""
#: lib/bds/desktop/menu_bar.ex:72
#: lib/bds/desktop/shell_live.ex:1097
#: lib/bds/desktop/shell_live.ex:1163
#, elixir-autogen, elixir-format
msgid "Server address (user@host or user@host:port), public-key auth:"
msgstr ""
@@ -3816,12 +3819,12 @@ msgstr ""
msgid "Use the form user@host or user@host:port."
msgstr ""
#: lib/bds/tui.ex:1457
#: lib/bds/tui.ex:1456
#, elixir-autogen, elixir-format
msgid "Preview (ctrl+e to edit)"
msgstr ""
#: lib/bds/tui.ex:1771
#: lib/bds/tui.ex:1773
#, elixir-autogen, elixir-format
msgid "ctrl+s save · ctrl+p publish · ctrl+e preview · ctrl+t title · ctrl+l language · ctrl+g AI · esc back"
msgstr ""
@@ -3831,7 +3834,7 @@ msgstr ""
msgid "All tasks finished."
msgstr ""
#: lib/bds/tui.ex:1540
#: lib/bds/tui.ex:1542
#, elixir-autogen, elixir-format
msgid "Commands — esc to close"
msgstr ""
@@ -3841,27 +3844,27 @@ msgstr ""
msgid "Unknown command."
msgstr ""
#: lib/bds/tui.ex:1530
#: lib/bds/tui.ex:1532
#, elixir-autogen, elixir-format
msgid "[report/apply in GUI]"
msgstr ""
#: lib/bds/tui.ex:1679
#: lib/bds/tui.ex:1681
#, elixir-autogen, elixir-format
msgid "%{diffs} differences · %{orphans} orphan files"
msgstr ""
#: lib/bds/tui.ex:1711
#: lib/bds/tui.ex:1713
#, elixir-autogen, elixir-format
msgid "Expected %{expected} · Existing %{existing}"
msgstr ""
#: lib/bds/tui.ex:1728
#: lib/bds/tui.ex:1730
#, elixir-autogen, elixir-format
msgid "Extra files (will be removed):"
msgstr ""
#: lib/bds/tui.ex:1724
#: lib/bds/tui.ex:1726
#, elixir-autogen, elixir-format
msgid "Missing pages (will be rendered):"
msgstr ""
@@ -3876,27 +3879,27 @@ msgstr ""
msgid "Nothing to repair."
msgstr ""
#: lib/bds/tui.ex:1702
#: lib/bds/tui.ex:1704
#, elixir-autogen, elixir-format
msgid "Orphan files (not in database):"
msgstr ""
#: lib/bds/tui.ex:1718
#: lib/bds/tui.ex:1720
#, elixir-autogen, elixir-format
msgid "Sitemap changed."
msgstr ""
#: lib/bds/tui.ex:1732
#: lib/bds/tui.ex:1734
#, elixir-autogen, elixir-format
msgid "Updated posts (will be re-rendered):"
msgstr ""
#: lib/bds/tui.ex:1669
#: lib/bds/tui.ex:1671
#, elixir-autogen, elixir-format
msgid "enter apply changes · esc close"
msgstr ""
#: lib/bds/tui.ex:1664
#: lib/bds/tui.ex:1666
#, elixir-autogen, elixir-format
msgid "enter repair all from files · esc close"
msgstr ""
@@ -3911,7 +3914,7 @@ msgstr ""
msgid "Not a folder: %{path}"
msgstr ""
#: lib/bds/tui.ex:1606
#: lib/bds/tui.ex:1608
#, elixir-autogen, elixir-format
msgid "Projects — enter switch · o open existing · esc close"
msgstr ""
@@ -3921,12 +3924,12 @@ msgstr ""
msgid "Switched to %{name}."
msgstr ""
#: lib/bds/tui.ex:1634
#: lib/bds/tui.ex:1636
#, elixir-autogen, elixir-format
msgid "Matching folders"
msgstr ""
#: lib/bds/tui.ex:1572
#: lib/bds/tui.ex:1574
#, elixir-autogen, elixir-format
msgid "Open Existing Blog — type a folder path · tab complete · enter open · esc back"
msgstr ""
@@ -3946,7 +3949,7 @@ msgstr ""
msgid "Diff (pgup/pgdn scroll)"
msgstr ""
#: lib/bds/tui.ex:1799
#: lib/bds/tui.ex:1801
#, elixir-autogen, elixir-format
msgid "No changes."
msgstr ""
@@ -4057,7 +4060,7 @@ msgstr ""
msgid "enter edit · ctrl+s save · esc close"
msgstr ""
#: lib/bds/tui.ex:1750
#: lib/bds/tui.ex:1752
#, elixir-autogen, elixir-format
msgid "enter edit/toggle/cycle · ctrl+s save · esc close · ctrl+q quit"
msgstr ""
@@ -4067,12 +4070,12 @@ msgstr ""
msgid "not supported yet"
msgstr ""
#: lib/bds/tui.ex:1757
#: lib/bds/tui.ex:1759
#, elixir-autogen, elixir-format
msgid "c commit · u pull · s push · enter jump to file · pgup/pgdn scroll diff · 1-7 views · ctrl+q quit"
msgstr ""
#: lib/bds/tui.ex:1764
#: lib/bds/tui.ex:1766
#, elixir-autogen, elixir-format
msgid "enter open · n new post · 1-7 views · p projects · / search · : commands (:? help) · r refresh · ctrl+q quit"
msgstr ""
@@ -4204,12 +4207,12 @@ msgstr ""
msgid "default"
msgstr ""
#: lib/bds/tui.ex:1917
#: lib/bds/tui.ex:1919
#, elixir-autogen, elixir-format
msgid "esc close"
msgstr ""
#: lib/bds/tui.ex:1922
#: lib/bds/tui.ex:1924
#, elixir-autogen, elixir-format
msgid "n new · enter rename · c colour · t template · d delete · s sync · esc close"
msgstr ""
@@ -4219,7 +4222,17 @@ msgstr ""
msgid "none"
msgstr ""
#: lib/bds/tui.ex:1927
#: lib/bds/tui.ex:1929
#, elixir-autogen, elixir-format
msgid "space mark · m merge into selected · esc close"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:157
#, elixir-autogen, elixir-format
msgid "Pending"
msgstr ""
#: lib/bds/desktop/shell_live/panel_renderer.ex:156
#, elixir-autogen, elixir-format
msgid "Running"
msgstr ""
+1 -1
View File
@@ -1,2 +1,2 @@
/*! tailwindcss v4.1.14 | MIT License | https://tailwindcss.com */
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-700:oklch(50.5% .213 27.518);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-semibold:600;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--ease-in:cubic-bezier(.4,0,1,1);--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetimLine truncated
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-700:oklch(50.5% .213 27.518);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-semibold:600;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--ease-in:cubic-bezier(.4,0,1,1);--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetimLine truncated
+9 -9
View File
@@ -1,28 +1,28 @@
(()=>{var an=Object.create;var Ti=Object.defineProperty;var ln=Object.getOwnPropertyDescriptor;var hn=Object.getOwnPropertyNames;var cn=Object.getPrototypeOf,dn=Object.prototype.hasOwnProperty;var un=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,i)=>(typeof require<"u"?require:t)[i]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var fn=(e,t,i,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of hn(t))!dn.call(e,n)&&n!==i&&Ti(e,n,{get:()=>t[n],enumerable:!(s=ln(t,n))||s.enumerable});return e};var pn=(e,t,i)=>(i=e!=null?an(cn(e)):{},fn(t||!e||!e.__esModule?Ti(i,"default",{value:e,enumerable:!0}):i,e));var Be=e=>typeof e=="function"?e:function(){return e},mn=typeof self<"u"?self:null,Re=typeof window<"u"?window:null,G=mn||Re||globalThis,gn="2.0.0",Y={connecting:0,open:1,closing:2,closed:3},vn=100,bn=1e4,yn=1e3,V={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},re={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},Mt={longpoll:"longpoll",websocket:"websocket"},wn={complete:4},Ht="base64url.bearer.phx.",rt=class{constructor(e,t,i,s){this.channel=e,this.event=t,this.payload=i||function(){return{}},this.receivedResp=null,this.timeout=s,this.timeoutTimer=null,this.recHooks=[],this.sent=!1}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}matchReceive({status:e,response:t,_ref:i}){this.recHooks.filter(s=>s.status===e).forEach(s=>s.callback(t))}cancelRefEvent(){this.refEvent&&this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}},Ci=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=null,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}},En=class{constructor(e,t,i){this.state=V.closed,this.topic=e,this.params=Be(t||{}),this.socket=i,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new rt(this,re.join,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new Ci(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=V.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(s=>s.send()),this.pushBuffer=[]}),this.joinPush.receive("error",()=>{this.state=V.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic} ${this.joinRef()}`),this.state=V.closed,this.socket.remove(this)}),this.onError(s=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.isJoining()&&this.joinPush.reset(),this.state=V.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic} (${this.joinRef()})`,this.joinPush.timeout),new rt(this,re.leave,Be({}),this.timeout).send(),this.state=V.errored,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(re.reply,(s,n)=>{this.trigger(this.replyEventName(n),s)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}onClose(e){this.on(re.close,e)}onError(e){return this.on(re.error,t=>e(t))}on(e,t){let i=this.bindingRef++;return this.bindings.push({event:e,ref:i,callback:t}),i}off(e,t){this.bindings=this.bindings.filter(i=>!(i.event===e&&(typeof t>"u"||t===i.ref)))}canPush(){return this.socket.isConnected(Line truncated
`),()=>this.onerror("timeout"),n=>{!n||n.status!==200?(this.awaitingBatchAck=!1,this.onerror(n&&n.status),this.closeAndRetry(1011,"internal server error",!1)):i<e.length?this.batchSend(e,i):this.batchBuffer.length>0?(this.batchSend(this.batchBuffer),this.batchBuffer=[]):this.awaitingBatchAck=!1})}close(e,t,i){for(let n of this.reqs)n.abort();this.readyState=Y.closed;let s=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:i});this.batchBuffer=[],clearTimeout(this.currentBatchTimer),this.currentBatchTimer=null,typeof CloseEvent<"u"?this.onclose(new CloseEvent("close",s)):this.onclose(s)}ajax(e,t,i,s,n){let r,o=()=>{this.reqs.delete(r),s()};r=at.request(e,this.endpointURL(),t,i,this.timeout,o,a=>{this.reqs.delete(r),this.isActive()&&n(a)}),this.reqs.add(r)}};var ot={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(e,t){if(e.payload.constructor===ArrayBuffer)return t(this.binaryEncode(e));{let i=[e.join_ref,e.ref,e.topic,e.event,e.payload];return t(JSON.stringify(i))}},decode(e,t){if(e.constructor===ArrayBuffer)return t(this.binaryDecode(e));{let[i,s,n,r,o]=JSON.parse(e);return t({join_ref:i,ref:s,topic:n,event:r,payload:o})}},binaryEncode(e){let{join_ref:t,ref:i,event:s,topic:n,payload:r}=e,o=new TextEncoder,a=o.encode(t),l=o.encode(i),h=o.encode(n),d=o.encode(s);this.assertFieldSize(a.byteLength,"join_ref"),this.assertFieldSize(l.byteLength,"ref"),this.assertFieldSize(h.byteLength,"topic"),this.assertFieldSize(d.byteLength,"event");let p=this.META_LENGTH+a.byteLength+l.byteLength+h.byteLength+d.byteLength,m=new ArrayBuffer(this.HEADER_LENGTH+p),g=new Uint8Array(m),u=new DataView(m),v=0;u.setUint8(v++,this.KINDS.push),u.setUint8(v++,a.byteLength),u.setUint8(v++,l.byteLength),u.setUint8(v++,h.byteLength),u.setUint8(v++,d.byteLength),g.set(a,v),v+=a.byteLength,g.set(l,v),v+=l.byteLength,g.set(h,v),v+=h.byteLength,g.set(d,v),v+=d.byteLength;var y=new Uint8Array(m.byteLength+r.byteLength);return y.set(g,0),y.set(new Uint8Array(r),m.byteLength),y.buffer},assertFieldSize(e,t){if(e>255)throw new Error(`unable to convert ${t} to binary: must be less than or equal to 255 bytes, but is ${e} bytes`)},binaryDecode(e){let t=new DataView(e),i=t.getUint8(0),s=new TextDecoder;switch(i){case this.KINDS.push:return this.decodePush(e,t,s);case this.KINDS.reply:return this.decodeReply(e,t,s);case this.KINDS.broadcast:return this.decodeBroadcast(e,t,s)}},decodePush(e,t,i){let s=t.getUint8(1),n=t.getUint8(2),r=t.getUint8(3),o=this.HEADER_LENGTH+this.META_LENGTH-1,a=i.decode(e.slice(o,o+s));o=o+s;let l=i.decode(e.slice(o,o+n));o=o+n;let h=i.decode(e.slice(o,o+r));o=o+r;let d=e.slice(o,e.byteLength);return{join_ref:a,ref:null,topic:l,event:h,payload:d}},decodeReply(e,t,i){let s=t.getUint8(1),n=t.getUint8(2),r=t.getUint8(3),o=t.getUint8(4),a=this.HEADER_LENGTH+this.META_LENGTH,l=i.decode(e.slice(a,a+s));a=a+s;let h=i.decode(e.slice(a,a+n));a=a+n;let d=i.decode(e.slice(a,a+r));a=a+r;let p=i.decode(e.slice(a,a+o));a=a+o;let m=e.slice(a,e.byteLength),g={status:p,response:m};return{join_ref:l,ref:h,topic:d,event:re.reply,payload:g}},decodeBroadcast(e,t,i){let s=t.getUint8(1),n=t.getUint8(2),r=this.HEADER_LENGTH+2,o=i.decode(e.slice(r,r+s));r=r+s;let a=i.decode(e.slice(r,r+n));r=r+n;let l=e.slice(r,e.byteLength);return{join_ref:null,ref:null,topic:o,event:a,payload:l}}},_i=class{constructor(e,t={}){this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.fallbackRef=null,this.timeout=t.timeout||bn,this.transport=t.transport||G.WebSocket||Pe,this.primaryPassedHealthCheck=!1,this.longPollFallbackMs=t.longPollFallbackMs,this.fallbackTimer=null,this.sessionStore=t.sessionStorage||G&&G.sessionStorage,this.establishedConnections=0,this.defaultEncoder=ot.encode.bind(ot),this.defaultDecoder=ot.decode.bind(ot),this.closeWasClean=!0,this.disconnecting=!1,this.binaryType=t.binaryType||"arraybuffer",this.connectClock=1,this.pageHidden=!1,this.transport!==Pe?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let i=null;Re&&Re.addEventListener&&(Re.addEventListener("pagehide",s=>{this.conn&&(this.disconnect(),i=this.connectClock)}),Re.addEventListener("pageshow",s=>{i===this.connectClock&&(i=null,this.connect())}),Re.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?this.pageHidden=!0:(this.pageHidden=!1,!this.isConnected()&&!this.closeWasClean&&this.teardown(()=>this.connect()))})),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.rejoinAfterMs=s=>t.rejoinAfterMs?t.rejoinAfterMs(s):[1e3,2e3,5e3][s-1]||1e4,this.reconnectAfterMs=s=>t.reconnectAfterMs?t.reconnectAfterMs(s):[10,50,100,150,200,250,500,1e3,2e3][s-1]||5e3,this.logger=t.logger||null,!this.logger&&t.debug&&(this.logger=(s,n,r)=>{console.log(`${s}: ${n}`,r)}),this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=Be(t.params||{}),this.endPoint=`${e}Line truncated
(()=>{var ln=Object.create;var Ti=Object.defineProperty;var hn=Object.getOwnPropertyDescriptor;var cn=Object.getOwnPropertyNames;var dn=Object.getPrototypeOf,un=Object.prototype.hasOwnProperty;var fn=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,i)=>(typeof require<"u"?require:t)[i]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var pn=(e,t,i,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of cn(t))!un.call(e,n)&&n!==i&&Ti(e,n,{get:()=>t[n],enumerable:!(s=hn(t,n))||s.enumerable});return e};var mn=(e,t,i)=>(i=e!=null?ln(dn(e)):{},pn(t||!e||!e.__esModule?Ti(i,"default",{value:e,enumerable:!0}):i,e));var Be=e=>typeof e=="function"?e:function(){return e},gn=typeof self<"u"?self:null,Re=typeof window<"u"?window:null,G=gn||Re||globalThis,vn="2.0.0",Y={connecting:0,open:1,closing:2,closed:3},bn=100,yn=1e4,wn=1e3,V={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},re={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},Mt={longpoll:"longpoll",websocket:"websocket"},En={complete:4},Ht="base64url.bearer.phx.",rt=class{constructor(e,t,i,s){this.channel=e,this.event=t,this.payload=i||function(){return{}},this.receivedResp=null,this.timeout=s,this.timeoutTimer=null,this.recHooks=[],this.sent=!1}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}matchReceive({status:e,response:t,_ref:i}){this.recHooks.filter(s=>s.status===e).forEach(s=>s.callback(t))}cancelRefEvent(){this.refEvent&&this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}},Ci=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=null,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}},Sn=class{constructor(e,t,i){this.state=V.closed,this.topic=e,this.params=Be(t||{}),this.socket=i,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new rt(this,re.join,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new Ci(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=V.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(s=>s.send()),this.pushBuffer=[]}),this.joinPush.receive("error",()=>{this.state=V.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic} ${this.joinRef()}`),this.state=V.closed,this.socket.remove(this)}),this.onError(s=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.isJoining()&&this.joinPush.reset(),this.state=V.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic} (${this.joinRef()})`,this.joinPush.timeout),new rt(this,re.leave,Be({}),this.timeout).send(),this.state=V.errored,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(re.reply,(s,n)=>{this.trigger(this.replyEventName(n),s)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}onClose(e){this.on(re.close,e)}onError(e){return this.on(re.error,t=>e(t))}on(e,t){let i=this.bindingRef++;return this.bindings.push({event:e,ref:i,callback:t}),i}off(e,t){this.bindings=this.bindings.filter(i=>!(i.event===e&&(typeof t>"u"||t===i.ref)))}canPush(){return this.socket.isConnected(Line truncated
`),()=>this.onerror("timeout"),n=>{!n||n.status!==200?(this.awaitingBatchAck=!1,this.onerror(n&&n.status),this.closeAndRetry(1011,"internal server error",!1)):i<e.length?this.batchSend(e,i):this.batchBuffer.length>0?(this.batchSend(this.batchBuffer),this.batchBuffer=[]):this.awaitingBatchAck=!1})}close(e,t,i){for(let n of this.reqs)n.abort();this.readyState=Y.closed;let s=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:i});this.batchBuffer=[],clearTimeout(this.currentBatchTimer),this.currentBatchTimer=null,typeof CloseEvent<"u"?this.onclose(new CloseEvent("close",s)):this.onclose(s)}ajax(e,t,i,s,n){let r,o=()=>{this.reqs.delete(r),s()};r=at.request(e,this.endpointURL(),t,i,this.timeout,o,a=>{this.reqs.delete(r),this.isActive()&&n(a)}),this.reqs.add(r)}};var ot={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(e,t){if(e.payload.constructor===ArrayBuffer)return t(this.binaryEncode(e));{let i=[e.join_ref,e.ref,e.topic,e.event,e.payload];return t(JSON.stringify(i))}},decode(e,t){if(e.constructor===ArrayBuffer)return t(this.binaryDecode(e));{let[i,s,n,r,o]=JSON.parse(e);return t({join_ref:i,ref:s,topic:n,event:r,payload:o})}},binaryEncode(e){let{join_ref:t,ref:i,event:s,topic:n,payload:r}=e,o=new TextEncoder,a=o.encode(t),l=o.encode(i),h=o.encode(n),d=o.encode(s);this.assertFieldSize(a.byteLength,"join_ref"),this.assertFieldSize(l.byteLength,"ref"),this.assertFieldSize(h.byteLength,"topic"),this.assertFieldSize(d.byteLength,"event");let p=this.META_LENGTH+a.byteLength+l.byteLength+h.byteLength+d.byteLength,m=new ArrayBuffer(this.HEADER_LENGTH+p),g=new Uint8Array(m),u=new DataView(m),v=0;u.setUint8(v++,this.KINDS.push),u.setUint8(v++,a.byteLength),u.setUint8(v++,l.byteLength),u.setUint8(v++,h.byteLength),u.setUint8(v++,d.byteLength),g.set(a,v),v+=a.byteLength,g.set(l,v),v+=l.byteLength,g.set(h,v),v+=h.byteLength,g.set(d,v),v+=d.byteLength;var y=new Uint8Array(m.byteLength+r.byteLength);return y.set(g,0),y.set(new Uint8Array(r),m.byteLength),y.buffer},assertFieldSize(e,t){if(e>255)throw new Error(`unable to convert ${t} to binary: must be less than or equal to 255 bytes, but is ${e} bytes`)},binaryDecode(e){let t=new DataView(e),i=t.getUint8(0),s=new TextDecoder;switch(i){case this.KINDS.push:return this.decodePush(e,t,s);case this.KINDS.reply:return this.decodeReply(e,t,s);case this.KINDS.broadcast:return this.decodeBroadcast(e,t,s)}},decodePush(e,t,i){let s=t.getUint8(1),n=t.getUint8(2),r=t.getUint8(3),o=this.HEADER_LENGTH+this.META_LENGTH-1,a=i.decode(e.slice(o,o+s));o=o+s;let l=i.decode(e.slice(o,o+n));o=o+n;let h=i.decode(e.slice(o,o+r));o=o+r;let d=e.slice(o,e.byteLength);return{join_ref:a,ref:null,topic:l,event:h,payload:d}},decodeReply(e,t,i){let s=t.getUint8(1),n=t.getUint8(2),r=t.getUint8(3),o=t.getUint8(4),a=this.HEADER_LENGTH+this.META_LENGTH,l=i.decode(e.slice(a,a+s));a=a+s;let h=i.decode(e.slice(a,a+n));a=a+n;let d=i.decode(e.slice(a,a+r));a=a+r;let p=i.decode(e.slice(a,a+o));a=a+o;let m=e.slice(a,e.byteLength),g={status:p,response:m};return{join_ref:l,ref:h,topic:d,event:re.reply,payload:g}},decodeBroadcast(e,t,i){let s=t.getUint8(1),n=t.getUint8(2),r=this.HEADER_LENGTH+2,o=i.decode(e.slice(r,r+s));r=r+s;let a=i.decode(e.slice(r,r+n));r=r+n;let l=e.slice(r,e.byteLength);return{join_ref:null,ref:null,topic:o,event:a,payload:l}}},_i=class{constructor(e,t={}){this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.fallbackRef=null,this.timeout=t.timeout||yn,this.transport=t.transport||G.WebSocket||Pe,this.primaryPassedHealthCheck=!1,this.longPollFallbackMs=t.longPollFallbackMs,this.fallbackTimer=null,this.sessionStore=t.sessionStorage||G&&G.sessionStorage,this.establishedConnections=0,this.defaultEncoder=ot.encode.bind(ot),this.defaultDecoder=ot.decode.bind(ot),this.closeWasClean=!0,this.disconnecting=!1,this.binaryType=t.binaryType||"arraybuffer",this.connectClock=1,this.pageHidden=!1,this.transport!==Pe?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let i=null;Re&&Re.addEventListener&&(Re.addEventListener("pagehide",s=>{this.conn&&(this.disconnect(),i=this.connectClock)}),Re.addEventListener("pageshow",s=>{i===this.connectClock&&(i=null,this.connect())}),Re.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?this.pageHidden=!0:(this.pageHidden=!1,!this.isConnected()&&!this.closeWasClean&&this.teardown(()=>this.connect()))})),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.rejoinAfterMs=s=>t.rejoinAfterMs?t.rejoinAfterMs(s):[1e3,2e3,5e3][s-1]||1e4,this.reconnectAfterMs=s=>t.reconnectAfterMs?t.reconnectAfterMs(s):[10,50,100,150,200,250,500,1e3,2e3][s-1]||5e3,this.logger=t.logger||null,!this.logger&&t.debug&&(this.logger=(s,n,r)=>{console.log(`${s}: ${n}`,r)}),this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=Be(t.params||{}),this.endPoint=`${e}Line truncated
hook attached to non-connected DOM element
ensure you are calling createHook within your connectedCallback. ${e.outerHTML}
`),this.putPrivate(e,"custom-el-hook",t)},getCustomElHook(e){return this.private(e,"custom-el-hook")},isUsedInput(e){return e.nodeType===Node.ELEMENT_NODE&&(this.private(e,yt)||this.private(e,Ye))},resetForm(e){Array.from(e.elements).forEach(t=>{this.deletePrivate(t,yt),this.deletePrivate(t,Ye)})},isPhxChild(e){return e.getAttribute&&e.getAttribute(Ae)},isPhxSticky(e){return e.getAttribute&&e.getAttribute(Jt)!==null},isChildOfAny(e,t){return!!t.find(i=>i.contains(e))},firstPhxChild(e){return this.isPhxChild(e)?e:this.all(e,`[${Ae}]`)[0]},isPortalTemplate(e){return e.tagName==="TEMPLATE"&&e.hasAttribute(ei)},closestViewEl(e){let t=e.closest(`[${ke}],${Ze}`);return t?t.hasAttribute(ke)?this.byId(t.getAttribute(ke)):t.hasAttribute(te)?t:null:null},dispatchEvent(e,t,i={}){let s=!0;e.nodeName==="INPUT"&&e.type==="file"&&t==="click"&&(s=!1);let o={bubbles:i.bubbles===void 0?s:!!i.bubbles,cancelable:!0,detail:i.detail||{}},a=t==="click"?new MouseEvent("click",o):new CustomEvent(t,o);e.dispatchEvent(a)},cloneNode(e,t){if(typeof t>"u")return e.cloneNode(!0);{let i=e.cloneNode(!1);return i.innerHTML=t,i}},mergeAttrs(e,t,i={}){let s=new Set(i.exclude||[]),n=i.isIgnored,r=t.attributes;for(let a=r.length-1;a>=0;a--){let l=r[a].name;if(s.has(l)){if(l==="value"){let h=t.value??t.getAttribute(l);e.value===h&&e.setAttribute("value",t.getAttribute(l))}}else{let h=t.getAttribute(l);e.getAttribute(l)!==h&&(!n||n&&l.startsWith("data-"))&&e.setAttribute(l,h)}}let o=e.attributes;for(let a=o.length-1;a>=0;a--){let l=o[a].name;n?l.startsWith("data-")&&!t.hasAttribute(l)&&!$i.includes(l)&&e.removeAttribute(l):t.hasAttribute(l)||e.removeAttribute(l)}},mergeFocusedInput(e,t){e instanceof HTMLSelectElement||we.mergeAttrs(e,t,{exclude:["value"]}),t.readOnly?e.setAttribute("readonly",!0):e.removeAttribute("readonly")},hasSelectionRange(e){return e.setSelectionRange&&(e.type==="text"||e.type==="textarea")},restoreFocus(e,t,i){if(e instanceof HTMLSelectElement&&e.focus(),!we.isTextualInput(e))return;e.matches(":focus")||e.focus(),this.hasSelectionRange(e)&&e.setSelectionRange(t,i)},isFormInput(e){return e.localName&&customElements.get(e.localName)?customElements.get(e.localName).formAssociated:/^(?:input|select|textarea)$/i.test(e.tagName)&&e.type!=="button"},syncAttrsToProps(e){e instanceof HTMLInputElement&&os.indexOf(e.type.toLocaleLowerCase())>=0&&(e.checked=e.getAttribute("checked")!==null)},isTextualInput(e){return In.indexOf(e.type)>=0},isNowTriggerFormExternal(e,t){return e.getAttribute&&e.getAttribute(t)!==null&&document.body.contains(e)},cleanChildNodes(e,t){if(we.isPhxUpdate(e,t,["append","prepend",gt])){let i=[];e.childNodes.forEach(s=>{s.id||(!(s.nodeType===Node.TEXT_NODE&&s.nodeValue.trim()==="")&&s.nodeType!==Node.COMMENT_NODE&&I(`only HTML element tags with an id are allowed inside containers with phx-update.
`),this.putPrivate(e,"custom-el-hook",t)},getCustomElHook(e){return this.private(e,"custom-el-hook")},isUsedInput(e){return e.nodeType===Node.ELEMENT_NODE&&(this.private(e,yt)||this.private(e,Ye))},resetForm(e){Array.from(e.elements).forEach(t=>{this.deletePrivate(t,yt),this.deletePrivate(t,Ye)})},isPhxChild(e){return e.getAttribute&&e.getAttribute(Ae)},isPhxSticky(e){return e.getAttribute&&e.getAttribute(Jt)!==null},isChildOfAny(e,t){return!!t.find(i=>i.contains(e))},firstPhxChild(e){return this.isPhxChild(e)?e:this.all(e,`[${Ae}]`)[0]},isPortalTemplate(e){return e.tagName==="TEMPLATE"&&e.hasAttribute(ei)},closestViewEl(e){let t=e.closest(`[${ke}],${Ze}`);return t?t.hasAttribute(ke)?this.byId(t.getAttribute(ke)):t.hasAttribute(te)?t:null:null},dispatchEvent(e,t,i={}){let s=!0;e.nodeName==="INPUT"&&e.type==="file"&&t==="click"&&(s=!1);let o={bubbles:i.bubbles===void 0?s:!!i.bubbles,cancelable:!0,detail:i.detail||{}},a=t==="click"?new MouseEvent("click",o):new CustomEvent(t,o);e.dispatchEvent(a)},cloneNode(e,t){if(typeof t>"u")return e.cloneNode(!0);{let i=e.cloneNode(!1);return i.innerHTML=t,i}},mergeAttrs(e,t,i={}){let s=new Set(i.exclude||[]),n=i.isIgnored,r=t.attributes;for(let a=r.length-1;a>=0;a--){let l=r[a].name;if(s.has(l)){if(l==="value"){let h=t.value??t.getAttribute(l);e.value===h&&e.setAttribute("value",t.getAttribute(l))}}else{let h=t.getAttribute(l);e.getAttribute(l)!==h&&(!n||n&&l.startsWith("data-"))&&e.setAttribute(l,h)}}let o=e.attributes;for(let a=o.length-1;a>=0;a--){let l=o[a].name;n?l.startsWith("data-")&&!t.hasAttribute(l)&&!$i.includes(l)&&e.removeAttribute(l):t.hasAttribute(l)||e.removeAttribute(l)}},mergeFocusedInput(e,t){e instanceof HTMLSelectElement||we.mergeAttrs(e,t,{exclude:["value"]}),t.readOnly?e.setAttribute("readonly",!0):e.removeAttribute("readonly")},hasSelectionRange(e){return e.setSelectionRange&&(e.type==="text"||e.type==="textarea")},restoreFocus(e,t,i){if(e instanceof HTMLSelectElement&&e.focus(),!we.isTextualInput(e))return;e.matches(":focus")||e.focus(),this.hasSelectionRange(e)&&e.setSelectionRange(t,i)},isFormInput(e){return e.localName&&customElements.get(e.localName)?customElements.get(e.localName).formAssociated:/^(?:input|select|textarea)$/i.test(e.tagName)&&e.type!=="button"},syncAttrsToProps(e){e instanceof HTMLInputElement&&os.indexOf(e.type.toLocaleLowerCase())>=0&&(e.checked=e.getAttribute("checked")!==null)},isTextualInput(e){return Dn.indexOf(e.type)>=0},isNowTriggerFormExternal(e,t){return e.getAttribute&&e.getAttribute(t)!==null&&document.body.contains(e)},cleanChildNodes(e,t){if(we.isPhxUpdate(e,t,["append","prepend",gt])){let i=[];e.childNodes.forEach(s=>{s.id||(!(s.nodeType===Node.TEXT_NODE&&s.nodeValue.trim()==="")&&s.nodeType!==Node.COMMENT_NODE&&I(`only HTML element tags with an id are allowed inside containers with phx-update.
removing illegal node: "${(s.outerHTML||s.nodeValue).trim()}"
`),i.push(s))}),i.forEach(s=>s.remove())}},replaceRootContainer(e,t,i){let s=new Set(["id",te,Se,Qt,ae]);if(e.tagName.toLowerCase()===t.toLowerCase())return Array.from(e.attributes).filter(n=>!s.has(n.name.toLowerCase())).forEach(n=>e.removeAttribute(n.name)),Object.keys(i).filter(n=>!s.has(n.toLowerCase())).forEach(n=>e.setAttribute(n,i[n])),e;{let n=document.createElement(t);return Object.keys(i).forEach(r=>n.setAttribute(r,i[r])),s.forEach(r=>n.setAttribute(r,e.getAttribute(r))),n.innerHTML=e.innerHTML,e.replaceWith(n),n}},getSticky(e,t,i){let s=(we.private(e,"sticky")||[]).find(([n])=>t===n);if(s){let[n,r,o]=s;return o}else return typeof i=="function"?i():i},deleteSticky(e,t){this.updatePrivate(e,"sticky",[],i=>i.filter(([s,n])=>s!==t))},putSticky(e,t,i){let s=i(e);this.updatePrivate(e,"sticky",[],n=>{let r=n.findIndex(([o])=>t===o);return r>=0?n[r]=[t,i,s]:n.push([t,i,s]),n})},applyStickyOperations(e){let t=we.private(e,"sticky");t&&t.forEach(([i,s,n])=>this.putSticky(e,i,s))},isLocked(e){return e.hasAttribute&&e.hasAttribute(M)},attributeIgnored(e,t){return t.some(i=>e.name==i||i==="*"||i.includes("*")&&e.name.match(i)!=null)}},c=we,Xe=class{static isActive(e,t){let i=t._phxRef===void 0,n=e.getAttribute(Wt).split(",").indexOf(N.genFileRef(t))>=0;return t.size>0&&(i||n)}static isPreflighted(e,t){return e.getAttribute(Zt).split(",").indexOf(N.genFileRef(t))>=0&&this.isActive(e,t)}static isPreflightInProgress(e){return e._preflightInProgress===!0}static markPreflightInProgress(e){e._preflightInProgress=!0}constructor(e,t,i,s){this.ref=N.genFileRef(t),this.fileEl=e,this.file=t,this.view=i,this.meta=null,this._isCancelled=!1,this._isDone=!1,this._progress=0,this._lastProgressSent=-1,this._onDone=function(){},this._onElUpdated=this.onElUpdated.bind(this),this.fileEl.addEventListener(mt,this._onElUpdated),this.autoUpload=s}metadata(){return this.meta}progress(e){this._progress=Math.floor(e),this._progress>this._lastProgressSent&&(this._progress>=100?(this._progress=100,this._lastProgressSent=100,this._isDone=!0,this.view.pushFileProgress(this.fileEl,this.ref,100,()=>{N.untrackFile(this.fileEl,this.file),this._onDone()})):(this._lastProgressSent=this._progress,this.view.pushFileProgress(this.fileEl,this.ref,this._progress)))}isCancelled(){return this._isCancelled}cancel(){this.file._preflightInProgress=!1,this._isCancelled=!0,this._isDone=!0,this._onDone()}isDone(){return this._isDone}error(e="failed"){this.fileEl.removeEventListener(mt,this._onElUpdated),this.view.pushFileProgress(this.fileEl,this.ref,{error:e}),this.isAutoUpload()||N.clearFiles(this.fileEl)}isAutoUpload(){return this.autoUpload}onDone(e){this._onDone=()=>{this.fileEl.removeEventListener(mt,this._onElUpdated),e()}}onElUpdated(){this.fileEl.getAttribute(Wt).split(",").indexOf(this.ref)===-1&&(N.untrackFile(this.fileEl,this.file),this.cancel())}toPreflightPayload(){return{last_modified:this.file.lastModified,name:this.file.name,relative_path:this.file.webkitRelativePath,size:this.file.size,type:this.file.type,ref:this.ref,meta:typeof this.file.meta=="function"?this.file.meta():void 0}}uploader(e){if(this.meta.uploader){let t=e[this.meta.uploader]||I(`no uploader configured for ${this.meta.uploader}`);return{name:this.meta.uploader,callback:t}}else return{name:"channel",callback:Xn}}zipPostFlight(e){this.meta=e.entries[this.ref],this.meta||I(`no preflight upload response returned with ref ${this.ref}`,{input:this.fileEl,response:e})}},Zn=0,N=class Xt{static genFileRef(t){let i=t._phxRef;return i!==void 0?i:(t._phxRef=(Zn++).toString(),t._phxRef)}static getEntryDataURL(t,i,s){let n=this.activeFiles(t).find(r=>this.genFileRef(r)===i);s(URL.createObjectURL(n))}static hasUploadsInProgress(t){let i=0;return c.findUploadInputs(t).forEach(s=>{s.getAttribute(Zt)!==s.getAttribute(Pn)&&i++}),i>0}static serializeUploads(t){let i=this.activeFiles(t),s={};return i.forEach(n=>{let r={path:t.name},o=t.getAttribute(le);s[o]=s[o]||[],r.ref=this.genFileRef(n),r.last_modified=n.lastModified,r.name=n.name||r.ref,r.relative_path=n.webkitRelativePath,r.type=n.type,r.size=n.size,typeof n.meta=="function"&&(r.meta=n.meta()),s[o].push(r)}),s}static clearFiles(t){t.value=null,t.removeAttribute(le),c.putPrivate(t,"files",[])}static untrackFile(t,i){c.putPrivate(t,"files",c.private(t,"files").filter(s=>!Object.is(s,i)))}static trackFiles(t,i,s){if(t.getAttribute("multiple")!==null){let n=i.filter(r=>!this.activeFiles(t).find(o=>Object.is(o,r)));c.updatePrivate(t,"files",[],r=>r.concat(n)),t.value=null}else s&&s.files.length>0&&(t.files=s.files),c.putPrivate(t,"files",i)}static activeFileInputs(t){let i=c.findUploadInputs(t);return Array.from(i).filter(s=>s.files&&this.activeFiles(s).length>0)}static activeFiles(t){return(c.private(t,"files")||[]).filter(i=>Xe.isActive(t,i))}static inputsAwaitingPreflight(t){let i=c.findUploadInputs(t);return Array.from(i).filter(s=>this.filesAwaitingPreflight(s).length>0)}static filesAwaitingPreflight(t){return this.activeFiles(t).filter Line truncated
`,w)})),v.length>0&&i.time("post-morph append/prepend restoration",()=>{v.forEach(w=>w.perform())}),i.silenceEvents(()=>c.restoreFocus(o,a,l)),c.dispatchEvent(document,"phx:update"),g.forEach(w=>this.trackAfter("added",w)),u.forEach(w=>this.trackAfter("updated",w)),this.transitionPendingRemoves(),L){i.unload();let w=c.private(L,"submitter");if(w&&w.name&&r.contains(w)){let k=document.createElement("input");k.type="hidden";let T=w.getAttribute("form");T&&k.setAttribute("form",T),k.name=w.name,k.value=w.value,w.parentElement.insertBefore(k,w)}Object.getPrototypeOf(L).submit.call(L)}return!0}onNodeDiscarded(e){(c.isPhxChild(e)||c.isPhxSticky(e))&&this.liveSocket.destroyViewByEl(e),this.trackAfter("discarded",e)}maybePendingRemove(e){return e.getAttribute&&e.getAttribute(this.phxRemove)!==null?(this.pendingRemoves.push(e),!0):!1}removeStreamChildElement(e,t=!1){!t&&!this.view.ownsElement(e)||(this.streamInserts[e.id]?(this.streamComponentRestore[e.id]=e,e.remove()):this.maybePendingRemove(e)||(e.remove(),this.onNodeDiscarded(e)))}getStreamInsert(e){return(e.id?this.streamInserts[e.id]:{})||{}}setStreamRef(e,t){c.putSticky(e,qe,i=>i.setAttribute(qe,t))}maybeReOrderStream(e,t){let{ref:i,streamAt:s,reset:n}=this.getStreamInsert(e);if(s!==void 0&&(this.setStreamRef(e,i),!(!n&&!t)&&e.parentElement)){if(s===0)e.parentElement.insertBefore(e,e.parentElement.firstElementChild);else if(s>0){let r=Array.from(e.parentElement.children),o=r.indexOf(e);if(s>=r.length-1)e.parentElement.appendChild(e);else{let a=r[s];o>s?e.parentElement.insertBefore(e,a):e.parentElement.insertBefore(e,a.nextElementSibling)}}this.maybeLimitStream(e)}}maybeLimitStream(e){let{limit:t}=this.getStreamInsert(e),i=t!==null&&Array.from(e.parentElement.children);t&&t<0&&i.length>t*-1?i.slice(0,i.length+t).forEach(s=>this.removeStreamChildElement(s)):t&&t>=0&&i.length>t&&i.slice(t).forEach(s=>this.removeStreamChildElement(s))}transitionPendingRemoves(){let{pendingRemoves:e,liveSocket:t}=this;e.length>0&&t.transitionRemoves(e,()=>{e.forEach(i=>{let s=c.firstPhxChild(i);s&&t.destroyViewByEl(s),i.remove()}),this.trackAfter("transitionsDiscarded",e)})}isChangedSelect(e,t){return!(e instanceof HTMLSelectElement)||e.multiple?!1:e.options.length!==t.options.length?!0:(t.value=e.value,!e.isEqualNode(t))}isCIDPatch(){return this.cidPatch}skipCIDSibling(e){return e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute(ns)}targetCIDContainer(e){if(!this.isCIDPatch())return;let[t,...i]=c.findComponentNodeList(this.view.id,this.targetCID);return i.length===0&&c.childNodeLength(e)===1?t:t&&t.parentNode}indexOf(e,t){return Array.from(e.children).indexOf(t)}teleport(e,t){let i=e.getAttribute(ei),s=document.querySelector(i);if(!s)throw new Error("portal target with selector "+i+" not found");let n=e.content.firstElementChild;if(this.skipCIDSibling(n))return;if(!n?.id)throw new Error("phx-portal template must have a single root element with ID!");let r=document.getElementById(n.id),o;r?(s.contains(r)||s.appendChild(r),o=r):(o=document.createElement(n.tagName),s.appendChild(o)),n.setAttribute(ke,this.view.id),n.setAttribute(me,e.id),t(o,n,!0),n.removeAttribute(ke),n.removeAttribute(me),this.view.pushPortalElementId(n.id)}handleRuntimeHook(e,t){let i=e.getAttribute(vt),s=e.hasAttribute("nonce")?e.getAttribute("nonce"):null;if(e.hasAttribute("nonce")){let r=document.createElement("template");r.innerHTML=t,s=r.content.querySelector(`script[${vt}="${CSS.escape(i)}"]`).getAttribute("nonce")}let n=document.createElement("script");n.textContent=e.textContent,c.mergeAttrs(n,e,{isIgnored:!1}),s&&(n.nonce=s),e.replaceWith(n),e=n}},vr=new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),br=new Set(["'",'"']),Gi=(e,t,i)=>{let s=0,n=!1,r,o,a,l,h,d,p=e.match(/^(\s*(?:<!--.*?-->\s*)*)<([^\s\/>]+)/);if(p===null)throw new Error(`malformed html ${e}`);for(s=p[0].length,r=p[1],a=p[2],l=s,s;s<e.length&&e.charAt(s)!==">";s++)if(e.charAt(s)==="="){let u=e.slice(s-3,s)===" id";s++;let v=e.charAt(s);if(br.has(v)){let y=s;for(s++,s;s<e.length&&e.charAt(s)!==v;s++);if(u){h=e.slice(y+1,s);break}}}let m=e.length-1;for(n=!1;m>=r.length+a.length;){let u=e.charAt(m);if(n)u==="-"&&e.slice(m-3,m)==="<!-"?(n=!1,m-=4):m-=1;else if(u===">"&&e.slice(m-2,m)==="--")n=!0,m-=3;else{if(u===">")break;m-=1}}o=e.slice(m+1,e.length);let g=Object.keys(t).map(u=>t[u]===!0?u:`${u}="${t[u]}"`).join(" ");if(i){let u=h?` id="${h}"`:"";vr.has(a)?d=`<${a}${u}${g===""?"":" "}${g}/>`:d=`<${a}${u}${g===""?"":" "}${g}></${a}>`}else{let u=e.slice(l,m+1);d=`<${a}${g===""?"":" "}${g}${u}`}return[d,r,o]},Yi=class{static extract(e){let{[Ui]:t,[Fi]:i,[ji]:s}=e;return delete e[Ui],delete e[Fi],delete e[ji],{diff:e,title:s,reply:t||null,events:i||[]}}constructor(e,t){this.viewId=e,this.rendered={},this.magicId=0,this.mergeDiff(t)}parentViewId(){return this.viewId}toString(e){let{buffer:t,streams:i}=this.recursiveToString(this.rendered,this.rendered[F],e,!0,{});return{buffeLine truncated
`),i.push(s))}),i.forEach(s=>s.remove())}},replaceRootContainer(e,t,i){let s=new Set(["id",te,Se,Qt,ae]);if(e.tagName.toLowerCase()===t.toLowerCase())return Array.from(e.attributes).filter(n=>!s.has(n.name.toLowerCase())).forEach(n=>e.removeAttribute(n.name)),Object.keys(i).filter(n=>!s.has(n.toLowerCase())).forEach(n=>e.setAttribute(n,i[n])),e;{let n=document.createElement(t);return Object.keys(i).forEach(r=>n.setAttribute(r,i[r])),s.forEach(r=>n.setAttribute(r,e.getAttribute(r))),n.innerHTML=e.innerHTML,e.replaceWith(n),n}},getSticky(e,t,i){let s=(we.private(e,"sticky")||[]).find(([n])=>t===n);if(s){let[n,r,o]=s;return o}else return typeof i=="function"?i():i},deleteSticky(e,t){this.updatePrivate(e,"sticky",[],i=>i.filter(([s,n])=>s!==t))},putSticky(e,t,i){let s=i(e);this.updatePrivate(e,"sticky",[],n=>{let r=n.findIndex(([o])=>t===o);return r>=0?n[r]=[t,i,s]:n.push([t,i,s]),n})},applyStickyOperations(e){let t=we.private(e,"sticky");t&&t.forEach(([i,s,n])=>this.putSticky(e,i,s))},isLocked(e){return e.hasAttribute&&e.hasAttribute(M)},attributeIgnored(e,t){return t.some(i=>e.name==i||i==="*"||i.includes("*")&&e.name.match(i)!=null)}},c=we,Xe=class{static isActive(e,t){let i=t._phxRef===void 0,n=e.getAttribute(Wt).split(",").indexOf(N.genFileRef(t))>=0;return t.size>0&&(i||n)}static isPreflighted(e,t){return e.getAttribute(Zt).split(",").indexOf(N.genFileRef(t))>=0&&this.isActive(e,t)}static isPreflightInProgress(e){return e._preflightInProgress===!0}static markPreflightInProgress(e){e._preflightInProgress=!0}constructor(e,t,i,s){this.ref=N.genFileRef(t),this.fileEl=e,this.file=t,this.view=i,this.meta=null,this._isCancelled=!1,this._isDone=!1,this._progress=0,this._lastProgressSent=-1,this._onDone=function(){},this._onElUpdated=this.onElUpdated.bind(this),this.fileEl.addEventListener(mt,this._onElUpdated),this.autoUpload=s}metadata(){return this.meta}progress(e){this._progress=Math.floor(e),this._progress>this._lastProgressSent&&(this._progress>=100?(this._progress=100,this._lastProgressSent=100,this._isDone=!0,this.view.pushFileProgress(this.fileEl,this.ref,100,()=>{N.untrackFile(this.fileEl,this.file),this._onDone()})):(this._lastProgressSent=this._progress,this.view.pushFileProgress(this.fileEl,this.ref,this._progress)))}isCancelled(){return this._isCancelled}cancel(){this.file._preflightInProgress=!1,this._isCancelled=!0,this._isDone=!0,this._onDone()}isDone(){return this._isDone}error(e="failed"){this.fileEl.removeEventListener(mt,this._onElUpdated),this.view.pushFileProgress(this.fileEl,this.ref,{error:e}),this.isAutoUpload()||N.clearFiles(this.fileEl)}isAutoUpload(){return this.autoUpload}onDone(e){this._onDone=()=>{this.fileEl.removeEventListener(mt,this._onElUpdated),e()}}onElUpdated(){this.fileEl.getAttribute(Wt).split(",").indexOf(this.ref)===-1&&(N.untrackFile(this.fileEl,this.file),this.cancel())}toPreflightPayload(){return{last_modified:this.file.lastModified,name:this.file.name,relative_path:this.file.webkitRelativePath,size:this.file.size,type:this.file.type,ref:this.ref,meta:typeof this.file.meta=="function"?this.file.meta():void 0}}uploader(e){if(this.meta.uploader){let t=e[this.meta.uploader]||I(`no uploader configured for ${this.meta.uploader}`);return{name:this.meta.uploader,callback:t}}else return{name:"channel",callback:Gn}}zipPostFlight(e){this.meta=e.entries[this.ref],this.meta||I(`no preflight upload response returned with ref ${this.ref}`,{input:this.fileEl,response:e})}},Qn=0,N=class Xt{static genFileRef(t){let i=t._phxRef;return i!==void 0?i:(t._phxRef=(Qn++).toString(),t._phxRef)}static getEntryDataURL(t,i,s){let n=this.activeFiles(t).find(r=>this.genFileRef(r)===i);s(URL.createObjectURL(n))}static hasUploadsInProgress(t){let i=0;return c.findUploadInputs(t).forEach(s=>{s.getAttribute(Zt)!==s.getAttribute(Rn)&&i++}),i>0}static serializeUploads(t){let i=this.activeFiles(t),s={};return i.forEach(n=>{let r={path:t.name},o=t.getAttribute(le);s[o]=s[o]||[],r.ref=this.genFileRef(n),r.last_modified=n.lastModified,r.name=n.name||r.ref,r.relative_path=n.webkitRelativePath,r.type=n.type,r.size=n.size,typeof n.meta=="function"&&(r.meta=n.meta()),s[o].push(r)}),s}static clearFiles(t){t.value=null,t.removeAttribute(le),c.putPrivate(t,"files",[])}static untrackFile(t,i){c.putPrivate(t,"files",c.private(t,"files").filter(s=>!Object.is(s,i)))}static trackFiles(t,i,s){if(t.getAttribute("multiple")!==null){let n=i.filter(r=>!this.activeFiles(t).find(o=>Object.is(o,r)));c.updatePrivate(t,"files",[],r=>r.concat(n)),t.value=null}else s&&s.files.length>0&&(t.files=s.files),c.putPrivate(t,"files",i)}static activeFileInputs(t){let i=c.findUploadInputs(t);return Array.from(i).filter(s=>s.files&&this.activeFiles(s).length>0)}static activeFiles(t){return(c.private(t,"files")||[]).filter(i=>Xe.isActive(t,i))}static inputsAwaitingPreflight(t){let i=c.findUploadInputs(t);return Array.from(i).filter(s=>this.filesAwaitingPreflight(s).length>0)}static filesAwaitingPreflight(t){return this.activeFiles(t).filter Line truncated
`,w)})),v.length>0&&i.time("post-morph append/prepend restoration",()=>{v.forEach(w=>w.perform())}),i.silenceEvents(()=>c.restoreFocus(o,a,l)),c.dispatchEvent(document,"phx:update"),g.forEach(w=>this.trackAfter("added",w)),u.forEach(w=>this.trackAfter("updated",w)),this.transitionPendingRemoves(),L){i.unload();let w=c.private(L,"submitter");if(w&&w.name&&r.contains(w)){let k=document.createElement("input");k.type="hidden";let T=w.getAttribute("form");T&&k.setAttribute("form",T),k.name=w.name,k.value=w.value,w.parentElement.insertBefore(k,w)}Object.getPrototypeOf(L).submit.call(L)}return!0}onNodeDiscarded(e){(c.isPhxChild(e)||c.isPhxSticky(e))&&this.liveSocket.destroyViewByEl(e),this.trackAfter("discarded",e)}maybePendingRemove(e){return e.getAttribute&&e.getAttribute(this.phxRemove)!==null?(this.pendingRemoves.push(e),!0):!1}removeStreamChildElement(e,t=!1){!t&&!this.view.ownsElement(e)||(this.streamInserts[e.id]?(this.streamComponentRestore[e.id]=e,e.remove()):this.maybePendingRemove(e)||(e.remove(),this.onNodeDiscarded(e)))}getStreamInsert(e){return(e.id?this.streamInserts[e.id]:{})||{}}setStreamRef(e,t){c.putSticky(e,qe,i=>i.setAttribute(qe,t))}maybeReOrderStream(e,t){let{ref:i,streamAt:s,reset:n}=this.getStreamInsert(e);if(s!==void 0&&(this.setStreamRef(e,i),!(!n&&!t)&&e.parentElement)){if(s===0)e.parentElement.insertBefore(e,e.parentElement.firstElementChild);else if(s>0){let r=Array.from(e.parentElement.children),o=r.indexOf(e);if(s>=r.length-1)e.parentElement.appendChild(e);else{let a=r[s];o>s?e.parentElement.insertBefore(e,a):e.parentElement.insertBefore(e,a.nextElementSibling)}}this.maybeLimitStream(e)}}maybeLimitStream(e){let{limit:t}=this.getStreamInsert(e),i=t!==null&&Array.from(e.parentElement.children);t&&t<0&&i.length>t*-1?i.slice(0,i.length+t).forEach(s=>this.removeStreamChildElement(s)):t&&t>=0&&i.length>t&&i.slice(t).forEach(s=>this.removeStreamChildElement(s))}transitionPendingRemoves(){let{pendingRemoves:e,liveSocket:t}=this;e.length>0&&t.transitionRemoves(e,()=>{e.forEach(i=>{let s=c.firstPhxChild(i);s&&t.destroyViewByEl(s),i.remove()}),this.trackAfter("transitionsDiscarded",e)})}isChangedSelect(e,t){return!(e instanceof HTMLSelectElement)||e.multiple?!1:e.options.length!==t.options.length?!0:(t.value=e.value,!e.isEqualNode(t))}isCIDPatch(){return this.cidPatch}skipCIDSibling(e){return e.nodeType===Node.ELEMENT_NODE&&e.hasAttribute(ns)}targetCIDContainer(e){if(!this.isCIDPatch())return;let[t,...i]=c.findComponentNodeList(this.view.id,this.targetCID);return i.length===0&&c.childNodeLength(e)===1?t:t&&t.parentNode}indexOf(e,t){return Array.from(e.children).indexOf(t)}teleport(e,t){let i=e.getAttribute(ei),s=document.querySelector(i);if(!s)throw new Error("portal target with selector "+i+" not found");let n=e.content.firstElementChild;if(this.skipCIDSibling(n))return;if(!n?.id)throw new Error("phx-portal template must have a single root element with ID!");let r=document.getElementById(n.id),o;r?(s.contains(r)||s.appendChild(r),o=r):(o=document.createElement(n.tagName),s.appendChild(o)),n.setAttribute(ke,this.view.id),n.setAttribute(me,e.id),t(o,n,!0),n.removeAttribute(ke),n.removeAttribute(me),this.view.pushPortalElementId(n.id)}handleRuntimeHook(e,t){let i=e.getAttribute(vt),s=e.hasAttribute("nonce")?e.getAttribute("nonce"):null;if(e.hasAttribute("nonce")){let r=document.createElement("template");r.innerHTML=t,s=r.content.querySelector(`script[${vt}="${CSS.escape(i)}"]`).getAttribute("nonce")}let n=document.createElement("script");n.textContent=e.textContent,c.mergeAttrs(n,e,{isIgnored:!1}),s&&(n.nonce=s),e.replaceWith(n),e=n}},br=new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),yr=new Set(["'",'"']),Gi=(e,t,i)=>{let s=0,n=!1,r,o,a,l,h,d,p=e.match(/^(\s*(?:<!--.*?-->\s*)*)<([^\s\/>]+)/);if(p===null)throw new Error(`malformed html ${e}`);for(s=p[0].length,r=p[1],a=p[2],l=s,s;s<e.length&&e.charAt(s)!==">";s++)if(e.charAt(s)==="="){let u=e.slice(s-3,s)===" id";s++;let v=e.charAt(s);if(yr.has(v)){let y=s;for(s++,s;s<e.length&&e.charAt(s)!==v;s++);if(u){h=e.slice(y+1,s);break}}}let m=e.length-1;for(n=!1;m>=r.length+a.length;){let u=e.charAt(m);if(n)u==="-"&&e.slice(m-3,m)==="<!-"?(n=!1,m-=4):m-=1;else if(u===">"&&e.slice(m-2,m)==="--")n=!0,m-=3;else{if(u===">")break;m-=1}}o=e.slice(m+1,e.length);let g=Object.keys(t).map(u=>t[u]===!0?u:`${u}="${t[u]}"`).join(" ");if(i){let u=h?` id="${h}"`:"";br.has(a)?d=`<${a}${u}${g===""?"":" "}${g}/>`:d=`<${a}${u}${g===""?"":" "}${g}></${a}>`}else{let u=e.slice(l,m+1);d=`<${a}${g===""?"":" "}${g}${u}`}return[d,r,o]},Yi=class{static extract(e){let{[Ui]:t,[Fi]:i,[ji]:s}=e;return delete e[Ui],delete e[Fi],delete e[ji],{diff:e,title:s,reply:t||null,events:i||[]}}constructor(e,t){this.viewId=e,this.rendered={},this.magicId=0,this.mergeDiff(t)}parentViewId(){return this.viewId}toString(e){let{buffer:t,streams:i}=this.recursiveToString(this.rendered,this.rendered[F],e,!0,{});return{buffeLine truncated
An element can only ever be associated with a single view!
Please ensure that you are not trying to initialize multiple LiveSockets on the same page.
This could happen if you're accidentally trying to render your root layout more than once.
Ensure that the template set on the LiveView is different than the root layout.
`,{view:o}),new Error("Cannot bind multiple views to the same DOM element.");c.putPrivate(this.el,"view",this),this.id=this.el.id,this.el.setAttribute(ae,this.root.id),this.ref=0,this.lastAckRef=null,this.childJoins=0,this.loaderTimer=null,this.disconnectedTimer=null,this.pendingDiffs=[],this.pendingForms=new Set,this.redirect=!1,this.href=null,this.joinCount=this.parent?this.parent.joinCount-1:0,this.joinAttempts=0,this.joinPending=!0,this.destroyed=!1,this.joinCallback=function(a){a&&a()},this.stopCallback=function(){},this.pendingJoinOps=[],this.viewHooks={},this.formSubmits=[],this.children=this.parent?null:{},this.root.children[this.id]={},this.formsForRecovery={},this.channel=this.liveSocket.channel(`lv:${this.id}`,()=>{let a=this.href&&this.expandURL(this.href);return{redirect:this.redirect?a:void 0,url:this.redirect?void 0:a||void 0,params:this.connectParams(r),session:this.getSession(),static:this.getStatic(),flash:this.flash,sticky:this.el.hasAttribute(Jt)}}),this.portalElementIds=new Set}setHref(t){this.href=t}setRedirect(t){this.redirect=!0,this.href=t}isMain(){return this.el.hasAttribute(Qt)}connectParams(t){let i=this.liveSocket.params(this.el),s=c.all(document,`[${this.binding(_n)}]`).map(n=>n.src||n.href).filter(n=>typeof n=="string");return s.length>0&&(i._track_static=s),i._mounts=this.joinCount,i._mount_attempts=this.joinAttempts,i._live_referer=t,this.joinAttempts++,i}isConnected(){return this.channel.canPush()}getSession(){return this.el.getAttribute(te)}getStatic(){let t=this.el.getAttribute(Se);return t===""?null:t}destroy(t=function(){}){this.destroyAllChildren(),this.destroyPortalElements(),this.destroyed=!0,c.deletePrivate(this.el,"view"),delete this.root.children[this.id],this.parent&&delete this.root.children[this.parent.id][this.id],clearTimeout(this.loaderTimer);let i=()=>{t();for(let s in this.viewHooks)this.destroyHook(this.viewHooks[s])};c.markPhxChildDestroyed(this.el),this.log("destroyed",()=>["the child has been removed from the parent"]),this.channel.leave().receive("ok",i).receive("error",i).receive("timeout",i)}setContainerClasses(...t){this.el.classList.remove(Ri,be,Le,Li,Ve),this.el.classList.add(...t)}showLoader(t){if(clearTimeout(this.loaderTimer),t)this.loaderTimer=setTimeout(()=>this.showLoader(),t);else{for(let i in this.viewHooks)this.viewHooks[i].__disconnected();this.setContainerClasses(be)}}execAll(t){c.all(this.el,`[${t}]`,i=>this.liveSocket.execJS(i,i.getAttribute(t)))}hideLoader(){clearTimeout(this.loaderTimer),clearTimeout(this.disconnectedTimer),this.setContainerClasses(Ri),this.execAll(this.binding("connected"))}triggerReconnected(){for(let t in this.viewHooks)this.viewHooks[t].__reconnected()}log(t,i){this.liveSocket.log(this,t,i)}transition(t,i,s=function(){}){this.liveSocket.transition(t,i,s)}withinTargets(t,i,s=document){if(t instanceof HTMLElement||t instanceof SVGElement)return this.liveSocket.owner(t,n=>i(n,t));if(oe(t))c.findComponentNodeList(this.id,t,s).length===0?I(`no component found matching phx-target of ${t}`):i(this,parseInt(t));else{let n=Array.from(s.querySelectorAll(t));n.length===0&&I(`nothing found matching the phx-target selector "${t}"`),n.forEach(r=>this.liveSocket.owner(r,o=>i(o,r)))}}applyDiff(t,i,s){this.log(t,()=>["",bt(i)]);let{diff:n,reply:r,events:o,title:a}=Yi.extract(i),l=o.reduce((d,p)=>(p.length===3&&p[2]==!0?d.pre.push(p.slice(0,-1)):d.post.push(p),d),{pre:[],post:[]});this.liveSocket.dispatchEvents(l.pre);let h=()=>{s({diff:n,reply:r,events:l.post}),(typeof a=="string"||t=="mount"&&this.isMain())&&window.requestAnimationFrame(()=>c.putTitle(a))};"onDocumentPatch"in this.liveSocket.domCallbacks?this.liveSocket.triggerDOM("onDocumentPatch",[h]):h()}onJoin(t){let{rendered:i,container:s,liveview_version:n,pid:r}=t;if(s){let[o,a]=s;this.el=c.replaceRootContainer(this.el,o,a)}this.childJoins=0,this.joinPending=!0,this.flash=null,this.root===this&&(this.formsForRecovery=this.getFormsForRecovery()),this.isMain()&&window.history.state===null&&B.pushState("replace",{type:"patch",id:this.id,position:this.liveSocket.currentHistoryPosition}),n!==this.liveSocket.version()&&console.warn(`LiveView asset version mismatch. JavaScript version ${this.liveSocket.version()} vs. server ${n}. To avoid issues, please ensure that your assets use the same version as the server.`),r&&this.el.setAttribute(Mn,r),B.dropLocal(this.liveSocket.localStorage,window.location.pathname,ts),this.applyDiff("mount",i,({diff:o,events:a})=>{this.rendered=new Yi(this.id,o);let[l,h]=this.renderContainer(null,"join");this.dropPendingRefs(),this.joinCount++,this.joinAttempts=0,this.maybeRecoverForms(l,()=>{this.onJoinComplete(t,l,h,a)})})}dropPendingRefs(){c.all(document,`[${J}="${this.refSrc()}"]`,t=>{t.removeAttribute(Ne),t.removeAttribute(J),t.removeAttribute(M)})}onJoinComplete({live_patch:t},i,s,n){if(this.joinCount>1||this.parent&&!this.parent.isJoinPending())return this.applyJoinPatch(t,i,s,n);c.findPhxChildrenInFragment(i,this.id).filter(o=>{let a= Line truncated
`,{view:o}),new Error("Cannot bind multiple views to the same DOM element.");c.putPrivate(this.el,"view",this),this.id=this.el.id,this.el.setAttribute(ae,this.root.id),this.ref=0,this.lastAckRef=null,this.childJoins=0,this.loaderTimer=null,this.disconnectedTimer=null,this.pendingDiffs=[],this.pendingForms=new Set,this.redirect=!1,this.href=null,this.joinCount=this.parent?this.parent.joinCount-1:0,this.joinAttempts=0,this.joinPending=!0,this.destroyed=!1,this.joinCallback=function(a){a&&a()},this.stopCallback=function(){},this.pendingJoinOps=[],this.viewHooks={},this.formSubmits=[],this.children=this.parent?null:{},this.root.children[this.id]={},this.formsForRecovery={},this.channel=this.liveSocket.channel(`lv:${this.id}`,()=>{let a=this.href&&this.expandURL(this.href);return{redirect:this.redirect?a:void 0,url:this.redirect?void 0:a||void 0,params:this.connectParams(r),session:this.getSession(),static:this.getStatic(),flash:this.flash,sticky:this.el.hasAttribute(Jt)}}),this.portalElementIds=new Set}setHref(t){this.href=t}setRedirect(t){this.redirect=!0,this.href=t}isMain(){return this.el.hasAttribute(Qt)}connectParams(t){let i=this.liveSocket.params(this.el),s=c.all(document,`[${this.binding(xn)}]`).map(n=>n.src||n.href).filter(n=>typeof n=="string");return s.length>0&&(i._track_static=s),i._mounts=this.joinCount,i._mount_attempts=this.joinAttempts,i._live_referer=t,this.joinAttempts++,i}isConnected(){return this.channel.canPush()}getSession(){return this.el.getAttribute(te)}getStatic(){let t=this.el.getAttribute(Se);return t===""?null:t}destroy(t=function(){}){this.destroyAllChildren(),this.destroyPortalElements(),this.destroyed=!0,c.deletePrivate(this.el,"view"),delete this.root.children[this.id],this.parent&&delete this.root.children[this.parent.id][this.id],clearTimeout(this.loaderTimer);let i=()=>{t();for(let s in this.viewHooks)this.destroyHook(this.viewHooks[s])};c.markPhxChildDestroyed(this.el),this.log("destroyed",()=>["the child has been removed from the parent"]),this.channel.leave().receive("ok",i).receive("error",i).receive("timeout",i)}setContainerClasses(...t){this.el.classList.remove(Ri,be,Le,Li,Ve),this.el.classList.add(...t)}showLoader(t){if(clearTimeout(this.loaderTimer),t)this.loaderTimer=setTimeout(()=>this.showLoader(),t);else{for(let i in this.viewHooks)this.viewHooks[i].__disconnected();this.setContainerClasses(be)}}execAll(t){c.all(this.el,`[${t}]`,i=>this.liveSocket.execJS(i,i.getAttribute(t)))}hideLoader(){clearTimeout(this.loaderTimer),clearTimeout(this.disconnectedTimer),this.setContainerClasses(Ri),this.execAll(this.binding("connected"))}triggerReconnected(){for(let t in this.viewHooks)this.viewHooks[t].__reconnected()}log(t,i){this.liveSocket.log(this,t,i)}transition(t,i,s=function(){}){this.liveSocket.transition(t,i,s)}withinTargets(t,i,s=document){if(t instanceof HTMLElement||t instanceof SVGElement)return this.liveSocket.owner(t,n=>i(n,t));if(oe(t))c.findComponentNodeList(this.id,t,s).length===0?I(`no component found matching phx-target of ${t}`):i(this,parseInt(t));else{let n=Array.from(s.querySelectorAll(t));n.length===0&&I(`nothing found matching the phx-target selector "${t}"`),n.forEach(r=>this.liveSocket.owner(r,o=>i(o,r)))}}applyDiff(t,i,s){this.log(t,()=>["",bt(i)]);let{diff:n,reply:r,events:o,title:a}=Yi.extract(i),l=o.reduce((d,p)=>(p.length===3&&p[2]==!0?d.pre.push(p.slice(0,-1)):d.post.push(p),d),{pre:[],post:[]});this.liveSocket.dispatchEvents(l.pre);let h=()=>{s({diff:n,reply:r,events:l.post}),(typeof a=="string"||t=="mount"&&this.isMain())&&window.requestAnimationFrame(()=>c.putTitle(a))};"onDocumentPatch"in this.liveSocket.domCallbacks?this.liveSocket.triggerDOM("onDocumentPatch",[h]):h()}onJoin(t){let{rendered:i,container:s,liveview_version:n,pid:r}=t;if(s){let[o,a]=s;this.el=c.replaceRootContainer(this.el,o,a)}this.childJoins=0,this.joinPending=!0,this.flash=null,this.root===this&&(this.formsForRecovery=this.getFormsForRecovery()),this.isMain()&&window.history.state===null&&B.pushState("replace",{type:"patch",id:this.id,position:this.liveSocket.currentHistoryPosition}),n!==this.liveSocket.version()&&console.warn(`LiveView asset version mismatch. JavaScript version ${this.liveSocket.version()} vs. server ${n}. To avoid issues, please ensure that your assets use the same version as the server.`),r&&this.el.setAttribute(Hn,r),B.dropLocal(this.liveSocket.localStorage,window.location.pathname,ts),this.applyDiff("mount",i,({diff:o,events:a})=>{this.rendered=new Yi(this.id,o);let[l,h]=this.renderContainer(null,"join");this.dropPendingRefs(),this.joinCount++,this.joinAttempts=0,this.maybeRecoverForms(l,()=>{this.onJoinComplete(t,l,h,a)})})}dropPendingRefs(){c.all(document,`[${J}="${this.refSrc()}"]`,t=>{t.removeAttribute(Ne),t.removeAttribute(J),t.removeAttribute(M)})}onJoinComplete({live_patch:t},i,s,n){if(this.joinCount>1||this.parent&&!this.parent.isJoinPending())return this.applyJoinPatch(t,i,s,n);c.findPhxChildrenInFragment(i,this.id).filter(o=>{let a= Line truncated
a phoenix Socket must be provided as the second argument to the LiveSocket constructor. For example:
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
let liveSocket = new LiveSocket("/live", Socket, {...})
`);this.socket=new t(e,i),this.bindingPrefix=i.bindingPrefix||jn,this.opts=i,this.params=ze(i.params||{}),this.viewLogger=i.viewLogger,this.metadataCallbacks=i.metadata||{},this.defaults=Object.assign(bt(Vn),i.defaults||{}),this.prevActive=null,this.silenced=!1,this.main=null,this.outgoingMainEl=null,this.clickStartedAtTarget=null,this.linkRef=1,this.roots={},this.href=window.location.href,this.pendingLink=null,this.currentLocation=bt(window.location),this.hooks=i.hooks||{},this.uploaders=i.uploaders||{},this.loaderTimeout=i.loaderTimeout||$n,this.disconnectedTimeout=i.disconnectedTimeout||Un,this.reloadWithJitterTimer=null,this.maxReloads=i.maxReloads||An,this.reloadJitterMin=i.reloadJitterMin||kn,this.reloadJitterMax=i.reloadJitterMax||Tn,this.failsafeJitter=i.failsafeJitter||Cn,this.localStorage=i.localStorage||window.localStorage,this.sessionStorage=i.sessionStorage||window.sessionStorage,this.boundTopLevelEvents=!1,this.boundEventNames=new Set,this.blockPhxChangeWhileComposing=i.blockPhxChangeWhileComposing||!1,this.serverCloseRef=null,this.domCallbacks=Object.assign({jsQuerySelectorAll:null,onPatchStart:ze(),onPatchEnd:ze(),onNodeAdded:ze(),onBeforeElUpdated:ze()},i.dom||{}),this.transitions=new kr,this.currentHistoryPosition=parseInt(this.sessionStorage.getItem(ct))||0,window.addEventListener("pagehide",s=>{this.unloaded=!0}),this.socket.onOpen(()=>{this.isUnloaded()&&window.location.reload()})}version(){return"1.1.28"}isProfileEnabled(){return this.sessionStorage.getItem(Ft)==="true"}isDebugEnabled(){return this.sessionStorage.getItem(ht)==="true"}isDebugDisabled(){return this.sessionStorage.getItem(ht)==="false"}enableDebug(){this.sessionStorage.setItem(ht,"true")}enableProfiling(){this.sessionStorage.setItem(Ft,"true")}disableDebug(){this.sessionStorage.setItem(ht,"false")}disableProfiling(){this.sessionStorage.removeItem(Ft)}enableLatencySim(e){this.enableDebug(),console.log("latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable"),this.sessionStorage.setItem(Ut,e)}disableLatencySim(){this.sessionStorage.removeItem(Ut)}getLatencySim(){let e=this.sessionStorage.getItem(Ut);return e?parseInt(e):null}getSocket(){return this.socket}connect(){window.location.hostname==="localhost"&&!this.isDebugDisabled()&&this.enableDebug();let e=()=>{this.resetReloadStatus(),this.joinRootViews()?(this.bindTopLevelEvents(),this.socket.connect()):this.main?this.socket.connect():this.bindTopLevelEvents({dead:!0}),this.joinDeadView()};["complete","loaded","interactive"].indexOf(document.readyState)>=0?e():document.addEventListener("DOMContentLoaded",()=>e())}disconnect(e){clearTimeout(this.reloadWithJitterTimer),this.serverCloseRef&&(this.socket.off(this.serverCloseRef),this.serverCloseRef=null),this.socket.disconnect(e)}replaceTransport(e){clearTimeout(this.reloadWithJitterTimer),this.socket.replaceTransport(e),this.connect()}execJS(e,t,i=null){let s=new CustomEvent("phx:exec",{detail:{sourceElement:e}});this.owner(e,n=>P.exec(s,i,t,n,e))}js(){return hs(this,"js")}unload(){this.unloaded||(this.main&&this.isConnected()&&this.log(this.main,"socket",()=>["disconnect for page nav"]),this.unloaded=!0,this.destroyAllViews(),this.disconnect())}triggerDOM(e,t){this.domCallbacks[e](...t)}time(e,t){if(!this.isProfileEnabled()||!console.time)return t();console.time(e);let i=t();return console.timeEnd(e),i}log(e,t,i){if(this.viewLogger){let[s,n]=i();this.viewLogger(e,t,s,n)}else if(this.isDebugEnabled()){let[s,n]=i();Jn(e,t,s,n)}}requestDOMUpdate(e){this.transitions.after(e)}asyncTransition(e){this.transitions.addAsyncTransition(e)}transition(e,t,i=function(){}){this.transitions.addTransition(e,t,i)}onChannel(e,t,i){e.on(t,s=>{let n=this.getLatencySim();n?setTimeout(()=>i(s),n):i(s)})}reloadWithJitter(e,t){clearTimeout(this.reloadWithJitterTimer),this.disconnect();let i=this.reloadJitterMin,s=this.reloadJitterMax,n=Math.floor(Math.random()*(s-i+1))+i,r=B.updateLocal(this.localStorage,window.location.pathname,ts,0,o=>o+1);r>=this.maxReloads&&(n=this.failsafeJitter),this.reloadWithJitterTimer=setTimeout(()=>{e.isDestroyed()||e.isConnected()||(e.destroy(),t?t():this.log(e,"join",()=>[`encountered ${r} consecutive reloads`]),r>=this.maxReloads&&this.log(e,"join",()=>[`exceeded ${this.maxReloads} consecutive reloads. Entering failsafe mode`]),this.hasPendingLink()?window.location=this.pendingLink:window.location.reload())},n)}getHookDefinition(e){if(e)return this.maybeInternalHook(e)||this.hooks[e]||this.maybeRuntimeHook(e)}maybeInternalHook(e){return e&&e.startsWith("Phoenix.")&&ir[e.split(".")[1]]}maybeRuntimeHook(e){let t=document.querySelector(`script[${vt}="${CSS.escape(e)}"]`);if(!t)return;let i=window[`phx_hook_${e}`];if(!i||typeof i!="function"){I("a runtime hook must be a function",t);return}let s=i();if(s&&(typeof s=="object"||typeof s=="function"))return s;I("runtime hook must return an object with hook callbacks or an instance of ViewHook",t)}isUnloaded(){return this.u Line truncated
`);this.socket=new t(e,i),this.bindingPrefix=i.bindingPrefix||Bn,this.opts=i,this.params=ze(i.params||{}),this.viewLogger=i.viewLogger,this.metadataCallbacks=i.metadata||{},this.defaults=Object.assign(bt(Wn),i.defaults||{}),this.prevActive=null,this.silenced=!1,this.main=null,this.outgoingMainEl=null,this.clickStartedAtTarget=null,this.linkRef=1,this.roots={},this.href=window.location.href,this.pendingLink=null,this.currentLocation=bt(window.location),this.hooks=i.hooks||{},this.uploaders=i.uploaders||{},this.loaderTimeout=i.loaderTimeout||Fn,this.disconnectedTimeout=i.disconnectedTimeout||jn,this.reloadWithJitterTimer=null,this.maxReloads=i.maxReloads||kn,this.reloadJitterMin=i.reloadJitterMin||Tn,this.reloadJitterMax=i.reloadJitterMax||Cn,this.failsafeJitter=i.failsafeJitter||_n,this.localStorage=i.localStorage||window.localStorage,this.sessionStorage=i.sessionStorage||window.sessionStorage,this.boundTopLevelEvents=!1,this.boundEventNames=new Set,this.blockPhxChangeWhileComposing=i.blockPhxChangeWhileComposing||!1,this.serverCloseRef=null,this.domCallbacks=Object.assign({jsQuerySelectorAll:null,onPatchStart:ze(),onPatchEnd:ze(),onNodeAdded:ze(),onBeforeElUpdated:ze()},i.dom||{}),this.transitions=new Tr,this.currentHistoryPosition=parseInt(this.sessionStorage.getItem(ct))||0,window.addEventListener("pagehide",s=>{this.unloaded=!0}),this.socket.onOpen(()=>{this.isUnloaded()&&window.location.reload()})}version(){return"1.1.28"}isProfileEnabled(){return this.sessionStorage.getItem(Ft)==="true"}isDebugEnabled(){return this.sessionStorage.getItem(ht)==="true"}isDebugDisabled(){return this.sessionStorage.getItem(ht)==="false"}enableDebug(){this.sessionStorage.setItem(ht,"true")}enableProfiling(){this.sessionStorage.setItem(Ft,"true")}disableDebug(){this.sessionStorage.setItem(ht,"false")}disableProfiling(){this.sessionStorage.removeItem(Ft)}enableLatencySim(e){this.enableDebug(),console.log("latency simulator enabled for the duration of this browser session. Call disableLatencySim() to disable"),this.sessionStorage.setItem(Ut,e)}disableLatencySim(){this.sessionStorage.removeItem(Ut)}getLatencySim(){let e=this.sessionStorage.getItem(Ut);return e?parseInt(e):null}getSocket(){return this.socket}connect(){window.location.hostname==="localhost"&&!this.isDebugDisabled()&&this.enableDebug();let e=()=>{this.resetReloadStatus(),this.joinRootViews()?(this.bindTopLevelEvents(),this.socket.connect()):this.main?this.socket.connect():this.bindTopLevelEvents({dead:!0}),this.joinDeadView()};["complete","loaded","interactive"].indexOf(document.readyState)>=0?e():document.addEventListener("DOMContentLoaded",()=>e())}disconnect(e){clearTimeout(this.reloadWithJitterTimer),this.serverCloseRef&&(this.socket.off(this.serverCloseRef),this.serverCloseRef=null),this.socket.disconnect(e)}replaceTransport(e){clearTimeout(this.reloadWithJitterTimer),this.socket.replaceTransport(e),this.connect()}execJS(e,t,i=null){let s=new CustomEvent("phx:exec",{detail:{sourceElement:e}});this.owner(e,n=>P.exec(s,i,t,n,e))}js(){return hs(this,"js")}unload(){this.unloaded||(this.main&&this.isConnected()&&this.log(this.main,"socket",()=>["disconnect for page nav"]),this.unloaded=!0,this.destroyAllViews(),this.disconnect())}triggerDOM(e,t){this.domCallbacks[e](...t)}time(e,t){if(!this.isProfileEnabled()||!console.time)return t();console.time(e);let i=t();return console.timeEnd(e),i}log(e,t,i){if(this.viewLogger){let[s,n]=i();this.viewLogger(e,t,s,n)}else if(this.isDebugEnabled()){let[s,n]=i();zn(e,t,s,n)}}requestDOMUpdate(e){this.transitions.after(e)}asyncTransition(e){this.transitions.addAsyncTransition(e)}transition(e,t,i=function(){}){this.transitions.addTransition(e,t,i)}onChannel(e,t,i){e.on(t,s=>{let n=this.getLatencySim();n?setTimeout(()=>i(s),n):i(s)})}reloadWithJitter(e,t){clearTimeout(this.reloadWithJitterTimer),this.disconnect();let i=this.reloadJitterMin,s=this.reloadJitterMax,n=Math.floor(Math.random()*(s-i+1))+i,r=B.updateLocal(this.localStorage,window.location.pathname,ts,0,o=>o+1);r>=this.maxReloads&&(n=this.failsafeJitter),this.reloadWithJitterTimer=setTimeout(()=>{e.isDestroyed()||e.isConnected()||(e.destroy(),t?t():this.log(e,"join",()=>[`encountered ${r} consecutive reloads`]),r>=this.maxReloads&&this.log(e,"join",()=>[`exceeded ${this.maxReloads} consecutive reloads. Entering failsafe mode`]),this.hasPendingLink()?window.location=this.pendingLink:window.location.reload())},n)}getHookDefinition(e){if(e)return this.maybeInternalHook(e)||this.hooks[e]||this.maybeRuntimeHook(e)}maybeInternalHook(e){return e&&e.startsWith("Phoenix.")&&sr[e.split(".")[1]]}maybeRuntimeHook(e){let t=document.querySelector(`script[${vt}="${CSS.escape(e)}"]`);if(!t)return;let i=window[`phx_hook_${e}`];if(!i||typeof i!="function"){I("a runtime hook must be a function",t);return}let s=i();if(s&&(typeof s=="object"||typeof s=="function"))return s;I("runtime hook must return an object with hook callbacks or an instance of ViewHook",t)}isUnloaded(){return this.u Line truncated
`)&&!this._prevInputValue.includes(`
`)){t.value=t.value.replace(/\n/g,""),this._prevInputValue=t.value,this.stickToBottom=!0,this.autoResize(),this._submitChat();return}this._enterKeyHandled=!1,this._prevInputValue=t.value,this.stickToBottom=!0,this.autoResize()},this.handleKeyDown=e=>{e.target.closest(".chat-input")&&e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),this._enterKeyHandled=!0,this._submitChat())},this.el.addEventListener("input",this.handleInput),this.el.addEventListener("keydown",this.handleKeyDown),this.syncScrollContainer(),this.syncExpandedSurfaces(),this.surfaceObserver.observe(this.el,{childList:!0,subtree:!0}),this.autoResize(),window.requestAnimationFrame(()=>this.scrollToBottom(!0))},updated(){this.syncScrollContainer(),this.syncExpandedSurfaces(),this.autoResize(),window.requestAnimationFrame(()=>this.scrollToBottom())},destroyed(){this.surfaceObserver.disconnect(),this.el.removeEventListener("input",this.handleInput),this.el.removeEventListener("keydown",this.handleKeyDown),this.scrollContainer&&this.scrollContainer.removeEventListener("scroll",this.handleScroll)}};var Ds={mounted(){this._onClickAway=e=>{this.el.contains(e.target)||this.el.querySelector(".colour-picker-popover")?.classList.add("hidden")},document.addEventListener("mousedown",this._onClickAway),this._setupCustomInput()},updated(){this._setupCustomInput()},destroyed(){document.removeEventListener("mousedown",this._onClickAway)},_setupCustomInput(){let e=this.el.querySelector(".colour-picker-custom input");if(!e||e._cpBound)return;e._cpBound=!0;let t=()=>{let i=e.value.trim();if(i&&!i.startsWith("#")&&(i="#"+i),/^#[0-9a-fA-F]{6}$/.test(i)){let s=this.el.dataset.pickEvent;this.pushEventTo(this.el.dataset.target,s,{color:i}),this.el.querySelector(".colour-picker-popover")?.classList.add("hidden")}};e.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),t())}),e.addEventListener("blur",t)}};var Os={mounted(){this.dragItemId=null,this.dragSourceEl=null,this.dropTargetEl=null,this.dropPosition=null,this.clearDropTarget=()=>{this.dropTargetEl&&this.dropTargetEl.classList.remove("is-drop-before","is-drop-after","is-drop-inside"),this.dropTargetEl=null,this.dropPosition=null},this.setDropTarget=(e,t)=>{this.dropTargetEl===e&&this.dropPosition===t||(this.clearDropTarget(),this.dropTargetEl=e,this.dropPosition=t,e.classList.add(`is-drop-${t}`))},this.handleDragStart=e=>{let t=e.target.closest("[data-menu-drag-handle='true']"),i=e.target.closest("[data-menu-item-id]");!t||!i||!this.el.contains(i)||(this.dragItemId=i.dataset.menuItemId||null,this.dragSourceEl=i,i.classList.add("is-dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",this.dragItemId||"")))},this.handleDragOver=e=>{let t=e.target.closest("[data-menu-item-id]");if(!this.dragItemId||!t||!this.el.contains(t)){this.clearDropTarget();return}let i=t.dataset.menuItemId||"";if(!i||i===this.dragItemId){this.clearDropTarget();return}e.preventDefault();let s=t.getBoundingClientRect(),n=e.clientY-s.top,r=t.dataset.menuCanDropInside==="true",o=s.height*.3,a=s.height*.7,l=r&&n>=o&&n<=a?"inside":n<s.height/2?"before":"after";this.setDropTarget(t,l),e.dataTransfer&&(e.dataTransfer.dropEffect="move")},this.handleDrop=e=>{let t=e.target.closest("[data-menu-item-id]");if(!this.dragItemId||!t||!this.el.contains(t)||!this.dropPosition){this.clearDropTarget();return}e.preventDefault(),this.pushEvent("menu_editor_drop_item",{drag_item_id:this.dragItemId,target_item_id:t.dataset.menuItemId,position:this.dropPosition}),this.clearDropTarget()},this.handleDragLeave=e=>{let t=e.relatedTarget;this.dropTargetEl&&(!t||!this.dropTargetEl.contains(t))&&this.clearDropTarget()},this.handleDragEnd=()=>{this.dragSourceEl&&this.dragSourceEl.classList.remove("is-dragging"),this.dragItemId=null,this.dragSourceEl=null,this.clearDropTarget()},this.el.addEventListener("dragstart",this.handleDragStart),this.el.addEventListener("dragover",this.handleDragOver),this.el.addEventListener("drop",this.handleDrop),this.el.addEventListener("dragleave",this.handleDragLeave),this.el.addEventListener("dragend",this.handleDragEnd)},destroyed(){this.el.removeEventListener("dragstart",this.handleDragStart),this.el.removeEventListener("dragover",this.handleDragOver),this.el.removeEventListener("drop",this.handleDrop),this.el.removeEventListener("dragleave",this.handleDragLeave),this.el.removeEventListener("dragend",this.handleDragEnd)}};var Pr={ArrowLeft:"cursorLeft",ArrowRight:"cursorRight",ArrowUp:"cursorUp",ArrowDown:"cursorDown"},Rr=()=>{let e=globalThis.navigator?.userAgent||"";return e.includes("AppleWebKit")&&!e.includes("Chrome")&&!e.includes("Chromium")},Lr=e=>e instanceof HTMLTextAreaElement&&e.classList.contains("inputarea"),Ir=e=>{if(e?.altKey||e?.ctrlKey||e?.metaKey)return null;let t=Pr[e?.key];return t?e.shiftKey?`${t}Select`:t:null},Dr=(e,t)=>{let i=e.getSelections?e.getSelections():null;e.setValue(t),i&&i.length>0&&e.setSelections&&e.setSelections(i)},Or=(e,t)=>{if Line truncated
`)){t.value=t.value.replace(/\n/g,""),this._prevInputValue=t.value,this.stickToBottom=!0,this.autoResize(),this._submitChat();return}this._enterKeyHandled=!1,this._prevInputValue=t.value,this.stickToBottom=!0,this.autoResize()},this.handleKeyDown=e=>{e.target.closest(".chat-input")&&e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),this._enterKeyHandled=!0,this._submitChat())},this.el.addEventListener("input",this.handleInput),this.el.addEventListener("keydown",this.handleKeyDown),this.syncScrollContainer(),this.syncExpandedSurfaces(),this.surfaceObserver.observe(this.el,{childList:!0,subtree:!0}),this.autoResize(),window.requestAnimationFrame(()=>this.scrollToBottom(!0))},updated(){this.syncScrollContainer(),this.syncExpandedSurfaces(),this.autoResize(),window.requestAnimationFrame(()=>this.scrollToBottom())},destroyed(){this.surfaceObserver.disconnect(),this.el.removeEventListener("input",this.handleInput),this.el.removeEventListener("keydown",this.handleKeyDown),this.scrollContainer&&this.scrollContainer.removeEventListener("scroll",this.handleScroll)}};var Os={mounted(){this._onClickAway=e=>{this.el.contains(e.target)||this.el.querySelector(".colour-picker-popover")?.classList.add("hidden")},document.addEventListener("mousedown",this._onClickAway),this._setupCustomInput()},updated(){this._setupCustomInput()},destroyed(){document.removeEventListener("mousedown",this._onClickAway)},_setupCustomInput(){let e=this.el.querySelector(".colour-picker-custom input");if(!e||e._cpBound)return;e._cpBound=!0;let t=()=>{let i=e.value.trim();if(i&&!i.startsWith("#")&&(i="#"+i),/^#[0-9a-fA-F]{6}$/.test(i)){let s=this.el.dataset.pickEvent;this.pushEventTo(this.el.dataset.target,s,{color:i}),this.el.querySelector(".colour-picker-popover")?.classList.add("hidden")}};e.addEventListener("keydown",i=>{i.key==="Enter"&&(i.preventDefault(),t())}),e.addEventListener("blur",t)}};var Ms={mounted(){this.dragItemId=null,this.dragSourceEl=null,this.dropTargetEl=null,this.dropPosition=null,this.clearDropTarget=()=>{this.dropTargetEl&&this.dropTargetEl.classList.remove("is-drop-before","is-drop-after","is-drop-inside"),this.dropTargetEl=null,this.dropPosition=null},this.setDropTarget=(e,t)=>{this.dropTargetEl===e&&this.dropPosition===t||(this.clearDropTarget(),this.dropTargetEl=e,this.dropPosition=t,e.classList.add(`is-drop-${t}`))},this.handleDragStart=e=>{let t=e.target.closest("[data-menu-drag-handle='true']"),i=e.target.closest("[data-menu-item-id]");!t||!i||!this.el.contains(i)||(this.dragItemId=i.dataset.menuItemId||null,this.dragSourceEl=i,i.classList.add("is-dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",this.dragItemId||"")))},this.handleDragOver=e=>{let t=e.target.closest("[data-menu-item-id]");if(!this.dragItemId||!t||!this.el.contains(t)){this.clearDropTarget();return}let i=t.dataset.menuItemId||"";if(!i||i===this.dragItemId){this.clearDropTarget();return}e.preventDefault();let s=t.getBoundingClientRect(),n=e.clientY-s.top,r=t.dataset.menuCanDropInside==="true",o=s.height*.3,a=s.height*.7,l=r&&n>=o&&n<=a?"inside":n<s.height/2?"before":"after";this.setDropTarget(t,l),e.dataTransfer&&(e.dataTransfer.dropEffect="move")},this.handleDrop=e=>{let t=e.target.closest("[data-menu-item-id]");if(!this.dragItemId||!t||!this.el.contains(t)||!this.dropPosition){this.clearDropTarget();return}e.preventDefault(),this.pushEvent("menu_editor_drop_item",{drag_item_id:this.dragItemId,target_item_id:t.dataset.menuItemId,position:this.dropPosition}),this.clearDropTarget()},this.handleDragLeave=e=>{let t=e.relatedTarget;this.dropTargetEl&&(!t||!this.dropTargetEl.contains(t))&&this.clearDropTarget()},this.handleDragEnd=()=>{this.dragSourceEl&&this.dragSourceEl.classList.remove("is-dragging"),this.dragItemId=null,this.dragSourceEl=null,this.clearDropTarget()},this.el.addEventListener("dragstart",this.handleDragStart),this.el.addEventListener("dragover",this.handleDragOver),this.el.addEventListener("drop",this.handleDrop),this.el.addEventListener("dragleave",this.handleDragLeave),this.el.addEventListener("dragend",this.handleDragEnd)},destroyed(){this.el.removeEventListener("dragstart",this.handleDragStart),this.el.removeEventListener("dragover",this.handleDragOver),this.el.removeEventListener("drop",this.handleDrop),this.el.removeEventListener("dragleave",this.handleDragLeave),this.el.removeEventListener("dragend",this.handleDragEnd)}};var Rr={ArrowLeft:"cursorLeft",ArrowRight:"cursorRight",ArrowUp:"cursorUp",ArrowDown:"cursorDown"},Lr=()=>{let e=globalThis.navigator?.userAgent||"";return e.includes("AppleWebKit")&&!e.includes("Chrome")&&!e.includes("Chromium")},Ir=e=>e instanceof HTMLTextAreaElement&&e.classList.contains("inputarea"),Dr=e=>{if(e?.altKey||e?.ctrlKey||e?.metaKey)return null;let t=Rr[e?.key];return t?e.shiftKey?`${t}Select`:t:null},Or=(e,t)=>{let i=e.getSelections?e.getSelections():null;e.setValue(t),i&&i.length>0&&e.setSelections&&e.setSelections(i)},Mr=(e,t)=>{if Line truncated
`)?`
`:"",d=l!==""&&!t.endsWith(`
`)?`
`:"",p=`${h}${t}${d}`;this.editor.executeEdits("bds-insert-content",[{range:s,text:p,forceMoveMarkers:!0}]),this.editor.focus()},$e().then(async e=>{!this.host||!this.textarea||(await this.waitForMonacoVisibleSize(),ce(e),this.editor=e.editor.create(this.host,{value:this.textarea.value||"",language:this.language,theme:"bds-theme",automaticLayout:!0,minimap:{enabled:!1},scrollBeyondLastLine:!1,wordWrap:this.wordWrap,lineNumbers:"on",lineNumbersMinChars:3,fontSize:14,fontFamily:"'Cascadia Code', 'Consolas', 'Courier New', monospace",padding:{top:12,bottom:12},roundedSelection:!1,renderLineHighlight:"line",formatOnPaste:!0,cursorStyle:"line",cursorBlinking:"smooth",quickSuggestions:this.language!=="markdown-with-macros",tabSize:2,insertSpaces:!0}),As(this.editorId||this.el.id,this.editor),e.editor.setTheme("bds-theme"),this.syncEditorFromTextarea(),this.layoutEditorSoon(),this.changeSubscription=this.editor.onDidChangeModelContent(()=>{this.isApplyingRemoteUpdate||this.queueSync()}),this.insertEvent&&this.handleEvent(this.insertEvent,this.handleInsert),this.dropEvent&&(this.el.addEventListener("dragover",this.handleDragOver),this.el.addEventListener("drop",this.handleDrop)),Rr()&&this.host.addEventListener("keydown",this.handleWebKitTextAreaArrowKey,!0))}).catch(e=>{console.error("Failed to load Monaco editor",e)})},updated(){this.textarea=document.getElementById(this.el.dataset.monacoInputId)||this.el.querySelector("textarea"),this.host=this.el.querySelector(".monaco-editor-instance"),this.language=this.el.dataset.monacoLanguage||this.language||"plaintext",this.wordWrap=this.el.dataset.monacoWordWrap||this.wordWrap||"off",!(!this.editor||!this.textarea)&&($e().then(e=>{ce(e),e.editor.setTheme("bds-theme"),this.editor.getModel()?.getLanguageId()!==this.language&&e.editor.setModelLanguage(this.editor.getModel(),this.language),this.editor.updateOptions({wordWrap:this.wordWrap})}),this.syncEditorFromTextarea(),this.layoutEditorSoon())},destroyed(){window.clearTimeout(this.syncTimer),this.visibleSizeObserver?.disconnect(),this.changeSubscription?.dispose(),this.dropEvent&&(this.el.removeEventListener("dragover",this.handleDragOver),this.el.removeEventListener("drop",this.handleDrop)),this.host?.removeEventListener("keydown",this.handleWebKitTextAreaArrowKey,!0),ks(this.editorId||this.el.id),this.editor?.dispose()}};var Hs={mounted(){this.host=this.el.querySelector(".monaco-diff-editor-instance"),this.originalInput=this.el.querySelector(".monaco-diff-original"),this.modifiedInput=this.el.querySelector(".monaco-diff-modified"),this.filePath=this.el.dataset.monacoDiffFilePath||"working-tree",this.language=this.el.dataset.monacoDiffLanguage||"plaintext",this.viewStyle=this.el.dataset.monacoDiffViewStyle||"inline",this.wordWrap=this.el.dataset.monacoDiffWordWrap||"off",this.hideUnchanged=this.el.dataset.monacoDiffHideUnchanged==="true",this.readValues=()=>({original:this.originalInput?.value||"",modified:this.modifiedInput?.value||""}),this.applyDataset=()=>{this.filePath=this.el.dataset.monacoDiffFilePath||"working-tree",this.language=this.el.dataset.monacoDiffLanguage||"plaintext",this.viewStyle=this.el.dataset.monacoDiffViewStyle||"inline",this.wordWrap=this.el.dataset.monacoDiffWordWrap||"off",this.hideUnchanged=this.el.dataset.monacoDiffHideUnchanged==="true"},this.setModels=e=>{let t=this.readValues();this.originalModel?.dispose(),this.modifiedModel?.dispose(),this.originalModel=e.editor.createModel(t.original,this.language,e.Uri.parse(ci(this.filePath,"original"))),this.modifiedModel=e.editor.createModel(t.modified,this.language,e.Uri.parse(ci(this.filePath,"modified"))),this.editor.setModel({original:this.originalModel,modified:this.modifiedModel}),this.lastFilePath=this.filePath},$e().then(e=>{this.host&&(ce(e),this.editor=e.editor.createDiffEditor(this.host,{theme:"bds-theme",automaticLayout:!0,readOnly:!0,renderSideBySide:this.viewStyle==="side-by-side",minimap:{enabled:!1},scrollBeyondLastLine:!1,lineNumbers:"on",diffCodeLens:!1,originalEditable:!1,wordWrap:this.wordWrap,hideUnchangedRegions:{enabled:this.hideUnchanged},ignoreTrimWhitespace:!1}),this.setModels(e))}).catch(e=>{console.error("Failed to load Monaco diff editor",e)})},updated(){this.host=this.el.querySelector(".monaco-diff-editor-instance"),this.originalInput=this.el.querySelector(".monaco-diff-original"),this.modifiedInput=this.el.querySelector(".monaco-diff-modified"),this.applyDataset(),this.editor&&$e().then(e=>{if(ce(e),e.editor.setTheme("bds-theme"),this.editor.updateOptions({renderSideBySide:this.viewStyle==="side-by-side",wordWrap:this.wordWrap,hideUnchangedRegions:{enabled:this.hideUnchanged}}),this.lastFilePath!==this.filePath){this.setModels(e);return}let t=this.readValues();this.originalModel&&this.originalModel.getLanguageId()!==this.language&&e.editor.setModelLanguage(this.originalModel,this.language),this.modifiedModel&&this.modifiedModel.getLanguageId()!==this.language&&e.editor.setModelLanguage(this.modifiedModel,this.language Line truncated
`:"",p=`${h}${t}${d}`;this.editor.executeEdits("bds-insert-content",[{range:s,text:p,forceMoveMarkers:!0}]),this.editor.focus()},$e().then(async e=>{!this.host||!this.textarea||(await this.waitForMonacoVisibleSize(),ce(e),this.editor=e.editor.create(this.host,{value:this.textarea.value||"",language:this.language,theme:"bds-theme",automaticLayout:!0,minimap:{enabled:!1},scrollBeyondLastLine:!1,wordWrap:this.wordWrap,lineNumbers:"on",lineNumbersMinChars:3,fontSize:14,fontFamily:"'Cascadia Code', 'Consolas', 'Courier New', monospace",padding:{top:12,bottom:12},roundedSelection:!1,renderLineHighlight:"line",formatOnPaste:!0,cursorStyle:"line",cursorBlinking:"smooth",quickSuggestions:this.language!=="markdown-with-macros",tabSize:2,insertSpaces:!0}),As(this.editorId||this.el.id,this.editor),e.editor.setTheme("bds-theme"),this.syncEditorFromTextarea(),this.layoutEditorSoon(),this.changeSubscription=this.editor.onDidChangeModelContent(()=>{this.isApplyingRemoteUpdate||this.queueSync()}),this.insertEvent&&this.handleEvent(this.insertEvent,this.handleInsert),this.dropEvent&&(this.el.addEventListener("dragover",this.handleDragOver),this.el.addEventListener("drop",this.handleDrop)),Lr()&&this.host.addEventListener("keydown",this.handleWebKitTextAreaArrowKey,!0))}).catch(e=>{console.error("Failed to load Monaco editor",e)})},updated(){this.textarea=document.getElementById(this.el.dataset.monacoInputId)||this.el.querySelector("textarea"),this.host=this.el.querySelector(".monaco-editor-instance"),this.language=this.el.dataset.monacoLanguage||this.language||"plaintext",this.wordWrap=this.el.dataset.monacoWordWrap||this.wordWrap||"off",!(!this.editor||!this.textarea)&&($e().then(e=>{ce(e),e.editor.setTheme("bds-theme"),this.editor.getModel()?.getLanguageId()!==this.language&&e.editor.setModelLanguage(this.editor.getModel(),this.language),this.editor.updateOptions({wordWrap:this.wordWrap})}),this.syncEditorFromTextarea(),this.layoutEditorSoon())},destroyed(){window.clearTimeout(this.syncTimer),this.visibleSizeObserver?.disconnect(),this.changeSubscription?.dispose(),this.dropEvent&&(this.el.removeEventListener("dragover",this.handleDragOver),this.el.removeEventListener("drop",this.handleDrop)),this.host?.removeEventListener("keydown",this.handleWebKitTextAreaArrowKey,!0),ks(this.editorId||this.el.id),this.editor?.dispose()}};var Ns={mounted(){this.host=this.el.querySelector(".monaco-diff-editor-instance"),this.originalInput=this.el.querySelector(".monaco-diff-original"),this.modifiedInput=this.el.querySelector(".monaco-diff-modified"),this.filePath=this.el.dataset.monacoDiffFilePath||"working-tree",this.language=this.el.dataset.monacoDiffLanguage||"plaintext",this.viewStyle=this.el.dataset.monacoDiffViewStyle||"inline",this.wordWrap=this.el.dataset.monacoDiffWordWrap||"off",this.hideUnchanged=this.el.dataset.monacoDiffHideUnchanged==="true",this.readValues=()=>({original:this.originalInput?.value||"",modified:this.modifiedInput?.value||""}),this.applyDataset=()=>{this.filePath=this.el.dataset.monacoDiffFilePath||"working-tree",this.language=this.el.dataset.monacoDiffLanguage||"plaintext",this.viewStyle=this.el.dataset.monacoDiffViewStyle||"inline",this.wordWrap=this.el.dataset.monacoDiffWordWrap||"off",this.hideUnchanged=this.el.dataset.monacoDiffHideUnchanged==="true"},this.setModels=e=>{let t=this.readValues();this.originalModel?.dispose(),this.modifiedModel?.dispose(),this.originalModel=e.editor.createModel(t.original,this.language,e.Uri.parse(ci(this.filePath,"original"))),this.modifiedModel=e.editor.createModel(t.modified,this.language,e.Uri.parse(ci(this.filePath,"modified"))),this.editor.setModel({original:this.originalModel,modified:this.modifiedModel}),this.lastFilePath=this.filePath},$e().then(e=>{this.host&&(ce(e),this.editor=e.editor.createDiffEditor(this.host,{theme:"bds-theme",automaticLayout:!0,readOnly:!0,renderSideBySide:this.viewStyle==="side-by-side",minimap:{enabled:!1},scrollBeyondLastLine:!1,lineNumbers:"on",diffCodeLens:!1,originalEditable:!1,wordWrap:this.wordWrap,hideUnchangedRegions:{enabled:this.hideUnchanged},ignoreTrimWhitespace:!1}),this.setModels(e))}).catch(e=>{console.error("Failed to load Monaco diff editor",e)})},updated(){this.host=this.el.querySelector(".monaco-diff-editor-instance"),this.originalInput=this.el.querySelector(".monaco-diff-original"),this.modifiedInput=this.el.querySelector(".monaco-diff-modified"),this.applyDataset(),this.editor&&$e().then(e=>{if(ce(e),e.editor.setTheme("bds-theme"),this.editor.updateOptions({renderSideBySide:this.viewStyle==="side-by-side",wordWrap:this.wordWrap,hideUnchangedRegions:{enabled:this.hideUnchanged}}),this.lastFilePath!==this.filePath){this.setModels(e);return}let t=this.readValues();this.originalModel&&this.originalModel.getLanguageId()!==this.language&&e.editor.setModelLanguage(this.originalModel,this.language),this.modifiedModel&&this.modifiedModel.getLanguageId()!==this.language&&e.editor.setModelLanguage(this.modifiedModel,this.language Line truncated
+3
View File
@@ -47,6 +47,9 @@ for await (const line of rl) {
assistant_visible: !hasClass("[data-testid='assistant-shell']", "is-hidden"),
assistant_width: document.querySelector("[data-testid='assistant-shell']")?.getBoundingClientRect().width ?? 0,
panel_visible: !hasClass(".panel-shell", "is-hidden"),
panel_tabs_height: document.querySelector(".panel-tabs")?.getBoundingClientRect().height ?? 0,
panel_tab_labels: texts(".panel-tab", (node) => node.textContent.trim()),
panel_active_tab: text(".panel-tab.active"),
editor_title: text("[data-testid='editor-title']"),
activity_labels: texts("[data-testid='activity-button']", (node) => node.getAttribute("aria-label")),
sidebar_sections: texts("[data-testid='sidebar-section-title']", (node) => node.textContent.trim()),
+2
View File
@@ -249,6 +249,8 @@ invariant PanelTabFallback {
-- Tasks tab: last 10 tasks, newest first, with progress/cancel.
-- Tasks with shared group_id are collapsible groups showing aggregate progress.
-- Output tab: log entries with copy-all button.
-- The panel opens on Output automatically when a blogmark transform fails
-- or a transform script writes output.
-- Post Links tab: backlinks (posts linking here) + outlinks (posts linked from here).
-- Each entry clickable, opens linked post as pinned tab.
-- Git Log tab: file-level git history for active post/media (up to 50 entries).
+6
View File
@@ -110,6 +110,12 @@ surface ScriptRuntimeSurface {
-- Progress reporting is cooperative and flows through the supplied
-- progress sink rather than ambient global side effects.
@guarantee ScriptOutputRouting
-- print(…) calls and the explicit bds.app.log(…) API append lines to a
-- host-routed script output stream: the desktop app's Output panel,
-- stdout in the CLI, and the host logger when no sink is attached —
-- never the ambient console.
@guarantee BatchCancellation
-- Managed utility and transform jobs can be cancelled by the host
-- operator boundary.
+25
View File
@@ -129,6 +129,31 @@ defmodule BDS.Desktop.AutomationTest do
assert automation_process_counts() == baseline
end
@tag timeout: 120_000
test "cmd-J panel tab strip is visible and switches between tasks and output (issue #20)" do
{:ok, session} = Automation.start_session()
on_exit(fn ->
Automation.stop_session(session)
end)
assert :ok = Automation.press(session, "Meta+J")
snapshot = await(session, & &1.panel_visible)
assert snapshot.panel_visible == true
# The tab strip must offer both tabs and be tall enough to actually see
# and hit them — issue #20 was the strip collapsing to an unusable sliver.
assert "Tasks" in snapshot.panel_tab_labels
assert "Output" in snapshot.panel_tab_labels
assert snapshot.panel_tabs_height >= 20
assert :ok = Automation.click(session, "button[phx-value-tab='output']")
snapshot = await(session, &(&1.panel_active_tab == "Output"))
assert snapshot.panel_active_tab == "Output"
end
@tag timeout: 120_000
test "automation dispatches native menu actions into the liveview shell" do
{:ok, session} = Automation.start_session()
+146
View File
@@ -907,6 +907,120 @@ defmodule BDS.Desktop.ShellLiveTest do
assert html =~ ~s(data-tab-id="#{created_post.id}")
end
test "tasks panel shows a cancel button for running tasks and cancels them" do
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
{:ok, task} =
BDS.Tasks.submit_task("Long Running Task", fn _report ->
receive do
:finish -> :ok
after
30_000 -> :ok
end
end)
send(view.pid, :refresh_task_status)
html = render_click(view, "select_panel_tab", %{"tab" => "tasks"})
assert html =~ "Long Running Task"
assert html =~ ~s(data-testid="cancel-task-button")
view
|> element(~s{[data-testid="cancel-task-button"]})
|> render_click()
assert Enum.find(BDS.Tasks.list_tasks(), &(&1.id == task.id)).status == :cancelled
end
test "tasks panel groups tasks by group_id and toggles the group collapsed" do
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
blocking = fn _report ->
receive do
:finish -> :ok
after
30_000 -> :ok
end
end
{:ok, _t1} = BDS.Tasks.submit_task("First Grouped", blocking, %{group_id: "grp", group_name: "Batch"})
{:ok, _t2} = BDS.Tasks.submit_task("Second Grouped", blocking, %{group_id: "grp", group_name: "Batch"})
send(view.pid, :refresh_task_status)
html = render_click(view, "select_panel_tab", %{"tab" => "tasks"})
# One group row for both tasks, expanded by default (task names also
# appear in the status bar, hence the <strong> row scoping)
assert html =~ "Batch (2)"
assert html =~ "<strong>First Grouped</strong>"
assert html =~ "<strong>Second Grouped</strong>"
html = render_click(view, "toggle_task_group", %{"group" => "grp"})
assert html =~ "Batch (2)"
refute html =~ "<strong>First Grouped</strong>"
refute html =~ "<strong>Second Grouped</strong>"
html = render_click(view, "toggle_task_group", %{"group" => "grp"})
assert html =~ "<strong>First Grouped</strong>"
assert html =~ "<strong>Second Grouped</strong>"
end
test "output panel copy button pushes the full log text to the clipboard" do
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
send(view.pid, {:editor_output, "First", "line one", nil, "info"})
send(view.pid, {:editor_output, "Second", "line two", nil, "error"})
html = render_click(view, "select_panel_tab", %{"tab" => "output"})
assert html =~ ~s(data-testid="copy-output-button")
view
|> element(~s{[data-testid="copy-output-button"]})
|> render_click()
# Chronological order (oldest first), entries joined by a blank line.
assert_push_event(view, "clipboard", %{text: "line one\n\nline two"})
end
test "blogmark transform output lands in the output panel and auto-opens it", %{
project: project
} do
{:ok, _script} =
Scripts.create_and_publish_script(%{
project_id: project.id,
title: "Logging Transform",
kind: :transform,
entrypoint: "main",
content:
"function main(data, ctx) bds.app.log('transform ran') print('still ran') return data end"
})
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
url =
"bds2://new-post?title=" <>
URI.encode_www_form("Logged Blogmark") <>
"&url=" <> URI.encode_www_form("https://example.com/logged")
send(view.pid, {:blogmark_deep_link, url})
_html = render(view)
assigns = :sys.get_state(view.pid).socket.assigns
messages = Enum.map(assigns.output_entries, & &1.message)
assert "transform ran" in messages
assert "still ran" in messages
# Like the old app: noteworthy script output opens the panel on Output.
assert assigns.workbench.panel.visible == true
assert assigns.workbench.panel.active_tab == :output
end
test "blogmark deep link with a project_id switches to that project and imports there",
%{project: active} do
{:ok, other} =
@@ -6052,6 +6166,38 @@ defmodule BDS.Desktop.ShellLiveTest do
assert reloaded.version == 1
end
test "script editor run streams print and bds.app.log output to the output panel", %{
project: project
} do
{:ok, script} =
Scripts.create_script(%{
project_id: project.id,
title: "Output Test",
kind: :utility,
content:
"function main() print('from-print') bds.app.log('from-log') return 'done' end"
})
{:ok, view, _html} = live_isolated(build_conn(), BDS.Desktop.ShellLive)
render_click(view, "pin_sidebar_item", %{
"route" => "scripts",
"id" => script.id,
"title" => script.title,
"subtitle" => "draft"
})
view
|> element(".scripts-run-button")
|> render_click()
entries = :sys.get_state(view.pid).socket.assigns.output_entries
messages = Enum.map(entries, & &1.message)
assert "from-print" in messages
assert "from-log" in messages
end
test "script editor check syntax validates lua content without saving", %{project: project} do
{:ok, script} =
Scripts.create_script(%{
+51
View File
@@ -34,6 +34,57 @@ defmodule BDS.Scripting.LuaTest do
assert_receive {:progress, %{"phase" => "write", "current" => 2, "total" => 2}}
end
test "streams bds.app.log output through the on_output callback" do
parent = self()
source = """
function main()
bds.app.log('fetching')
bds.app.log('done', 42)
return 'ok'
end
"""
callback = fn text -> send(parent, {:script_output, text}) end
assert {:ok, "ok"} =
BDS.Scripting.execute_project_script("project-id", source, "main", [],
on_output: callback
)
assert_receive {:script_output, "fetching"}
assert_receive {:script_output, "done 42"}
end
test "routes print calls through the on_output callback" do
parent = self()
source = """
function main()
print('hello', 'world')
return 'ok'
end
"""
callback = fn text -> send(parent, {:script_output, text}) end
assert {:ok, "ok"} = BDS.Scripting.execute(source, "main", [], on_output: callback)
assert_receive {:script_output, "hello world"}
end
test "log and print fall back to a silent sink without an on_output callback" do
source = """
function main()
bds.app.log('note')
print('hello')
return 'ok'
end
"""
assert {:ok, "ok"} = BDS.Scripting.execute_project_script("project-id", source, "main", [])
end
test "sandbox blocks os.execute" do
source = "function main() os.execute('echo hacked') end"
+78
View File
@@ -0,0 +1,78 @@
defmodule BDS.UI.TaskGroupingTest do
use ExUnit.Case, async: true
alias BDS.UI.TaskGrouping
defp task(id, status, opts \\ %{}) do
%{
id: id,
name: Map.get(opts, :name, "Task #{id}"),
status: status,
progress: Map.get(opts, :progress),
message: nil,
group_id: Map.get(opts, :group_id),
group_name: Map.get(opts, :group_name)
}
end
describe "build_task_entries/1" do
test "tasks without a group stay single entries in order" do
entries = TaskGrouping.build_task_entries([task("a", :running), task("b", :completed)])
assert [{:single, %{id: "a"}}, {:single, %{id: "b"}}] = entries
end
test "tasks with a group_id are grouped by first-seen order" do
entries =
TaskGrouping.build_task_entries([
task("a", :running, %{group_id: "g1", group_name: "Import"}),
task("b", :running),
task("c", :pending, %{group_id: "g1", group_name: "Import"}),
task("d", :completed, %{group_id: "g2", group_name: "Upload"})
])
assert [
{:group, "g1", "Import", [%{id: "a"}, %{id: "c"}]},
{:single, %{id: "b"}},
{:group, "g2", "Upload", [%{id: "d"}]}
] = entries
end
test "group label falls back to the group_id when no group_name is set" do
assert [{:group, "g1", "g1", [_]}] =
TaskGrouping.build_task_entries([task("a", :running, %{group_id: "g1"})])
end
end
describe "summarize_task_group/1" do
test "counts statuses and averages progress contributions" do
summary =
TaskGrouping.summarize_task_group([
task("a", :running, %{progress: 0.5}),
task("b", :pending),
task("c", :completed)
])
assert summary.total == 3
assert summary.running == 1
assert summary.pending == 1
assert summary.completed == 1
assert summary.failed == 0
assert summary.cancelled == 0
# contributions: 0.5 (running) + 0 (pending) + 1.0 (completed)
assert_in_delta summary.progress, 0.5, 0.001
end
test "finished failures and cancellations count as full progress" do
summary = TaskGrouping.summarize_task_group([task("a", :failed), task("b", :cancelled)])
assert summary.progress == 1.0
assert summary.failed == 1
assert summary.cancelled == 1
end
test "empty group summarizes to zero" do
assert %{total: 0, progress: 0.0} = TaskGrouping.summarize_task_group([])
end
end
end