Was ist der TextBuilder?
Der TextBuilder ist eine Klasse, mit der Sie die vom Bluesky-AT-Protocol definierten facets (Rich-Text-Annotations) über Method-Chaining zusammenstellen.
Der Body eines Bluesky-Posts ist reiner Text. Um Mentions, Links und Hashtags anzuzeigen, muss neben dem Text ein facets-Array übermittelt werden, das jeweils Position (Byte-Offset) und Typ angibt. Der TextBuilder übernimmt diese Offset-Berechnung und den Array-Aufbau automatisch.
Einfache Textausgabe
TextBuilder::make()
Erzeugen Sie mit TextBuilder::make() eine Instanz mit optionalem Initialtext. Der Initialtext ist optional.
use Revolution\Bluesky\RichText\TextBuilder;
$builder = TextBuilder::make(text: 'Hello Bluesky');
text()
Mit text() hängen Sie Text am Ende an.
$builder = TextBuilder::make()
->text('Hello ')
->text('Bluesky');
// $builder->text === 'Hello Bluesky'
newLine()
Fügt einen Zeilenumbruch hinzu. Über count können Sie die Zeilenanzahl angeben (Default: 1).
$builder = TextBuilder::make('Zeile 1')
->newLine()
->text('Zeile 2')
->newLine(count: 2)
->text('Zeile 4');
toPost()
Wandelt die TextBuilder-Instanz in einen Post-Record um. Kann direkt an Bluesky::post() übergeben werden.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\RichText\TextBuilder;
$post = TextBuilder::make('Einfacher Post')->toPost();
$response = Bluesky::withToken()->post($post);
Post::build()
Alternativ übergeben Sie eine Closure an Post::build(). Der Rückgabewert ist ein Post.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\RichText\TextBuilder;
$post = Post::build(function (TextBuilder $builder) {
$builder->text('Hello Bluesky');
});
$response = Bluesky::withToken()->post($post);
Mention (@mention) hinzufügen
Fügen Sie mit mention() eine Mention-Facette hinzu.
$builder->mention(text: '@alice.bsky.social');
Automatische DID-Auflösung
Wenn Sie did weglassen, wird die DID automatisch aus dem Handle aufgelöst (Bluesky::resolveHandle() wird aufgerufen).
// DID automatisch auflösen (führt einen API-Aufruf aus)
$builder->mention('@alice.bsky.social');
DID explizit angeben
Wenn die DID bekannt ist, können Sie den API-Aufruf vermeiden, indem Sie sie explizit übergeben.
// DID direkt angeben (empfohlen: kein API-Aufruf)
$builder->mention(text: '@alice.bsky.social', did: 'did:plc:xxxxxxxxxxxxxxxxxxxx');
Wenn Sie in der Produktion häufig Mentions verwenden, können Sie die DIDs cachen, um API-Aufrufe zu reduzieren.
Link (URL) einbetten
Fügen Sie mit link() eine Link-Facette hinzu.
// Die URL selbst als Anzeigetext nutzen
$builder->link('https://laravel.com');
// Anzeigetext und URL getrennt angeben
$builder->link(text: 'Offizielle Laravel-Website', uri: 'https://laravel.com');
Wird uri weggelassen, wird text als URI verwendet.
Fügen Sie mit tag() eine Hashtag-Facette hinzu.
// Text, der mit # beginnt, extrahiert das Tag automatisch
$builder->tag('#Laravel');
// Tag-String explizit angeben (String ohne #)
$builder->tag(text: '#Laravel', tag: 'Laravel');
Zusammengesetzte Texte
Kombinieren Sie mehrere Facetten für reichhaltige Post-Texte.
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\RichText\TextBuilder;
$post = TextBuilder::make('Ein neuer Artikel wurde veröffentlicht!')
->newLine(count: 2)
->mention('@alice.bsky.social', did: 'did:plc:xxxx')
->text(' sollte ihn unbedingt lesen.')
->newLine()
->link(text: 'Artikel lesen', uri: 'https://example.com/article/1')
->newLine()
->tag('#Laravel')
->text(' ')
->tag('#PHP')
->toPost();
$response = Bluesky::withToken()->post($post);
Schreibweise mit Post::build()
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\RichText\TextBuilder;
$post = Post::build(function (TextBuilder $builder) {
$builder->text('Ein neuer Artikel wurde veröffentlicht!')
->newLine(count: 2)
->mention('@alice.bsky.social', did: 'did:plc:xxxx')
->text(' sollte ihn unbedingt lesen.')
->newLine()
->link(text: 'Artikel lesen', uri: 'https://example.com/article/1')
->newLine()
->tag('#Laravel')
->text(' ')
->tag('#PHP');
});
$response = Bluesky::withToken()->post($post);
Integration mit Posts
Kombination mit Bluesky::post()
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\RichText\TextBuilder;
$post = TextBuilder::make('test')
->newLine()
->link('https://bsky.app/')
->toPost();
$response = Bluesky::withToken()->post($post);
Kombination mit dem Notification-Kanal
In der Methode toBluesky() von BlueskyChannel können Sie Post::build() verwenden.
use Illuminate\Notifications\Notification;
use Revolution\Bluesky\Notifications\BlueskyChannel;
use Revolution\Bluesky\Record\Post;
use Revolution\Bluesky\RichText\TextBuilder;
class DeployedNotification extends Notification
{
public function __construct(
private string $url,
) {}
public function via(object $notifiable): array
{
return [BlueskyChannel::class];
}
public function toBluesky(object $notifiable): Post
{
return Post::build(function (TextBuilder $builder) {
$builder->text('Deployment abgeschlossen')
->newLine()
->link(text: 'Überprüfen', uri: $this->url)
->newLine()
->tag('#Laravel');
});
}
}
Facets automatisch erkennen
Es ist auch möglich, @mention, URLs und #hashtag im Text automatisch zu erkennen und facets zu setzen.
use Revolution\Bluesky\RichText\TextBuilder;
$builder = TextBuilder::make('@alice.bsky.social test https://example.com #alice')
->detectFacets();
// Nach detectFacets() können Sie weitere facets ergänzen
$builder->newLine()->tag('#bob');
$post = $builder->toPost();
detectFacets() arbeitet regex-basiert. Wenn Sie Links garantiert setzen möchten, ist es sicherer, link(), mention() und tag() explizit zu verwenden.
Eigene Facets hinzufügen
Mit der Methode facet() können Sie ein beliebiges Facet-Array direkt hinzufügen.
use Revolution\Bluesky\RichText\TextBuilder;
$builder = TextBuilder::make();
$builder->facet([
'index' => [
'byteStart' => 0,
'byteEnd' => 5,
],
'features' => [
[
'$type' => 'app.bsky.richtext.facet#link',
'uri' => 'https://example.com',
],
],
]);
Zeichenbegrenzung und Hinweise
Byte-Offsets und Graphemes
Der Facet-Index des AT Protocols wird in UTF-8-Byte-Offsets angegeben. TextBuilder berechnet die Byte-Anzahl intern über strlen().
Multi-Byte-Zeichen wie japanische Zeichen und Emojis verbrauchen pro Zeichen mehrere Bytes. Die Offsets ergeben sich daher aus der Byte-Anzahl, nicht aus der Zeichenanzahl.
// 'Hello' hat in UTF-8 5 Bytes (1 Zeichen = 1 Byte)
// '日本語' hat in UTF-8 9 Bytes (1 Zeichen = 3 Bytes)
$builder = TextBuilder::make('日本語');
// strlen($builder->text) === 9
Zeichenlimit für Posts
Bluesky-Posts sind auf maximal 300 Zeichen in Graphemes (angezeigte Zeichenanzahl) begrenzt. Da nicht in Bytes, sondern in Graphemes gerechnet wird, können Sie auch in Japanisch bis zu 300 Zeichen schreiben.
use Illuminate\Support\Str;
$text = 'Dies ist der Post-Text.';
// Zeichenanzahl in Graphemes ermitteln
$length = Str::length($text); // äquivalent zu mb_strlen()
TextBuilder selbst prüft die Zeichenanzahl nicht. Wenn Sie einen Post mit mehr als 300 Graphemes senden, gibt die AT-Protocol-API einen Fehler zurück.
Methodenübersicht
| Methode | Beschreibung |
|---|
TextBuilder::make(string $text = '') | Instanz erzeugen |
text(string $text) | Text am Ende hinzufügen |
newLine(int $count = 1) | Zeilenumbruch hinzufügen |
mention(string $text, ?string $did = null) | Mention-Facette hinzufügen |
link(string $text, ?string $uri = null) | Link-Facette hinzufügen |
tag(string $text, ?string $tag = null) | Hashtag-Facette hinzufügen |
detectFacets() | Facets automatisch aus dem Text erkennen |
facet(array $facet) | Eigene Facette hinzufügen |
resetFacets() | Alle Facets zurücksetzen |
toPost() | In einen Post-Record umwandeln |
toArray() | In das Array ['text' => ..., 'facets' => ...] umwandeln |
Zuletzt geändert am 13. Juli 2026