diff --git a/.env.example b/.env.example index 48f9687..2f47748 100644 --- a/.env.example +++ b/.env.example @@ -78,11 +78,11 @@ # Label for the message field. # BOOK_LABEL_MESSAGE=Your message: -# Number of rows for the message textarea. -# BOOK_TEXTAREA_ROWS=8 +# Message textarea width in pixels. +# BOOK_TEXTAREA_WIDTH=400 -# Number of columns for the message textarea. -# BOOK_TEXTAREA_COLS=60 +# Message textarea height in pixels. +# BOOK_TEXTAREA_HEIGHT=150 # Custom HTML template file with {{title}}, {{form}}, {{entries}}, and {{style}} placeholders. # Uses built-in default if unset. diff --git a/README.md b/README.md index 25f440b..48d1af0 100644 --- a/README.md +++ b/README.md @@ -167,11 +167,11 @@ Running `guestbook` with no env vars will give you a working guestbook on `local # Label for the message field. # BOOK_LABEL_MESSAGE=Your message: -# Number of rows for the message textarea. -# BOOK_TEXTAREA_ROWS=8 +# Message textarea width in pixels. +# BOOK_TEXTAREA_WIDTH=400 -# Number of columns for the message textarea. -# BOOK_TEXTAREA_COLS=60 +# Message textarea height in pixels. +# BOOK_TEXTAREA_HEIGHT=150 # Custom HTML template file with {{title}}, {{form}}, {{entries}}, and {{style}} placeholders. # Uses built-in default if unset. @@ -235,8 +235,8 @@ services.guestbook = { message = "Your message:"; }; message = { - rows = 8; - cols = 60; + width = 400; + height = 150; }; }; }; @@ -286,8 +286,8 @@ The `status` field can be `pending`, `approved`, or `denied`. Only approved entr title - Site title (BOOK_SITE_TITLE). Useful in and headings. form - The submission form (labels, inputs, button). Controlled by BOOK_FORM_PROMPT, BOOK_LABEL_NAME, BOOK_LABEL_WEBSITE, - BOOK_LABEL_MESSAGE, BOOK_BUTTON_TEXT, BOOK_TEXTAREA_ROWS, - BOOK_TEXTAREA_COLS. Empty when BOOK_ENABLE_SUBMISSIONS=false. + BOOK_LABEL_MESSAGE, BOOK_BUTTON_TEXT, BOOK_TEXTAREA_WIDTH, + BOOK_TEXTAREA_HEIGHT. Empty when BOOK_ENABLE_SUBMISSIONS=false. entries - Approved guestbook entries, newest first. Entry separator controlled by BOOK_SEPARATOR. style - Custom CSS from BOOK_STYLE or BOOK_STYLE_FILE, wrapped in @@ -340,6 +340,16 @@ entries .guestbook-textarea {} .guestbook-button {} +/* Drawings */ +.guestbook-canvas { + border: 1px solid #000; + cursor: crosshair; +} +.guestbook-canvas-reset {} +.entry-drawing { + max-width: 100%; +} + /* Entries */ .entry-header {} .entry-name {} diff --git a/module.nix b/module.nix index 09647c3..c6200c3 100644 --- a/module.nix +++ b/module.nix @@ -203,16 +203,16 @@ in }; message = { - rows = mkOption { + width = mkOption { type = types.int; - default = 8; - description = "Number of rows for the message textarea."; + default = 400; + description = "Message textarea width in pixels."; }; - cols = mkOption { + height = mkOption { type = types.int; - default = 60; - description = "Number of columns for the message textarea."; + default = 150; + description = "Message textarea height in pixels."; }; }; }; @@ -249,8 +249,8 @@ in BOOK_LABEL_NAME = cfg.styles.labels.name; BOOK_LABEL_WEBSITE = cfg.styles.labels.website; BOOK_LABEL_MESSAGE = cfg.styles.labels.message; - BOOK_TEXTAREA_ROWS = toString cfg.styles.message.rows; - BOOK_TEXTAREA_COLS = toString cfg.styles.message.cols; + BOOK_TEXTAREA_WIDTH = toString cfg.styles.message.width; + BOOK_TEXTAREA_HEIGHT = toString cfg.styles.message.height; } // lib.optionalAttrs (cfg.styles.cssFile != null) { BOOK_STYLE_FILE = cfg.styles.cssFile; } // lib.optionalAttrs (cfg.styles.templateFile != null) { diff --git a/src/config.rs b/src/config.rs index 6806929..6633961 100644 --- a/src/config.rs +++ b/src/config.rs @@ -33,8 +33,8 @@ pub struct Config { pub label_name: String, pub label_website: String, pub label_message: String, - pub textarea_rows: u32, - pub textarea_cols: u32, + pub textarea_width: u32, + pub textarea_height: u32, } impl Config { @@ -138,14 +138,14 @@ impl Config { .unwrap_or_else(|_| "Your website (optional):".into()), label_message: env::var("BOOK_LABEL_MESSAGE") .unwrap_or_else(|_| "Your message:".into()), - textarea_rows: env::var("BOOK_TEXTAREA_ROWS") - .unwrap_or_else(|_| "8".into()) + textarea_width: env::var("BOOK_TEXTAREA_WIDTH") + .unwrap_or_else(|_| "400".into()) .parse() - .map_err(|_| "BOOK_TEXTAREA_ROWS must be a number")?, - textarea_cols: env::var("BOOK_TEXTAREA_COLS") - .unwrap_or_else(|_| "60".into()) + .map_err(|_| "BOOK_TEXTAREA_WIDTH must be a number")?, + textarea_height: env::var("BOOK_TEXTAREA_HEIGHT") + .unwrap_or_else(|_| "150".into()) .parse() - .map_err(|_| "BOOK_TEXTAREA_COLS must be a number")?, + .map_err(|_| "BOOK_TEXTAREA_HEIGHT must be a number")?, }) } } diff --git a/src/render.rs b/src/render.rs index 338f756..07ab1b4 100644 --- a/src/render.rs +++ b/src/render.rs @@ -40,8 +40,7 @@ pub fn render_form(config: &Config) -> String { let drawing_section = if config.enable_drawings { format!( - r##" -<label class="guestbook-label">{label}</label> + r##"<label class="guestbook-label">{label}</label> <canvas class="guestbook-canvas" width="{w}" height="{h}"></canvas> <a href="#" class="guestbook-canvas-reset">Reset</a> <input type="hidden" name="drawing"> @@ -87,7 +86,7 @@ pub fn render_form(config: &Config) -> String { <input class="guestbook-input" name="name" required> {website_section} <label class="guestbook-label">{label_message}</label> -<textarea class="guestbook-textarea" name="message" rows="{rows}" cols="{cols}" required></textarea> +<textarea class="guestbook-textarea" name="message" style="width:{tw}px;height:{th}px" required></textarea> {captcha_section} {drawing_section} <input name="url" style="display:none" tabindex="-1" autocomplete="off"> @@ -97,8 +96,8 @@ pub fn render_form(config: &Config) -> String { label_name = config.label_name, website_section = website_section, label_message = config.label_message, - rows = config.textarea_rows, - cols = config.textarea_cols, + tw = config.textarea_width, + th = config.textarea_height, captcha_section = captcha_section, drawing_section = drawing_section, button = config.button_text, @@ -196,8 +195,8 @@ mod tests { label_name: "Your name:".into(), label_website: "Your website (optional):".into(), label_message: "Your message:".into(), - textarea_rows: 8, - textarea_cols: 60, + textarea_width: 400, + textarea_height: 150, } } @@ -298,11 +297,11 @@ mod tests { #[test] fn test_render_form_custom_textarea() { let mut config = test_config(); - config.textarea_rows = 12; - config.textarea_cols = 40; + config.textarea_width = 500; + config.textarea_height = 200; let form = render_form(&config); - assert!(form.contains("rows=\"12\"")); - assert!(form.contains("cols=\"40\"")); + assert!(form.contains("width:500px")); + assert!(form.contains("height:200px")); } #[test] @@ -424,6 +423,6 @@ mod tests { let entry = make_entry("alice", "2026-04-09", "Hello!"); let form = render_form(&config); let html = render_page(DEFAULT_TEMPLATE, &config, &[entry], &form); - assert!(!html.contains("entry-drawing")); + assert!(!html.contains("<img class=\"entry-drawing\"")); } } diff --git a/src/web.rs b/src/web.rs index 9c8d908..26392d1 100644 --- a/src/web.rs +++ b/src/web.rs @@ -275,8 +275,8 @@ mod tests { label_name: "Your name:".into(), label_website: "Your website (optional):".into(), label_message: "Your message:".into(), - textarea_rows: 8, - textarea_cols: 60, + textarea_width: 400, + textarea_height: 150, } } diff --git a/templates/default.css b/templates/default.css index f5df6db..91d8ba1 100644 --- a/templates/default.css +++ b/templates/default.css @@ -12,9 +12,21 @@ .guestbook-form {} .guestbook-label {} .guestbook-input {} -.guestbook-textarea {} +.guestbook-textarea { + box-sizing: border-box; +} .guestbook-button {} +/* Drawings */ +.guestbook-canvas { + border: 1px solid #000; + cursor: crosshair; +} +.guestbook-canvas-reset {} +.entry-drawing { + max-width: 100%; +} + /* Entries */ .entry-header {} .entry-name {}