diff --git a/resources/js/components/fieldtypes/bard/LinkToolbar.vue b/resources/js/components/fieldtypes/bard/LinkToolbar.vue index 2753706489a..72ceabdc006 100644 --- a/resources/js/components/fieldtypes/bard/LinkToolbar.vue +++ b/resources/js/components/fieldtypes/bard/LinkToolbar.vue @@ -80,6 +80,15 @@
+ + + after('statamic://')->before('?')->before('#')->toString(); [$type, $id] = explode('::', $ref, 2); $data = null; diff --git a/src/Fieldtypes/Bard/LinkMark.php b/src/Fieldtypes/Bard/LinkMark.php index 955011d86f8..1277d60c8f1 100644 --- a/src/Fieldtypes/Bard/LinkMark.php +++ b/src/Fieldtypes/Bard/LinkMark.php @@ -62,7 +62,7 @@ protected function convertHref($href) return $href; } - $ref = Str::after($href, 'statamic://'); + $ref = str($href)->after('statamic://')->before('?')->before('#')->toString(); if (! $item = Data::find($ref)) { return ''; @@ -70,11 +70,13 @@ protected function convertHref($href) $selectAcrossSites = Augmentor::$currentBardConfig['select_across_sites'] ?? false; + $extras = Str::after($href, $ref); + if (! $selectAcrossSites && ! $this->isApi() && $item instanceof Entry) { - return ($item->in(Site::current()->handle()) ?? $item)->url(); + return ($item->in(Site::current()->handle()) ?? $item)->url().$extras; } - return $selectAcrossSites ? $item->absoluteUrl() : $item->url(); + return $selectAcrossSites ? $item->absoluteUrl().$extras : $item->url().$extras; } private function isApi() diff --git a/tests/Fieldtypes/BardTest.php b/tests/Fieldtypes/BardTest.php index 7eca35f1d5a..01b907697e3 100644 --- a/tests/Fieldtypes/BardTest.php +++ b/tests/Fieldtypes/BardTest.php @@ -1351,6 +1351,116 @@ public function it_doesnt_localize_when_select_across_sites_setting_is_enabled() $this->assertEquals('The One', $augmented); } + #[Test] + public function it_preserves_query_params_on_entry_links() + { + tap(Facades\Collection::make('blog')->routes('blog/{slug}'))->save(); + EntryFactory::collection('blog')->id('123')->slug('my-post')->data(['title' => 'My Post'])->create(); + + $field = (new Bard)->setField(new Field('test', ['type' => 'bard'])); + + $augmented = $field->augment([ + ['type' => 'text', 'marks' => [['type' => 'link', 'attrs' => ['href' => 'statamic://entry::123?foo=bar']]], 'text' => 'Link'], + ]); + + $this->assertEquals('Link', $augmented); + } + + #[Test] + public function it_preserves_anchors_on_entry_links() + { + tap(Facades\Collection::make('blog')->routes('blog/{slug}'))->save(); + EntryFactory::collection('blog')->id('123')->slug('my-post')->data(['title' => 'My Post'])->create(); + + $field = (new Bard)->setField(new Field('test', ['type' => 'bard'])); + + $augmented = $field->augment([ + ['type' => 'text', 'marks' => [['type' => 'link', 'attrs' => ['href' => 'statamic://entry::123#section']]], 'text' => 'Link'], + ]); + + $this->assertEquals('Link', $augmented); + } + + #[Test] + public function it_preserves_query_params_and_anchors_on_entry_links() + { + tap(Facades\Collection::make('blog')->routes('blog/{slug}'))->save(); + EntryFactory::collection('blog')->id('123')->slug('my-post')->data(['title' => 'My Post'])->create(); + + $field = (new Bard)->setField(new Field('test', ['type' => 'bard'])); + + $augmented = $field->augment([ + ['type' => 'text', 'marks' => [['type' => 'link', 'attrs' => ['href' => 'statamic://entry::123?foo=bar#section']]], 'text' => 'Link'], + ]); + + $this->assertEquals('Link', $augmented); + } + + #[Test] + public function it_preserves_appends_on_localized_entry_links() + { + $this->setSites([ + 'en' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'fr' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'], + ]); + + Facades\Site::setCurrent('fr'); + + tap(Facades\Collection::make('blog')->routes('blog/{slug}'))->sites(['en', 'fr'])->save(); + + EntryFactory::id('parent')->collection('blog')->slug('theparent')->id(123)->locale('en')->create(); + EntryFactory::id('123-fr')->origin('123')->locale('fr')->collection('blog')->slug('one-fr')->data(['title' => 'Le One'])->create(); + + $field = (new Bard)->setField(new Field('test', array_merge(['type' => 'bard'], ['select_across_sites' => false]))); + + $augmented = $field->augment([ + ['type' => 'text', 'marks' => [['type' => 'link', 'attrs' => ['href' => 'statamic://entry::123-fr?foo=bar#section']]], 'text' => 'The One'], + ]); + + $this->assertEquals('The One', $augmented); + } + + #[Test] + public function it_preserves_appends_on_entry_links_with_select_across_sites() + { + $this->setSites([ + 'en' => ['url' => 'http://localhost/', 'locale' => 'en'], + 'fr' => ['url' => 'http://localhost/fr/', 'locale' => 'fr'], + ]); + + Facades\Site::setCurrent('en'); + + tap(Facades\Collection::make('blog')->routes('blog/{slug}'))->sites(['en', 'fr'])->save(); + + EntryFactory::id('parent')->collection('blog')->slug('theparent')->id(123)->locale('en')->create(); + EntryFactory::id('123-fr')->origin('123')->locale('fr')->collection('blog')->slug('one-fr')->data(['title' => 'Le One'])->create(); + + $field = (new Bard)->setField(new Field('test', array_merge(['type' => 'bard'], ['select_across_sites' => true]))); + + $augmented = $field->augment([ + ['type' => 'text', 'marks' => [['type' => 'link', 'attrs' => ['href' => 'statamic://entry::123-fr?foo=bar#section']]], 'text' => 'The One'], + ]); + + $this->assertEquals('The One', $augmented); + } + + #[Test] + public function it_gets_link_data_with_appends() + { + tap(Facades\Collection::make('pages')->routes('/{slug}'))->save(); + EntryFactory::collection('pages')->id('1')->slug('about')->data(['title' => 'About'])->create(); + + $bard = $this->bard(['save_html' => true, 'sets' => null]); + + $html = '

Link with appends

'; + + $prosemirror = (new Augmentor($this))->renderHtmlToProsemirror($html)['content']; + + $this->assertEquals([ + 'entry::1' => ['title' => 'About', 'permalink' => 'http://localhost/about'], + ], $bard->getLinkData($prosemirror)); + } + private function bard($config = []) { return (new Bard)->setField(new Field('test', array_merge(['type' => 'bard', 'sets' => ['one' => []]], $config)));