diff options
| author | Akshay Nair <phenax5@gmail.com> | 2025-07-27 15:57:54 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2025-07-27 19:46:00 +0530 |
| commit | 72a47c4eecb31a4976bfd4c47a36cd0ab9811a55 (patch) | |
| tree | 0bd813c8ec2b01d05c76bf56307ef1d1fe42286d | |
| parent | e3f1325b9da8c7d67c6d4aaefba625479fbce3d8 (diff) | |
| download | null-browser-72a47c4eecb31a4976bfd4c47a36cd0ab9811a55.tar.gz null-browser-72a47c4eecb31a4976bfd4c47a36cd0ab9811a55.zip | |
Refactor statusline + tabline with html generator util
| -rw-r--r-- | lua/null-browser/extras/html.lua | 51 | ||||
| -rw-r--r-- | lua/null-browser/extras/statusline.lua | 79 | ||||
| -rw-r--r-- | lua/null-browser/extras/tabline.lua | 32 |
3 files changed, 119 insertions, 43 deletions
diff --git a/lua/null-browser/extras/html.lua b/lua/null-browser/extras/html.lua new file mode 100644 index 0000000..d247090 --- /dev/null +++ b/lua/null-browser/extras/html.lua @@ -0,0 +1,51 @@ +local html = {} + +function html.create_el(name) + return function(attrs, children) + return { name = name, attrs = attrs, children = children } + end +end + +function html.el(name, attrs, children) + return html.create_el(name)(attrs, children) +end + +function html.to_string(elem) + if type(elem) == "string" then return html.escape_string(elem) end + + if elem.raw and elem.value then return elem.value end + + local attrs_str = '' + for key, value in pairs(elem.attrs or {}) do + -- TODO: html escape + quotify + attrs_str = attrs_str .. ' ' .. key .. '="' .. html.escape_string(value) .. '"' + end + + local children_str = '' + for _, value in ipairs(elem.children or {}) do + children_str = children_str .. ' ' .. html.to_string(value) + end + + return '<' .. elem.name .. attrs_str .. '>' .. children_str .. '</' .. elem.name .. '>' +end + +function html.raw(value) + return { raw = true, value = value }; +end + +html.div = html.create_el('div') +html.span = html.create_el('span') +html.button = html.create_el('button') +html.style = html.create_el('style') +html.a = html.create_el('a') + +function html.escape_string(str) + str = str:gsub('&', '&') + str = str:gsub('<', '<') + str = str:gsub('>', '>') + str = str:gsub('"', '"') + str = str:gsub("'", ''') + return str +end + +return html diff --git a/lua/null-browser/extras/statusline.lua b/lua/null-browser/extras/statusline.lua index 33a0220..6dd70ba 100644 --- a/lua/null-browser/extras/statusline.lua +++ b/lua/null-browser/extras/statusline.lua @@ -1,3 +1,4 @@ +local html = require 'null-browser.extras.html' local statusline = {} local mode_labels = { n = 'NORMAL', i = 'INSERT' } @@ -28,7 +29,15 @@ function statusline.show_status_in_window(win_id, decoration) web.view.set_html(statusline.html(), { view = view }) end - web.schedule(function() show_statusline() end) + web.schedule(function() + local view = decoration.view({ win = win_id }) + -- FIXME: web.schedule doesn't guarantee that view will be available + if not view then + web.schedule(function() show_statusline() end) + else + show_statusline() + end + end) web.event.add_listener({ 'ModeChanged', 'UrlChanged' }, { callback = function(_) show_statusline() end, }) @@ -52,40 +61,48 @@ end function statusline.html() local mode = web.keymap.get_mode() local url = statusline.current_url() - local mode_label = mode_labels[mode] or mode - local styles = '<style>' .. statusline.css() .. '</style>' - local mode_style = mode_styles[mode] or '' - local html = '<div class="statusline">' .. - '<div class="mode" style="' .. mode_style .. '">' .. mode_label .. '</div>' .. - '<div class="url">' .. url .. '</div>' .. - '</div>' - return styles .. html + local html_elem = html.div({}, { + html.style({}, { html.raw(statusline.css()) }), + html.div({ class = 'statusline' }, { + html.div({ class = 'mode', style = mode_styles[mode] or '' }, { + mode_labels[mode] or mode, + }), + html.div({ class = 'url' }, { url }), + }) + }) + return html.to_string(html_elem) end function statusline.css() return [[ - .statusline { - width: 100%; - height: 100vh; - display: flex; - justify-content: space-between; - align-items: stretch; - background-color: #000; - } - .mode { - display: flex; - justify-content: center; - align-items: center; - padding: 0 8px; - font-weight: bold; - background-color: #888; - } - .url { - display: flex; - justify-content: flex-end; - align-items: center; - padding: 0 8px; - } + html, body { + background: #000; + } + .statusline { + width: 100%; + height: 100vh; + display: flex; + justify-content: space-between; + align-items: stretch; + } + .mode { + display: flex; + justify-content: center; + align-items: center; + padding: 0 8px; + font-weight: bold; + background-color: #888; + } + .url { + display: flex; + justify-content: flex-start; + align-items: center; + padding: 0 8px; + max-width: 50vw; + overflow: hidden; + text-overflow: ellipsis; + text-wrap: nowrap; + } ]] end diff --git a/lua/null-browser/extras/tabline.lua b/lua/null-browser/extras/tabline.lua index 42612e9..4548207 100644 --- a/lua/null-browser/extras/tabline.lua +++ b/lua/null-browser/extras/tabline.lua @@ -1,3 +1,4 @@ +local html = require 'null-browser.extras.html' local tabline = {} -- TODO: vertical tabs @@ -42,19 +43,23 @@ function tabline.show_tabs_in_window(win_id, decoration) end function tabline.tabs_html() - local views_html = '' + local tab_list = {} for index, view in ipairs(web.view.list()) do - -- TODO: Sanitize this stuff - local text = index .. ': ' .. view.title .. ' (' .. view.url .. ')' - local classes = 'tab' - if web.view.current() == view.id then classes = classes .. ' current' end - local onclick = '__nullbrowser.tab_select({ view: ' .. view.id .. ' })' - local html = '<button class="' .. classes .. '" onclick="' .. onclick .. '">' .. text .. '</button>' - views_html = views_html .. html + local tab = html.button({ + class = 'tab' .. (web.view.current() == view.id and ' current' or ''), + onclick = '__nullbrowser.tab_select({ view: ' .. view.id .. ' })', + }, { + index .. ': ' .. view.title .. ' (' .. view.url .. ')', + }) + table.insert(tab_list, tab) end - return '<style>' .. tabline.css() .. '</style>' .. - '<div class="tabs">' .. views_html .. '</div>' + local tabs_html = html.div({}, { + html.style({}, { html.raw(tabline.css()) }), + html.div({ class = 'tabs' }, tab_list) + }) + + return html.to_string(tabs_html) end function tabline.css() @@ -76,12 +81,15 @@ function tabline.css() text-wrap: nowrap; text-align: left; min-width: 0; - border-left: 1px solid white; vertical-align: middle; padding: 0 8px; + border-left: 1px solid #555; + } + .tab:first-child { + border: none; } .tab.current { - background: #333; + background: #007070; } ]] end |
