feat(ccli): serve CCLI bookmarklet JS
This commit is contained in:
parent
cd44d6289c
commit
cd0a72124d
47
app/Http/Controllers/BookmarkletController.php
Normal file
47
app/Http/Controllers/BookmarkletController.php
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
|
||||
final class BookmarkletController extends Controller
|
||||
{
|
||||
public function show(): Response
|
||||
{
|
||||
$appUrl = rtrim((string) Config::get('app.url', ''), '/');
|
||||
|
||||
$bookmarkletScript = <<<'BOOKMARKLET'
|
||||
(function(){
|
||||
var APP_URL = '__APP_URL__';
|
||||
if(!location.hostname.includes('songselect.ccli.com')){
|
||||
alert('Bitte öffne dieses Lesezeichen auf einer SongSelect Liedseite (songselect.ccli.com).');
|
||||
return;
|
||||
}
|
||||
var title = (document.querySelector('h1, .song-title, [class*="title"]') || {}).innerText || document.title || '';
|
||||
var author = (document.querySelector('.song-authors, .song-artist, [class*="author"]') || {}).innerText || '';
|
||||
var bodyText = document.body ? document.body.innerText : '';
|
||||
var ccliMatch = bodyText.match(/CCLI[\s#-]*(\d+)/i);
|
||||
var ccliId = ccliMatch ? ccliMatch[1] : '';
|
||||
var payload = {
|
||||
title: title.trim(),
|
||||
author: author.trim(),
|
||||
ccliId: ccliId,
|
||||
sourceUrl: location.href,
|
||||
rawText: bodyText
|
||||
};
|
||||
var encoded = btoa(unescape(encodeURIComponent(JSON.stringify(payload))));
|
||||
window.open(APP_URL + '/songs/import-from-ccli-paste?prefill=' + encoded, '_blank');
|
||||
})();
|
||||
BOOKMARKLET;
|
||||
|
||||
$bookmarkletScript = str_replace('__APP_URL__', $appUrl, $bookmarkletScript);
|
||||
|
||||
$singleLine = 'javascript:'.preg_replace('/\s+/', ' ', $bookmarkletScript);
|
||||
|
||||
return response($singleLine, 200, [
|
||||
'Content-Type' => 'text/javascript; charset=utf-8',
|
||||
'Cache-Control' => 'public, max-age=3600',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use App\Http\Controllers\ApiLogController;
|
||||
use App\Http\Controllers\AuthController;
|
||||
use App\Http\Controllers\BookmarkletController;
|
||||
use App\Http\Controllers\LabelImportController;
|
||||
use App\Http\Controllers\MacroAssignmentController;
|
||||
use App\Http\Controllers\MacroImportController;
|
||||
|
|
@ -46,6 +47,8 @@
|
|||
->middleware('auth')
|
||||
->name('logout');
|
||||
|
||||
Route::get('/bookmarklets/ccli-import.js', [BookmarkletController::class, 'show'])->name('bookmarklets.ccli');
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::get('/', function () {
|
||||
return redirect()->route('dashboard');
|
||||
|
|
|
|||
41
tests/Feature/BookmarkletControllerTest.php
Normal file
41
tests/Feature/BookmarkletControllerTest.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('bookmarklet endpoint returns 200 with text/javascript content type', function () {
|
||||
$response = $this->get('/bookmarklets/ccli-import.js');
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'text/javascript; charset=utf-8');
|
||||
});
|
||||
|
||||
test('bookmarklet response starts with javascript: prefix', function () {
|
||||
$response = $this->get('/bookmarklets/ccli-import.js');
|
||||
|
||||
expect($response->getContent())->toStartWith('javascript:');
|
||||
});
|
||||
|
||||
test('bookmarklet response is a single line with no actual newlines', function () {
|
||||
$response = $this->get('/bookmarklets/ccli-import.js');
|
||||
$content = $response->getContent();
|
||||
|
||||
expect(substr_count($content, "\n"))->toBe(0);
|
||||
});
|
||||
|
||||
test('bookmarklet response contains app URL and import path', function () {
|
||||
$response = $this->get('/bookmarklets/ccli-import.js');
|
||||
$content = $response->getContent();
|
||||
|
||||
expect($content)->toContain('import-from-ccli-paste');
|
||||
expect($content)->toContain('songselect.ccli.com');
|
||||
expect($content)->toContain('btoa');
|
||||
});
|
||||
|
||||
test('bookmarklet endpoint does not require authentication', function () {
|
||||
$response = $this->get('/bookmarklets/ccli-import.js');
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertHeader('Content-Type', 'text/javascript; charset=utf-8');
|
||||
});
|
||||
Loading…
Reference in a new issue