diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70373ef..ca2baaf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
+## 0.2.0 (May 5, 2026)
+
+### Added
+- **Format IDs** field on the content plugin and site module — single ID or comma-separated list of BMLT format IDs to lock the widget to. Can be overridden per shortcode via `format_ids="17,54"`.
+
## 0.1.0 (April 29, 2026)
Initial release. Embed the [Crumb](https://crumb.bmlt.app/) BMLT meeting-finder widget in Joomla 4, 5, or 6 sites.
diff --git a/packages/module/language/en-GB/mod_crumb.ini b/packages/module/language/en-GB/mod_crumb.ini
index 4134a05..635ce85 100644
--- a/packages/module/language/en-GB/mod_crumb.ini
+++ b/packages/module/language/en-GB/mod_crumb.ini
@@ -10,6 +10,9 @@ MOD_CRUMB_FIELD_SERVER_DESC="Required. The full URL to your BMLT server (e.g. ht
MOD_CRUMB_FIELD_SERVICE_BODY_LABEL="Service Body IDs"
MOD_CRUMB_FIELD_SERVICE_BODY_DESC="Optional. Single ID or comma-separated list. Leave empty to show all meetings. Child service bodies are always included."
+MOD_CRUMB_FIELD_FORMAT_IDS_LABEL="Format IDs"
+MOD_CRUMB_FIELD_FORMAT_IDS_DESC="Optional. Single ID or comma-separated list of BMLT format IDs to lock the widget to. Leave empty to show all formats."
+
MOD_CRUMB_FIELD_VIEW_LABEL="Default View"
MOD_CRUMB_FIELD_VIEW_DESC="Optional. Sets the default view when the widget loads."
MOD_CRUMB_FIELD_VIEW_DEFAULT="— Widget Default (list) —"
diff --git a/packages/module/mod_crumb.xml b/packages/module/mod_crumb.xml
index ddb50a5..236a521 100644
--- a/packages/module/mod_crumb.xml
+++ b/packages/module/mod_crumb.xml
@@ -7,7 +7,7 @@
GPL v2 or later
bmlt-enabled@googlegroups.com
https://github.com/bmlt-enabled/crumb-joomla
- 0.1.0
+ 0.2.0
MOD_CRUMB_XML_DESCRIPTION
BmltEnabled\Module\Crumb\Site
@@ -43,6 +43,15 @@
filter="string"
default=""
/>
+
trim((string) $params->get('server', '')),
'service_body' => (string) $params->get('service_body', ''),
+ 'format_ids' => (string) $params->get('format_ids', ''),
'view' => (string) $params->get('view', ''),
'css_template' => (string) $params->get('css_template', ''),
'base_path' => (string) $params->get('base_path', ''),
@@ -52,6 +53,7 @@ public function render(array $settings): string
}
$serviceBody = $settings['service_body'] ?? '';
+ $formatIds = $settings['format_ids'] ?? '';
$viewRaw = $settings['view'] ?? '';
$view = \in_array($viewRaw, self::ALLOWED_VIEWS, true) ? $viewRaw : '';
$basePath = trim((string) ($settings['base_path'] ?? ''), '/');
@@ -65,6 +67,9 @@ public function render(array $settings): string
if ($serviceBody !== '') {
$attrs['data-service-body'] = trim((string) $serviceBody);
}
+ if ($formatIds !== '') {
+ $attrs['data-format-ids'] = trim((string) $formatIds);
+ }
if ($view !== '') {
$attrs['data-view'] = $view;
}
diff --git a/packages/plugin/crumb.xml b/packages/plugin/crumb.xml
index 1fd4a92..b62c04c 100644
--- a/packages/plugin/crumb.xml
+++ b/packages/plugin/crumb.xml
@@ -7,7 +7,7 @@
GPL v2 or later
bmlt-enabled@googlegroups.com
https://github.com/bmlt-enabled/crumb-joomla
- 0.1.0
+ 0.2.0
PLG_CONTENT_CRUMB_XML_DESCRIPTION
BmltEnabled\Plugin\Content\Crumb
@@ -42,6 +42,15 @@
filter="string"
default=""
/>
+
(string) $this->params->get('server', ''),
'service_body' => (string) $this->params->get('service_body', ''),
+ 'format_ids' => (string) $this->params->get('format_ids', ''),
'view' => (string) $this->params->get('view', ''),
'css_template' => (string) $this->params->get('css_template', ''),
'base_path' => (string) $this->params->get('base_path', ''),
diff --git a/packages/plugin/src/Helper/CrumbRenderer.php b/packages/plugin/src/Helper/CrumbRenderer.php
index e201416..e286399 100644
--- a/packages/plugin/src/Helper/CrumbRenderer.php
+++ b/packages/plugin/src/Helper/CrumbRenderer.php
@@ -39,6 +39,7 @@ public static function render(array $settings, array $overrides = []): string
}
$serviceBody = $overrides['service_body'] ?? $settings['service_body'] ?? '';
+ $formatIds = $overrides['format_ids'] ?? $settings['format_ids'] ?? '';
$viewRaw = $overrides['view'] ?? $settings['view'] ?? '';
$view = \in_array($viewRaw, self::ALLOWED_VIEWS, true) ? $viewRaw : '';
$basePath = trim((string) ($settings['base_path'] ?? ''), '/');
@@ -52,6 +53,9 @@ public static function render(array $settings, array $overrides = []): string
if ($serviceBody !== null && $serviceBody !== '') {
$attrs['data-service-body'] = trim((string) $serviceBody);
}
+ if ($formatIds !== null && $formatIds !== '') {
+ $attrs['data-format-ids'] = trim((string) $formatIds);
+ }
if ($view !== '') {
$attrs['data-view'] = $view;
}
diff --git a/pkg_crumb.xml b/pkg_crumb.xml
index 5ca6184..5399dab 100644
--- a/pkg_crumb.xml
+++ b/pkg_crumb.xml
@@ -8,7 +8,7 @@
bmlt-enabled@googlegroups.com
https://github.com/bmlt-enabled/crumb-joomla
crumb
- 0.1.0
+ 0.2.0
https://github.com/bmlt-enabled/crumb-joomla
bmlt-enabled
https://github.com/bmlt-enabled
diff --git a/tests/Unit/CrumbRendererTest.php b/tests/Unit/CrumbRendererTest.php
index 793a960..d1d0f85 100644
--- a/tests/Unit/CrumbRendererTest.php
+++ b/tests/Unit/CrumbRendererTest.php
@@ -39,6 +39,40 @@ public function testServiceBodyAttributeEmittedWhenSet(): void
$this->assertStringContainsString('data-service-body="42,57"', $output);
}
+ public function testFormatIdsAttributeEmittedFromSettings(): void
+ {
+ $output = CrumbRenderer::render([
+ 'server' => 'https://x/main_server',
+ 'format_ids' => '17,54',
+ ]);
+ $this->assertStringContainsString('data-format-ids="17,54"', $output);
+ }
+
+ public function testFormatIdsAttributeOmittedWhenEmpty(): void
+ {
+ $output = CrumbRenderer::render(['server' => 'https://x/main_server']);
+ $this->assertStringNotContainsString('data-format-ids', $output);
+ }
+
+ public function testFormatIdsOverrideBeatsSavedSetting(): void
+ {
+ $output = CrumbRenderer::render(
+ ['server' => 'https://x/main_server', 'format_ids' => '99'],
+ ['format_ids' => '17']
+ );
+ $this->assertStringContainsString('data-format-ids="17"', $output);
+ $this->assertStringNotContainsString('data-format-ids="99"', $output);
+ }
+
+ public function testEmptyFormatIdsOverrideOmitsAttribute(): void
+ {
+ $output = CrumbRenderer::render(
+ ['server' => 'https://x/main_server', 'format_ids' => '99'],
+ ['format_ids' => '']
+ );
+ $this->assertStringNotContainsString('data-format-ids', $output);
+ }
+
public function testInvalidViewIsDroppedNotPassedThrough(): void
{
$output = CrumbRenderer::render([