Mercurial Hosting > linkmystyle
diff src/theme.html.luan @ 0:8f4df159f06b
start public repo
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 11 Jul 2025 20:57:49 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/theme.html.luan Fri Jul 11 20:57:49 2025 -0600 @@ -0,0 +1,353 @@ +local Luan = require "luan:Luan.luan" +local error = Luan.error +local pairs = Luan.pairs or error() +local parse = Luan.parse or error() +local Html = require "luan:Html.luan" +local html_encode = Html.encode or error() +local Io = require "luan:Io.luan" +local Http = require "luan:http/Http.luan" +local Shared = require "site:/lib/Shared.luan" +local head = Shared.head or error() +local body_header = Shared.body_header or error() +local footer = Shared.footer or error() +local fields = Shared.theme_fields or error() +local User = require "site:/lib/User.luan" +local get_background_img_url = User.get_background_img_url or error() +local Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "theme.html" + + +local google_explanation = [[All Google fonts use this URL format. You can change the font name and edit the font URL to use other Google fonts not listed here.]] + +local fonts = { + ["Sans-Serif"] = {} + ["Times New Roman"] = {} + ["Optima"] = {} + ["Apple Chancery"] = {} + ["Courier"] = {} + ["Copperplate"] = {} + ["Bitter"] = { + title = "Google: Bitter" + url = "https://fonts.googleapis.com/css?family=Bitter" + explanation = google_explanation + } + ["Genos"] = { + title = "Google: Genos" + url = "https://fonts.googleapis.com/css?family=Genos" + explanation = google_explanation + } + ["Emblema One"] = { + title = "Google: Emblema One" + url = "https://fonts.googleapis.com/css?family=Emblema+One" + explanation = google_explanation + } +} +for name, font in pairs(fonts) do + font.name = name + font.title = font.title or name + font.url = font.url or "" + font.explanation = font.explanation or "" +end + +local function color_input(user_data,color) + local value = user_data[color] + value = value and html_encode(value) + local default = fields[color] + local v = value or default +%> + <div> + <input type=color <%= v=="" and "" or [[value="]]..v..[["]] %> oninput="colorChange(this)"> + <span color <%= v=="" and "" or [[style="background-color:]]..v..[["]] %> onclick="colorClick(this)"></span> + <input type=text name="<%=color%>" value="<%= value or "" %>" placeholder="<%=default%>" onchange="colorInputChange(this)"> + </div> +<% +end + +local function radio_input(user_data,name,value) + local current = user_data[name] or fields[name] + local checked = value==current and "checked" or "" + %><input type=radio name="<%=name%>" value="<%=value%>" <%=checked%> ><% +end + +return function() + local user = User.current_required() + if user==nil then return end + local user_data = user.theme_data + user_data = user_data and parse(user_data) or {} + local message + Io.stdout = Http.response.text_writer() +%> +<!doctype html> +<html lang="en"> + <head> +<% head() %> + <title>Link My Style</title> + <style> +<% + for _, font in pairs(fonts) do + if font.url ~= "" then +%> + @import "<%=font.url%>"; +<% + end +%> +<% + end +%> + + h1 { + text-align: center; + } + div[body] { + max-width: 600px; + margin-left: auto; + margin-right: auto; + } + @media (max-width: 700px) { + div[body] { + max-width: 90%; + } + } + label { + display: block; + } + form > div { + display: flex; + margin-top: 1px; + margin-bottom: 10px; + position: relative; + } + input[type="color"] { + /* hide this useless modern piece of junk */ + position: absolute; + z-index: 1; + width: 42.5px; + height: 42.5px; + cursor: pointer; + opacity: 0; + } + span[color] { + width: 42.5px; + cursor: pointer; + border: 1px solid #E0E0E0; + } + form span[pulldown] { + border: 1px solid #E0E0E0; + display: flex; + align-items: center; + } + form span[pulldown] > span { + padding: 4px; + } + span[shape] a { + margin: 12px; + padding: 12px 100px; + border: 1px solid black; + } + span[shape] a:hover { + text-decoration: none; + } + input[type="text"] { + display: initial; + margin: 0; + border-radius: 0; + } + label[clickable] { + border: 1px solid grey; + padding: 4px; + padding-right: 8px; + } + label[white] { + color: white; + background-color: black; + } + div[background_img] { + gap: 8px; + } + button[background_img] { + width: 42.5px; + height: 42.5px; + padding: 0; + border: 1px solid #E0E0E0; + } + button[background_img] img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; + } + div[background_img] button[small] { + flex-grow: 1; + background-color: #E0E0E0; + color: black; + } + div[background_img] button[small]:hover { + background-color: #C0C0C0; + } + div[font] { + gap: 8px; + } + div[font] input[name="font"] { + width: 33%; + } + div[font] input[name="font_url"] { + width: 66%; + } + div[font_explanation] { + color: #808080; + } + </style> + <script> + 'use strict'; + + function colorClick(colorSpan) { + console.log('colorClick'); + let colorInput = colorSpan.parentNode.querySelector('input[type="color"]'); + colorInput.click(); + } + function colorChange(colorInput) { + let parent = colorInput.parentNode; + let color = colorInput.value; + parent.querySelector('input[type="text"]').value = color; + parent.querySelector('span[color]').style['background-color'] = color; + } + function colorInputChange(input) { + let parent = input.parentNode; + let color = input.value || input.placeholder; + parent.querySelector('input[type="color"]').value = color; + parent.querySelector('span[color]').style['background-color'] = color; + } + function setField(name,value) { + document.querySelector('input[type="text"][name="'+name+'"]').value = value; + } + function setFont(font,url,explanation) { + setField('font',font); + setField('font_url',url); + document.querySelector('div[font_explanation]').textContent = explanation; + } + + function uploaded(uuid,filename) { + document.querySelector('input[name="background_img_uuid"]').value = uuid; + document.querySelector('input[name="background_img_filename"]').value = filename; + document.querySelector('div[background_img] img').src = uploadcareUrl(uuid); + } + function clearImg() { + document.querySelector('input[name="background_img_uuid"]').value = ''; + document.querySelector('input[name="background_img_filename"]').value = ''; + document.querySelector('div[background_img] img').src = '/images/nothing.svg'; + } + </script> + </head> + <body> + <div full> +<% body_header() %> + <h1>My Theme</h1> + <p top>Click the left side of every section to make quick changes or put exactly what you'd like in the input field. To remove a color or shadow, delete the text from the input field.</p> + <div body> + <form onsubmit="ajaxForm('/theme.js',this)" action="javascript:"> + <label>Background Image</label> + <div background_img> + <button type=button background_img onclick="uploadcare.upload(uploaded)"> + <img src="<%= get_background_img_url(user_data) or "/images/nothing.svg" %>" > + </button> + <input type=hidden name="background_img_uuid" value="<%= user_data.background_img_uuid or "" %>"> + <input type=hidden name="background_img_filename" value="<%= user_data.background_img_filename or "" %>"> + <button type=button small onclick="uploadcare.upload(uploaded)">Add</button> + <button type=button small onclick="clearImg()">Clear</button> + </div> + <label>Background Color</label> +<% color_input(user_data,"background_color") %> + <label>Button Color</label> +<% color_input(user_data,"link_background_color") %> + <label>Button Hover Color</label> +<% color_input(user_data,"link_hover_background_color") %> + <label>Button Text Color</label> +<% color_input(user_data,"link_text_color") %> + <label>Title Color</label> +<% color_input(user_data,"title_color") %> + <label>Bio Color</label> +<% color_input(user_data,"bio_color") %> + <label>Social Icon Color</label> + <div> + <label clickable black><% radio_input(user_data,"icon_color","") %>Black</label> + + <label clickable white><% radio_input(user_data,"icon_color","white") %>White</label> + </div> + <label>Button Shape</label> +<% + local field = "link_border_radius" + local value = user_data[field] + value = value and html_encode(value) + local default = fields[field] + local value_or_default = value or default +%> + <div> + <span shape pulldown> + <span onclick="clickMenu(this)">Select...</span> + <div pulldown_menu> + <a style="border-radius:22px / 50%" href="javascript:setField('<%=field%>','22px / 50%')">Link</a> + <a style="border-radius:12px / 50%" href="javascript:setField('<%=field%>','12px / 50%')">Link</a> + <a style="border-radius:10px" href="javascript:setField('<%=field%>','10px')">Link</a> + <a style="border-radius:0" href="javascript:setField('<%=field%>','0')">Link</a> + <a style="border-radius:10px 100px" href="javascript:setField('<%=field%>','10px 100px')">Link</a> + </div> + </span> + <input type=text name="<%=field%>" value="<%= value or "" %>" placeholder="<%=default%>"> + </div> + <label>Button Border Color</label> +<% color_input(user_data,"link_border_color") %> + <label>Button Shadow</label> +<% + local field = "link_shadow" + local value = user_data[field] + value = value and html_encode(value) + local default = fields[field] + local value_or_default = value or default +%> + <div> + <span shape pulldown> + <span onclick="clickMenu(this)">Select...</span> + <div pulldown_menu> + <a style="box-shadow:5px 5px 2px 1px" href="javascript:setField('<%=field%>','5px 5px 2px 1px')">Link</a> + <a style="box-shadow:1px 1px 10px 1px" href="javascript:setField('<%=field%>','1px 1px 10px 1px')">Link</a> + </div> + </span> + <input type=text name="<%=field%>" value="<%= value or "" %>" placeholder="<%=default%>"> + </div> + <label>Button Shadow Color</label> +<% color_input(user_data,"link_shadow_color") %> + <label>Font</label> +<% + local value = user_data.font + value = value and html_encode(value) + local value_url = user_data.font_url + value_url = value_url and html_encode(value_url) + local default = fields.font + local explanation = fonts[value] and fonts[value].explanation or "" +%> + <div font> + <span pulldown> + <span onclick="clickMenu(this)">Select...</span> + <div pulldown_menu> +<% for _, font in pairs(fonts) do %> + <a style="font-family:<%=font.name%>" href="javascript:setFont('<%=font.name%>','<%=font.url%>','<%=font.explanation%>')"><%=font.title%></a> +<% end %> + </div> + </span> + <input type=text name="font" value="<%= value or "" %>" placeholder="<%=default%>"> + <input type=text name="font_url" value="<%= value_url or "" %>" placeholder="URL"> + </div> + <div font_explanation><%=explanation%></div> + <button type=submit big>Save</button> +<% + local msg = message and message.info +%> + <div success><%= msg or "" %></div> + </form> + </div> +<% footer() %> + </div> + </body> +</html> +<% +end