Skip to content

Commit b8c3d11

Browse files
committed
post-release
1 parent 2f706be commit b8c3d11

11 files changed

Lines changed: 922 additions & 3 deletions

File tree

doc/_brand.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
meta:
22
name: ggsql
3-
link: https://github.com/georgestagg/ggsql
3+
link: https://ggsql.org
44

55
logo:
66
small: assets/icon.svg
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Mickaël Canouil
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
title: Iconify
2+
author: Mickaël Canouil
3+
version: 3.2.1
4+
quarto-required: ">=1.5.57"
5+
contributes:
6+
shortcodes:
7+
- iconify.lua
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
--- MC Logging - Formatted log output for Quarto Lua filters and shortcodes
2+
--- @module logging
3+
--- @license MIT
4+
--- @copyright 2026 Mickaël Canouil
5+
--- @author Mickaël Canouil
6+
--- @version 1.0.0
7+
8+
local M = {}
9+
10+
-- ============================================================================
11+
-- LOGGING UTILITIES
12+
-- ============================================================================
13+
14+
--- Format and log an error message with extension prefix.
15+
--- Provides standardised error messages with consistent formatting across extensions.
16+
--- Format: [extension-name] Message with details.
17+
---
18+
--- @param extension_name string The name of the extension (e.g., "external", "lua-env")
19+
--- @param message string The error message to display
20+
--- @usage M.log_error("external", "Could not open file 'example.md'.")
21+
function M.log_error(extension_name, message)
22+
quarto.log.error('[' .. extension_name .. '] ' .. message)
23+
end
24+
25+
--- Format and log a warning message with extension prefix.
26+
--- Provides standardised warning messages with consistent formatting across extensions.
27+
--- Format: [extension-name] Message with details.
28+
---
29+
--- @param extension_name string The name of the extension (e.g., "external", "lua-env")
30+
--- @param message string The warning message to display
31+
--- @usage M.log_warning("lua-env", "No variable name provided.")
32+
function M.log_warning(extension_name, message)
33+
quarto.log.warning('[' .. extension_name .. '] ' .. message)
34+
end
35+
36+
--- Format and log an output message with extension prefix.
37+
--- Provides standardised informational messages with consistent formatting across extensions.
38+
--- Format: [extension-name] Message with details.
39+
---
40+
--- @param extension_name string The name of the extension (e.g., "lua-env")
41+
--- @param message string The informational message to display
42+
--- @usage M.log_output("lua-env", "Exported metadata to: output.json")
43+
function M.log_output(extension_name, message)
44+
quarto.log.output('[' .. extension_name .. '] ' .. message)
45+
end
46+
47+
--- Format and log a debug message with extension prefix.
48+
--- Provides standardised debug messages with consistent formatting across extensions.
49+
--- Format: [extension-name] Message with details.
50+
---
51+
--- @param extension_name string The name of the extension (e.g., "lua-env")
52+
--- @param message string The debug message to display
53+
--- @usage M.log_debug("lua-env", "Variable 'x' has value: 42")
54+
function M.log_debug(extension_name, message)
55+
quarto.log.debug('[' .. extension_name .. '] ' .. message)
56+
end
57+
58+
-- ============================================================================
59+
-- MODULE EXPORT
60+
-- ============================================================================
61+
62+
return M
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
--- MC Metadata - Extension configuration and metadata access for Quarto Lua filters and shortcodes
2+
--- @module metadata
3+
--- @license MIT
4+
--- @copyright 2026 Mickaël Canouil
5+
--- @author Mickaël Canouil
6+
--- @version 1.0.0
7+
8+
local M = {}
9+
10+
--- Load a sibling module from the same directory as this file.
11+
--- @param filename string The sibling module filename (e.g., 'string.lua')
12+
--- @return table The loaded module
13+
local function load_sibling(filename)
14+
local source = debug.getinfo(1, 'S').source:sub(2)
15+
local dir = source:match('(.*[/\\])') or ''
16+
return require((dir .. filename):gsub('%.lua$', ''))
17+
end
18+
19+
--- Load required modules
20+
local str = load_sibling('string.lua')
21+
local log = load_sibling('logging.lua')
22+
23+
-- ============================================================================
24+
-- METADATA UTILITIES
25+
-- ============================================================================
26+
27+
--- Get configuration from extensions.name namespace.
28+
--- @param meta table Document metadata
29+
--- @param extension_name string The extension name (e.g., "github", "iconify")
30+
--- @return any The value/table or nil
31+
--- @usage local value = M.get_extension_config(meta, 'section-outline')
32+
function M.get_extension_config(meta, extension_name)
33+
local config_ext = meta.extensions and meta.extensions[extension_name]
34+
if not config_ext then return nil end
35+
return config_ext
36+
end
37+
38+
--- Extract metadata value from document meta using nested structure.
39+
--- Supports the extensions.{extension-name}.{key} pattern.
40+
--- @param meta table The document metadata table
41+
--- @param extension_name string The extension name (e.g., "github", "iconify")
42+
--- @param key string The metadata key to retrieve
43+
--- @return string|nil The metadata value as a string, or nil if not found
44+
--- @usage local repo = M.get_metadata_value(meta, "github", "repository-name")
45+
function M.get_metadata_value(meta, extension_name, key)
46+
if meta['extensions'] and meta['extensions'][extension_name] and meta['extensions'][extension_name][key] then
47+
return str.stringify(meta['extensions'][extension_name][key])
48+
end
49+
return nil
50+
end
51+
52+
--- Check for deprecated top-level configuration and emit warning
53+
--- @param meta table The document metadata table
54+
--- @param extension_name string The extension name
55+
--- @param key string|nil The configuration key being accessed (nil to check entire extension config)
56+
--- @param deprecation_warning_shown boolean Flag to track if warning has been shown
57+
--- @return any|nil The value from deprecated config, or nil if not found
58+
--- @return boolean Updated deprecation warning flag
59+
function M.check_deprecated_config(meta, extension_name, key, deprecation_warning_shown)
60+
-- Handle array-based configuration (when key is nil)
61+
if key == nil then
62+
if not str.is_empty(meta[extension_name]) then
63+
if not deprecation_warning_shown then
64+
log.log_warning(
65+
extension_name,
66+
'Top-level "' .. extension_name .. '" configuration is deprecated. ' ..
67+
'Please use:\n' ..
68+
'extensions:\n' ..
69+
' ' .. extension_name .. ':\n' ..
70+
' - (configuration array)'
71+
)
72+
deprecation_warning_shown = true
73+
end
74+
return meta[extension_name], deprecation_warning_shown
75+
end
76+
return nil, deprecation_warning_shown
77+
end
78+
79+
-- Handle key-value configuration (original behaviour)
80+
if not str.is_empty(meta[extension_name]) and not str.is_empty(meta[extension_name][key]) then
81+
if not deprecation_warning_shown then
82+
log.log_warning(
83+
extension_name,
84+
'Top-level "' .. extension_name .. '" configuration is deprecated. ' ..
85+
'Please use:\n' ..
86+
'extensions:\n' ..
87+
' ' .. extension_name .. ':\n' ..
88+
' ' .. key .. ': value'
89+
)
90+
deprecation_warning_shown = true
91+
end
92+
return str.stringify(meta[extension_name][key]), deprecation_warning_shown
93+
end
94+
return nil, deprecation_warning_shown
95+
end
96+
97+
-- ============================================================================
98+
-- ENHANCED METADATA/CONFIGURATION UTILITIES
99+
-- ============================================================================
100+
101+
--- Get option value with fallback hierarchy: args -> extensions.{extension}.{key} -> defaults.
102+
--- Provides a standardised way to read configuration values with multiple fallback levels.
103+
--- Priority: 1. Named arguments (kwargs), 2. Document metadata, 3. Default values.
104+
---
105+
--- @param spec table Configuration spec with fields: extension (string), key (string), args (table|nil), meta (table|nil), default (any|nil)
106+
--- @return any The resolved option value (type depends on what's stored in config)
107+
--- @usage local duration = M.get_option_with_fallbacks({extension = 'animate', key = 'duration', args = kwargs, meta = meta, default = '3s'})
108+
function M.get_option_with_fallbacks(spec)
109+
-- Validate required fields
110+
if not spec.extension or not spec.key then
111+
error("Configuration spec must include 'extension' and 'key' fields")
112+
end
113+
114+
--- @type string The extension name
115+
local extension = spec.extension
116+
--- @type string The configuration key
117+
local key = spec.key
118+
--- @type table|nil Named arguments table
119+
local args = spec.args
120+
--- @type table|nil Document metadata
121+
local meta = spec.meta
122+
--- @type any Default value if not found elsewhere
123+
local default = spec.default
124+
125+
-- Priority 1: Check named arguments (kwargs)
126+
if args and args[key] then
127+
local arg_value = str.stringify(args[key])
128+
if not str.is_empty(arg_value) then
129+
return arg_value
130+
end
131+
end
132+
133+
-- Priority 2: Check metadata extensions.{extension}.{key}
134+
if meta then
135+
local meta_value = M.get_metadata_value(meta, extension, key)
136+
if not str.is_empty(meta_value) then
137+
return meta_value
138+
end
139+
end
140+
141+
-- Priority 3: Return default value
142+
return default
143+
end
144+
145+
--- Get multiple option values at once with fallback hierarchy.
146+
--- Batch version of get_option_with_fallbacks for retrieving multiple configuration values.
147+
--- Returns a table mapping each key to its resolved value.
148+
---
149+
--- @param spec table Configuration spec with fields: extension (string), keys (table<integer, string>), args (table|nil), meta (table|nil), defaults (table<string, any>|nil)
150+
--- @return table<string, any> Table mapping each key to its resolved value
151+
--- @usage local opts = M.get_options({extension = 'animate', keys = {'duration', 'delay'}, args = kwargs, meta = meta, defaults = {duration = '3s', delay = '2s'}})
152+
function M.get_options(spec)
153+
-- Validate required fields
154+
if not spec.extension or not spec.keys then
155+
error("Configuration spec must include 'extension' and 'keys' fields")
156+
end
157+
158+
--- @type table<string, any> Result table
159+
local result = {}
160+
161+
--- @type table Default values table
162+
local defaults = spec.defaults or {}
163+
164+
-- Get each key using the single-option fallback logic
165+
for _, key in ipairs(spec.keys) do
166+
result[key] = M.get_option_with_fallbacks({
167+
extension = spec.extension,
168+
key = key,
169+
args = spec.args,
170+
meta = spec.meta,
171+
default = defaults[key]
172+
})
173+
end
174+
175+
return result
176+
end
177+
178+
-- ============================================================================
179+
-- MODULE EXPORT
180+
-- ============================================================================
181+
182+
return M

0 commit comments

Comments
 (0)