Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/Http/Controllers/ShowDocumentationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,24 @@ public function __invoke(Request $request, string $platform, string $version, ?s
return view('docs.index')->with($pageProperties);
}

public function serveRawMarkdown(Request $request, string $platform, string $version, string $page)
{
abort_unless(is_dir(resource_path('views/docs/'.$platform.'/'.$version)), 404);

$filePath = resource_path("views/docs/{$platform}/{$version}/{$page}.md");

if (! file_exists($filePath)) {
abort(404);
}

$content = file_get_contents($filePath);

return response($content, 200, [
'Content-Type' => 'text/plain; charset=utf-8',
'Content-Disposition' => 'inline; filename="'.basename($filePath).'"',
]);
}

protected function getPageProperties($platform, $version, $page = null): array
{
$markdownFileName = $platform.'.'.$version.'.'.($page ?? 'index');
Expand Down
34 changes: 34 additions & 0 deletions resources/js/alpine/copyMarkdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export default () => ({
showMessage: false,

async copyMarkdownToClipboard() {
try {
// Get the current page URL and convert it to .md URL
const currentUrl = window.location.href
const mdUrl = currentUrl.replace(
/\/docs\/([^\/]+\/[^\/]+\/.*)$/,
'/docs/$1.md',
)

// Fetch the raw markdown content
const response = await fetch(mdUrl)
if (!response.ok) {
throw new Error('Failed to fetch markdown content')
}

const markdownContent = await response.text()

// Copy to clipboard
await navigator.clipboard.writeText(markdownContent)

// Show success message
this.showMessage = true
setTimeout(() => {
this.showMessage = false
}, 2000)
} catch (error) {
console.error('Failed to copy markdown:', error)
// Could show an error message here if needed
}
},
})
2 changes: 2 additions & 0 deletions resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Alpine,
} from '../../vendor/livewire/livewire/dist/livewire.esm'
import codeBlock from './alpine/codeBlock.js'
import copyMarkdown from './alpine/copyMarkdown.js'
import docsearch from '@docsearch/js'
import Atropos from 'atropos'
import '@docsearch/css'
Expand Down Expand Up @@ -60,6 +61,7 @@ window.gsap = gsap

// Alpine
Alpine.data('codeBlock', codeBlock)
Alpine.data('copyMarkdown', copyMarkdown)
Alpine.magic('refAll', (el) => {
return (refName) => {
return Array.from(el.querySelectorAll(`[x-ref="${refName}"]`))
Expand Down
16 changes: 16 additions & 0 deletions resources/views/components/docs/copy-markdown-button.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{{-- Copy as Markdown Button --}}
<div {{ $attributes->merge(['class' => 'mb-4']) }} x-data="copyMarkdown()" x-init="$watch('$el', () => {})">
<button
@click="copyMarkdownToClipboard()"
class="flex items-center gap-1.5 text-sm opacity-60 hover:opacity-100 transition-opacity duration-200"
title="Copy page as Markdown"
>
{{-- Icon --}}
<x-icons.copy x-show="!showMessage" class="size-[18px]" />
<x-icons.checkmark x-show="showMessage" x-cloak class="size-[18px]" />

{{-- Label --}}
<div x-show="!showMessage">Copy as Markdown</div>
<div x-show="showMessage" x-cloak>Copied!</div>
</button>
</div>
3 changes: 3 additions & 0 deletions resources/views/components/docs/toc-and-sponsors.blade.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{{-- Copy as Markdown Button --}}
<x-docs.copy-markdown-button />

{{-- On this page --}}
<h3 class="flex items-center gap-1.5 text-sm opacity-60">
{{-- Icon --}}
Expand Down
3 changes: 3 additions & 0 deletions resources/views/components/icons/copy.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<svg {{ $attributes->merge(['fill' => 'none', 'stroke' => 'currentColor', 'viewBox' => '0 0 24 24']) }}>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
</svg>
7 changes: 5 additions & 2 deletions resources/views/docs/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
<x-docs.separator class="mt-4" />

{{-- Table of contents --}}
<div class="xl:hidden">
<h3 class="inline-flex items-center gap-1.5 pt-5 text-sm opacity-50">
<div class="xl:hidden pt-5">
{{-- Copy as Markdown Button --}}
<x-docs.copy-markdown-button class="mt-4" />

<h3 class="inline-flex items-center gap-1.5 text-sm opacity-50">
{{-- Icon --}}
<x-icons.stacked-lines class="size-[18px]" />
{{-- Label --}}
Expand Down
6 changes: 6 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
Route::get('blog', [ShowBlogController::class, 'index'])->name('blog');
Route::get('blog/{article}', [ShowBlogController::class, 'show'])->name('article');

Route::get('/docs/{platform}/{version}/{page}.md', [ShowDocumentationController::class, 'serveRawMarkdown'])
->where('page', '(.*)')
->where('platform', '[a-z]+')
->where('version', '[0-9]+')
->name('docs.raw');

Route::get('/docs/{platform}/{version}/{page?}', ShowDocumentationController::class)
->where('page', '(.*)')
->where('platform', '[a-z]+')
Expand Down