From a37a9cfe960dc057af1546dd917de868d9657fef Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Sat, 7 Feb 2026 13:35:59 +0100 Subject: [PATCH 1/2] fix: shared template context injection --- app/Liquid/Tags/PluginRenderTag.php | 45 +++++++++++++++++++++ app/Models/Plugin.php | 3 ++ tests/Feature/PluginInlineTemplatesTest.php | 32 +++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 app/Liquid/Tags/PluginRenderTag.php diff --git a/app/Liquid/Tags/PluginRenderTag.php b/app/Liquid/Tags/PluginRenderTag.php new file mode 100644 index 0000000..e4c441a --- /dev/null +++ b/app/Liquid/Tags/PluginRenderTag.php @@ -0,0 +1,45 @@ + + */ + private const PARENT_CONTEXT_KEYS = ['trmnl', 'size', 'data', 'config']; + + protected function buildPartialContext(RenderContext $rootContext, string $templateName, array $variables = []): RenderContext + { + $partialContext = $rootContext->newIsolatedSubContext($templateName); + + foreach (self::PARENT_CONTEXT_KEYS as $key) { + $value = $rootContext->get($key); + if ($value !== null && ! $value instanceof MissingValue) { + $partialContext->set($key, $value); + } + } + + foreach ($variables as $key => $value) { + $partialContext->set($key, $value); + } + + foreach ($this->attributes as $key => $value) { + $partialContext->set($key, $rootContext->evaluate($value)); + } + + return $partialContext; + } +} diff --git a/app/Models/Plugin.php b/app/Models/Plugin.php index 5eeeb6b..d377956 100644 --- a/app/Models/Plugin.php +++ b/app/Models/Plugin.php @@ -10,6 +10,7 @@ use App\Liquid\Filters\Numbers; use App\Liquid\Filters\StandardFilters; use App\Liquid\Filters\StringMarkup; use App\Liquid\Filters\Uniqueness; +use App\Liquid\Tags\PluginRenderTag; use App\Liquid\Tags\TemplateTag; use App\Services\Plugin\Parsers\ResponseParserRegistry; use App\Services\PluginImportService; @@ -499,6 +500,8 @@ class Plugin extends Model // Register the template tag for inline templates $environment->tagRegistry->register(TemplateTag::class); + // Use plugin render tag so partials receive trmnl, size, data, config + $environment->tagRegistry->register(PluginRenderTag::class); // Apply Liquid replacements (including 'with' syntax conversion) $processedMarkup = $this->applyLiquidReplacements($markup); diff --git a/tests/Feature/PluginInlineTemplatesTest.php b/tests/Feature/PluginInlineTemplatesTest.php index 76b29d7..0bd5963 100644 --- a/tests/Feature/PluginInlineTemplatesTest.php +++ b/tests/Feature/PluginInlineTemplatesTest.php @@ -1,6 +1,7 @@ assertStringContainsString('"35":[{"name":"Ryan","age":35}]', $result); $this->assertStringContainsString('"29":[{"name":"Sara","age":29},{"name":"Jimbob","age":29}]', $result); }); + +test('shared template receives trmnl context when', function (): void { + $user = User::factory()->create(['name' => 'Jane Smith']); + + $plugin = Plugin::factory()->create([ + 'user_id' => $user->id, + 'name' => 'Departures', + 'markup_language' => 'liquid', + 'render_markup_shared' => <<<'LIQUID' +{% template departures_view %} +
+ Departures + {{ trmnl.user.name }} +
+{% endtemplate %} +LIQUID + , + 'render_markup' => <<<'LIQUID' +
+{% render "departures_view", station: "Hauptbahnhof" %} +
+LIQUID + , + 'data_payload' => [], + ]); + + $result = $plugin->render('full'); + + $this->assertStringContainsString('Jane Smith', $result); + $this->assertStringContainsString('class="instance"', $result); +}); From b96a96155d1b77f6765fcd2a07ad55b7d35b2a73 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Sat, 7 Feb 2026 13:56:37 +0100 Subject: [PATCH 2/2] chore: format fixes --- ..._121714_add_maximum_compatibility_to_devices_table.php | 8 ++++---- tests/Feature/Api/DeviceEndpointsTest.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/database/migrations/2026_02_01_121714_add_maximum_compatibility_to_devices_table.php b/database/migrations/2026_02_01_121714_add_maximum_compatibility_to_devices_table.php index a682c62..bd0d54b 100644 --- a/database/migrations/2026_02_01_121714_add_maximum_compatibility_to_devices_table.php +++ b/database/migrations/2026_02_01_121714_add_maximum_compatibility_to_devices_table.php @@ -8,15 +8,15 @@ return new class extends Migration { public function up(): void { - Schema::table("devices", function (Blueprint $table): void { - $table->boolean("maximum_compatibility")->default(false); + Schema::table('devices', function (Blueprint $table): void { + $table->boolean('maximum_compatibility')->default(false); }); } public function down(): void { - Schema::table("devices", function (Blueprint $table): void { - $table->dropColumn("maximum_compatibility"); + Schema::table('devices', function (Blueprint $table): void { + $table->dropColumn('maximum_compatibility'); }); } }; diff --git a/tests/Feature/Api/DeviceEndpointsTest.php b/tests/Feature/Api/DeviceEndpointsTest.php index 54edb10..44fb651 100644 --- a/tests/Feature/Api/DeviceEndpointsTest.php +++ b/tests/Feature/Api/DeviceEndpointsTest.php @@ -100,7 +100,7 @@ test('display endpoint includes maximum_compatibility value when true for device $device = Device::factory()->create([ 'mac_address' => '00:11:22:33:44:55', 'api_key' => 'test-api-key', - 'maximum_compatibility' => true + 'maximum_compatibility' => true, ]); $response = $this->withHeaders([