syncLinks parses the default-locale content; processLinks resolves
each [[link]] against the current locale at render time. Link labels
preserve original spelling; destination resolves to the same document
in the current locale (with fallback).
createDocument/updateDocument now accept a \$locale parameter and
write to document_translations. Adds addTranslation, deleteTranslation,
setDefaultLocale (with path/slug regen), distinct-document search,
and findByTitle that delegates to WikiLinkResolver.
Adds translations/defaultTranslation relations, current-locale accessors
with fallback to default_locale, isFallback/availableLocales helpers,
and search scope that delegates to DocumentTranslation.
Includes a minimal Document::translations() HasMany relation so that
DocumentFactory's afterCreating callback (which calls
$document->translations()->count()) works. The full Document model
refactor (accessors, fallback helpers, default-translation accessor)
lands in Task 4.
- Vimeo regex now rejects URLs like vimeo.com/123abc that were
silently truncated to ID 123 and produced broken iframes. Negative
lookahead (?![A-Za-z0-9]) ensures the captured digits are not
followed by alphanumerics. Two false-positive test cases added.
- Spec corrected: HtmlInline nodes ARE filtered regardless of
insertion path; the implementation uses a dedicated MediaEmbedNode
+ renderer to bypass the filter only for trusted programmatic embeds.
Components list updated to include the two extra files.
- Plan Task 6 regex updated for consistency.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers image+video coexistence, multiple videos in one paragraph,
videos inside list items, wiki link non-interference, YouTube
timestamps end-to-end, and audio rendering through renderMarkdown.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The extension registers a DocumentParsedEvent listener that walks the
AST, finds Image nodes whose URLs match media patterns (via
MediaUrlResolver), and replaces them with MediaEmbedNode instances
containing the appropriate <video>/<audio>/<iframe> markup.
A custom MediaEmbedNode + MediaEmbedNodeRenderer pair bypasses the
html_input filter (which would strip raw HTML when set to 'strip'),
allowing programmatically generated embed HTML to pass through safely
while user-authored raw HTML remains stripped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Recognizes vimeo.com/{id} and player.vimeo.com/video/{id}. Preserves
timestamps from #t=30s and ?t=30s as #t=30s on the embed URL (Vimeo
convention).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Accepts ?t=30s, ?t=30, ?t=1m20s, ?t=1h2m3s, and ?start=N. Converts to
seconds and emits as ?start=N on the embed URL. ?t= takes priority over
?start= when both are present.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Recognizes youtu.be, watch?v=, shorts, embed, and mobile variants.
Emits an iframe pointing to youtube-nocookie.com with lazy loading,
strict-origin referrer policy, and allowfullscreen.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Initial skeleton returning null for any non-media URL. Subsequent commits
add detection for video, audio, YouTube, and Vimeo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Major features:
- Switch from slug-based to ID-based routing (/documents/123)
- Enable title editing with automatic slug/path regeneration
- Auto-generate folder structure from title slashes (e.g., Laravel/Livewire/Components)
- Persist sidebar folder open/close state using localStorage
- Remove slug unique constraint (ID routing makes it unnecessary)
- Implement recursive tree view with multi-level folder support
Architecture changes:
- DocumentService: Add generatePathAndSlug() for title-based path generation
- Routes: Change from {document:slug} to {document} for ID binding
- SidebarTree: Extract recursive rendering to partials/tree-item.blade.php
- Database: Remove unique constraint from documents.slug column
UI improvements:
- Display only last path component in sidebar (Components vs Laravel/Livewire/Components)
- Folder state persists across page navigation via localStorage
- Title field accepts slashes for folder organization
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>