From 97945efadb59622a87e7bb23f7ab56155619ea5b Mon Sep 17 00:00:00 2001
From: Navindra Umanee
Date: Mon, 16 Mar 2026 22:15:45 -0700
Subject: [PATCH 1/4] Added support for inline audio for mp3, aac, wav.
This renders the filename in the URL for context, with the audio player immediately below.
---
src/Plugins/Autoaudio/Configurator.php | 31 ++++++++++++++++++++++++++
src/Plugins/Autoaudio/Parser.js | 1 +
src/Plugins/Autoaudio/Parser.php | 15 +++++++++++++
3 files changed, 47 insertions(+)
create mode 100644 src/Plugins/Autoaudio/Configurator.php
create mode 100644 src/Plugins/Autoaudio/Parser.js
create mode 100644 src/Plugins/Autoaudio/Parser.php
diff --git a/src/Plugins/Autoaudio/Configurator.php b/src/Plugins/Autoaudio/Configurator.php
new file mode 100644
index 000000000..c1803c48d
--- /dev/null
+++ b/src/Plugins/Autoaudio/Configurator.php
@@ -0,0 +1,31 @@
+
';
+ }
+
+ protected function setUp(): void
+ {
+ parent::setUp();
+
+ $tag = $this->configurator->tags[$this->tagName];
+ $tag->attributes->add('filename')->filterChain->append('urldecode');
+ $tag->attributePreprocessors->add('src', '/\\/(?\'filename\'[^\\/]+)$/');
+ }
+}
diff --git a/src/Plugins/Autoaudio/Parser.js b/src/Plugins/Autoaudio/Parser.js
new file mode 100644
index 000000000..0873e9428
--- /dev/null
+++ b/src/Plugins/Autoaudio/Parser.js
@@ -0,0 +1 @@
+const tagPriority = -1;
diff --git a/src/Plugins/Autoaudio/Parser.php b/src/Plugins/Autoaudio/Parser.php
new file mode 100644
index 000000000..7b7da0504
--- /dev/null
+++ b/src/Plugins/Autoaudio/Parser.php
@@ -0,0 +1,15 @@
+
Date: Tue, 17 Mar 2026 19:58:23 -0700
Subject: [PATCH 2/4] Add Autoaudio plugin tests and extended format support
Add comprehensive test suite for the Autoaudio plugin covering
configurator setup, URL parsing, filename extraction with URL
decoding, and HTML rendering output.
Extend supported audio formats to include flac, m4a, and wave
in addition to the existing aac, mp3, ogg, and wav formats.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/Plugins/Autoaudio/Configurator.php | 4 +-
tests/Plugins/Autoaudio/ConfiguratorTest.php | 158 +++++++++++++++++++
tests/Plugins/Autoaudio/ParserTest.php | 98 ++++++++++++
3 files changed, 258 insertions(+), 2 deletions(-)
create mode 100644 tests/Plugins/Autoaudio/ConfiguratorTest.php
create mode 100644 tests/Plugins/Autoaudio/ParserTest.php
diff --git a/src/Plugins/Autoaudio/Configurator.php b/src/Plugins/Autoaudio/Configurator.php
index c1803c48d..1998ce887 100644
--- a/src/Plugins/Autoaudio/Configurator.php
+++ b/src/Plugins/Autoaudio/Configurator.php
@@ -11,13 +11,13 @@
class Configurator extends AbstractConfigurator
{
- public array $fileExtensions = ['mp3', 'aac', 'wav'];
+ public array $fileExtensions = ['aac', 'flac', 'm4a', 'mp3', 'ogg', 'wav', 'wave'];
protected $attrName = 'src';
protected $tagName = 'AUDIO';
protected function getTemplate(): string
{
- return '
';
+ return ':
';
}
protected function setUp(): void
diff --git a/tests/Plugins/Autoaudio/ConfiguratorTest.php b/tests/Plugins/Autoaudio/ConfiguratorTest.php
new file mode 100644
index 000000000..f92922d84
--- /dev/null
+++ b/tests/Plugins/Autoaudio/ConfiguratorTest.php
@@ -0,0 +1,158 @@
+configurator->Autoaudio;
+ $this->assertTrue($this->configurator->tags->exists('AUDIO'));
+
+ $tag = $this->configurator->tags->get('AUDIO');
+ $this->assertTrue($tag->attributes->exists('src'));
+
+ $attribute = $tag->attributes->get('src');
+ $this->assertTrue($attribute->filterChain->contains(new UrlFilter));
+ }
+
+ /**
+ * @testdox Automatically creates a "filename" attribute
+ */
+ public function testCreatesFilenameAttribute()
+ {
+ $this->configurator->Autoaudio;
+ $tag = $this->configurator->tags->get('AUDIO');
+ $this->assertTrue($tag->attributes->exists('filename'));
+ }
+
+ /**
+ * @testdox Does not attempt to create a tag if it already exists
+ */
+ public function testDoesNotCreateTag()
+ {
+ $tag = $this->configurator->tags->add('AUDIO');
+ $this->configurator->plugins->load('Autoaudio');
+
+ $this->assertSame($tag, $this->configurator->tags->get('AUDIO'));
+ }
+
+ /**
+ * @testdox The name of the tag used can be changed through the "tagName" constructor option
+ */
+ public function testCustomTagName()
+ {
+ $this->configurator->plugins->load('Autoaudio', ['tagName' => 'FOO']);
+ $this->assertTrue($this->configurator->tags->exists('FOO'));
+ }
+
+ /**
+ * @testdox The name of the attribute used can be changed through the "attrName" constructor option
+ */
+ public function testCustomAttrName()
+ {
+ $this->configurator->plugins->load('Autoaudio', ['attrName' => 'bar']);
+ $this->assertTrue($this->configurator->tags['AUDIO']->attributes->exists('bar'));
+ }
+
+ /**
+ * @testdox Has a quickMatch
+ */
+ public function testConfigQuickMatch()
+ {
+ $this->assertArrayHasKey(
+ 'quickMatch',
+ $this->configurator->plugins->load('Autoaudio')->asConfig()
+ );
+ }
+
+ /**
+ * @testdox The config array contains a regexp
+ */
+ public function testConfigRegexp()
+ {
+ $this->assertArrayHasKey(
+ 'regexp',
+ $this->configurator->plugins->load('Autoaudio')->asConfig()
+ );
+ }
+
+ /**
+ * @testdox The config array contains the name of the tag
+ */
+ public function testConfigTagName()
+ {
+ $config = $this->configurator->plugins->load('Autoaudio')->asConfig();
+
+ $this->assertArrayHasKey('tagName', $config);
+ $this->assertSame('AUDIO', $config['tagName']);
+ }
+
+ /**
+ * @testdox The config array contains the name of the attribute
+ */
+ public function testConfigAttributeName()
+ {
+ $config = $this->configurator->plugins->load('Autoaudio')->asConfig();
+
+ $this->assertArrayHasKey('attrName', $config);
+ $this->assertSame('src', $config['attrName']);
+ }
+
+ /**
+ * @testdox getTag() returns the tag that is associated with this plugin
+ */
+ public function testGetTag()
+ {
+ $plugin = $this->configurator->plugins->load('Autoaudio');
+
+ $this->assertSame(
+ $this->configurator->tags['AUDIO'],
+ $plugin->getTag()
+ );
+ }
+
+ /**
+ * @testdox The JS parser contains both parser files
+ */
+ public function testJSParser()
+ {
+ $js = $this->configurator->Autoaudio->getJSParser();
+
+ foreach (['AbstractStaticUrlReplacer', 'Autoaudio'] as $pluginName)
+ {
+ $filepath = __DIR__ . '/../../../src/Plugins/' . $pluginName . '/Parser.js';
+ $this->assertStringContainsString(file_get_contents($filepath), $js);
+ }
+ }
+
+ /**
+ * @testdox File extensions are configurable
+ */
+ public function testFileExtensions()
+ {
+ $this->configurator->Autoaudio->fileExtensions = ['flac', 'wma'];
+ $this->configurator->Autoaudio->finalize();
+
+ $config = $this->configurator->Autoaudio->asConfig();
+
+ $this->assertMatchesRegularExpression(
+ $config['regexp'],
+ 'https://example.org/audio.flac'
+ );
+ $this->assertDoesNotMatchRegularExpression(
+ $config['regexp'],
+ 'https://example.org/audio.mp4'
+ );
+ }
+}
diff --git a/tests/Plugins/Autoaudio/ParserTest.php b/tests/Plugins/Autoaudio/ParserTest.php
new file mode 100644
index 000000000..a453f6661
--- /dev/null
+++ b/tests/Plugins/Autoaudio/ParserTest.php
@@ -0,0 +1,98 @@
+.. ..'
+ ],
+ [
+ 'http://example.org/audio.mp3',
+ ''
+ ],
+ [
+ 'http://example.org/audio.wav',
+ ''
+ ],
+ [
+ 'http://example.org/audio.aac',
+ ''
+ ],
+ [
+ 'http://example.org/audio.flac',
+ ''
+ ],
+ [
+ 'http://example.org/audio.m4a',
+ ''
+ ],
+ [
+ 'http://example.org/audio.wave',
+ ''
+ ],
+ [
+ '.. HTTP://EXAMPLE.ORG/AUDIO.MP3 ..',
+ '.. ..'
+ ],
+ [
+ '.. http://user:pass@example.org/audio.mp3 ..',
+ '.. http://user:pass@example.org/audio.mp3 ..'
+ ],
+ [
+ '.. http://example.org/my%20song%20(1).mp3 ..',
+ '.. ..'
+ ],
+ [
+ 'http://example.org/audio.mp4',
+ 'http://example.org/audio.mp4'
+ ],
+ [
+ 'http://example.org/audio.mp3',
+ '',
+ [],
+ function ($configurator)
+ {
+ $configurator->Autolink;
+ }
+ ],
+ [
+ 'https://recitals.pianoworld.com/recital_files/Recital_65/11.%20navindra%20Navindra%20Umanee%20-%20Bluebird.mp3',
+ ''
+ ],
+ ];
+ }
+
+ public static function getRenderingTests()
+ {
+ return [
+ [
+ 'http://example.org/audio.mp3',
+ 'audio.mp3:
'
+ ],
+ [
+ 'http://example.org/my%20song.mp3',
+ 'my song.mp3:
'
+ ],
+ ];
+ }
+}
From e003b7a270f84462d392c8a6ca0abc93593dc7b5 Mon Sep 17 00:00:00 2001
From: Navindra Umanee
Date: Tue, 17 Mar 2026 20:40:41 -0700
Subject: [PATCH 3/4] Remove ogg from Autoaudio supported formats
The ogg format conflicts with Autovideo which already handles .ogg
files. Removing it from Autoaudio avoids ambiguity between the two
plugins.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/Plugins/Autoaudio/Configurator.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugins/Autoaudio/Configurator.php b/src/Plugins/Autoaudio/Configurator.php
index 1998ce887..007818d7f 100644
--- a/src/Plugins/Autoaudio/Configurator.php
+++ b/src/Plugins/Autoaudio/Configurator.php
@@ -11,7 +11,7 @@
class Configurator extends AbstractConfigurator
{
- public array $fileExtensions = ['aac', 'flac', 'm4a', 'mp3', 'ogg', 'wav', 'wave'];
+ public array $fileExtensions = ['aac', 'flac', 'm4a', 'mp3', 'wav', 'wave'];
protected $attrName = 'src';
protected $tagName = 'AUDIO';
From 893871c92b58c072b90c4e777b3fa6016333ad03 Mon Sep 17 00:00:00 2001
From: Navindra Umanee
Date: Tue, 17 Mar 2026 21:33:58 -0700
Subject: [PATCH 4/4] Use attrName variable consistently in Autoaudio
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/Plugins/Autoaudio/Configurator.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Plugins/Autoaudio/Configurator.php b/src/Plugins/Autoaudio/Configurator.php
index 007818d7f..61b717c92 100644
--- a/src/Plugins/Autoaudio/Configurator.php
+++ b/src/Plugins/Autoaudio/Configurator.php
@@ -17,7 +17,7 @@ class Configurator extends AbstractConfigurator
protected function getTemplate(): string
{
- return ':
';
+ return ':
';
}
protected function setUp(): void
@@ -26,6 +26,6 @@ protected function setUp(): void
$tag = $this->configurator->tags[$this->tagName];
$tag->attributes->add('filename')->filterChain->append('urldecode');
- $tag->attributePreprocessors->add('src', '/\\/(?\'filename\'[^\\/]+)$/');
+ $tag->attributePreprocessors->add($this->attrName, '/\\/(?\'filename\'[^\\/]+)$/');
}
}