All Projects → spatie → Sheets

spatie / Sheets

Licence: mit
Store & retrieve your static content in plain text files

Projects that are alternatives of or similar to Sheets

Laravel Blog
基于Laravel5.8构建的轻量博客应用,支持Markdown,支持图片拖拽上传,界面简洁,SEO友好,支持百度链接自动和手动提交
Stars: ✭ 84 (-52%)
Mutual labels:  blog, markdown, laravel
Moell Blog
基于 Laravel 开发,支持 Markdown 语法的博客
Stars: ✭ 301 (+72%)
Mutual labels:  blog, markdown, laravel
Blogged
🖍 Write beautiful blog articles using Markdown inside your Laravel app.
Stars: ✭ 114 (-34.86%)
Mutual labels:  blog, laravel
Coreblog
一款优雅的博客系统
Stars: ✭ 119 (-32%)
Mutual labels:  blog, laravel
Laravel Blog Api
laravel+vue 个人博客,项目预览: http://www.golang365.com
Stars: ✭ 127 (-27.43%)
Mutual labels:  blog, laravel
Viki
A simple Wiki page in Markdown from notebook of VNote.
Stars: ✭ 103 (-41.14%)
Mutual labels:  blog, markdown
Startblog
Startblog is a simple Markdown blog system based on the CodeIgniter!
Stars: ✭ 107 (-38.86%)
Mutual labels:  blog, markdown
Wizard
Wizard是一款开源的文档管理工具,支持Markdown/Swagger/Table类型的文档。
Stars: ✭ 1,733 (+890.29%)
Mutual labels:  markdown, laravel
Laravel 5 Myblog
The php blog writed by laravel5.1
Stars: ✭ 86 (-50.86%)
Mutual labels:  blog, laravel
Neontsunami Laravel
Source for my website and blog
Stars: ✭ 142 (-18.86%)
Mutual labels:  blog, laravel
Oblog
An Auto Rendering 🔽 Blogging System Based on MarkDown & Vue.js | 自动渲染装载 MarkDown 内容的博客系统
Stars: ✭ 133 (-24%)
Mutual labels:  blog, markdown
Laravel Blog Poetry All
Laravel诗词博客-匠心编程,热爱生活。喜欢就 Star 吧
Stars: ✭ 157 (-10.29%)
Mutual labels:  blog, laravel
Blog
博客文章 markdown 源文件
Stars: ✭ 100 (-42.86%)
Mutual labels:  blog, markdown
Blog
基于Python Flask并支持Markdown语法的简易博客
Stars: ✭ 89 (-49.14%)
Mutual labels:  blog, markdown
Quickblog
PHP开源的一文多发平台(支持开源中国、简书、知乎、博客园、CSDN、SegmentFault)
Stars: ✭ 112 (-36%)
Mutual labels:  blog, laravel
Blog System In Laravel
Complete Blog System in Laravel
Stars: ✭ 89 (-49.14%)
Mutual labels:  blog, laravel
Cell Blog
基于 Laravel 7开发,支持 Markdown 语法的博客
Stars: ✭ 120 (-31.43%)
Mutual labels:  blog, laravel
Blog
Code for my personal blog built with Gatsby
Stars: ✭ 167 (-4.57%)
Mutual labels:  blog, markdown
Blog Vue Typescript
vue + typescript + element-ui 支持 markdown 渲染的博客前台展示
Stars: ✭ 1,262 (+621.14%)
Mutual labels:  blog, markdown
Dropplets
Welcome to an easier way to blog - A minimalist markdown blogging platform.
Stars: ✭ 1,616 (+823.43%)
Mutual labels:  blog, markdown

Store & retrieve your static content in plain text files

Latest Version on Packagist GitHub Workflow Status Total Downloads

Sheets is a Laravel package to store, retrieve & index content stored as text files. Markdown & front matter are supported out of the box, but you can parse & extract data from your files in whatever format you prefer.

Sheets can be added to any existing Laravel application and is a perfect fit for documentation sites & personal blogs.

---
title: Home
---
# Hello, world!

Welcome to Sheets!
class SheetController
{
    public function index(Sheets $sheets)
    {
        return view('sheet', [
            'sheet' => $sheets->get('home'),
        ]);
    }

    public function show(string $id, Sheets $sheets)
    {
        return view('sheet', [
            'sheet' => $sheets->get($id),
        ]);
    }
}
@extends('layouts.app', [
    'title' => $sheet->title,
])

@section('main')
    {{ $sheet->contents }}
@endsection

Features

  • Allows any document format (by default Markdown files with front matter)
  • Stores your content wherever you want (uses Laravel's filesystem component)
  • Keeps multiple collections of content (e.g. posts, pages, etc.)
  • Casts your document contents to Eloquent-like classes with accessors
  • Convention over configuration, near-zero setup if you use the defaults

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Installation

You can install the package via composer:

composer require spatie/sheets

Laravel will auto-discover and register the SheetsServiceProvider, so no further setup is required.

After installing, you must publish the sheets.php configuration file:

php artisan vendor:publish --provider="Spatie\Sheets\SheetsServiceProvider" --tag="config"

Finally you must create your first collection.

Usage

The Sheets instance is available through a facade, helper function, or dependency injection.

use Sheets;

Sheets::all();
sheets()->all();
use Spatie\Sheets\Sheets;

class SheetsController
{
    public function index(Sheets $sheets)
    {
        return view('sheets', [
            'sheets' => $sheets->all(),
        ]);
    }
}

Creating your first collection

A collection maps to a folder in your filesystem of choice. Sheets will look for a disk configured in config/filesystems.php with the same name as the collection—or you can configure the disk name yourself.

// config/filesystems.php
return [
    'disks' => [
        // ...
        'posts' => [
            'driver' => 'local',
            'root' => base_path('posts'),
        ],
    ],
];

// config/sheets.php
return [
    'collections' => ['posts'],
];

Sheets will create a repository for the posts folder in your application.

app/
config/
posts/
  hello-world.md
---
title: Hello, world!
---
# Hello, world!

Welcome to Sheets!

A repository has two public methods: all() and get($slug). You can get a repository instance through the collection method on Sheets.

Repository::all() will return an Illuminate\Support\Collection containing Spatie\Sheets\Sheet instances.

$repository = Sheets::collection('posts');

$repository->all();

Repository::get($slug) returns a single Sheet instance or null if nothing was found. A sheet's slug field contains its filename without an extension.

Sheets::collection('posts')->get('hello-world');

A Sheet instance is very similar to an Eloquent model. It holds an array of attributes that are exposed as properties. By default it will contain the path as a slug field, all front matter data, and a contents field containing an HTML representation of the contained Markdown.

$sheet = Sheets::collection('posts')->get('hello-world');

echo $sheet->slug;
// 'hello-world'

echo $sheet->title;
// 'Hello, world!'

echo $sheet->contents;
// '<h1>Hello, world!</h1><p>Welcome to Sheets!</p>'

You can create your own Sheet implementations with accessors just like Eloquent, but we'll dive into that later.

Configuring collections

Sheets is highly configurable. You can configure each collection separately by using an associative array in config/sheets.php.

// config/sheets.php
return [
    'collections' => [
        'pages' => [
            'disk' => null, // Defaults to collection name
            'sheet_class' => Spatie\Sheets\Sheet::class,
            'path_parser' => Spatie\Sheets\PathParsers\SlugParser::class,
            'content_parser' => Spatie\Sheets\ContentParsers\MarkdownWithFrontMatterParser::class,
            'extension' => 'md',
        ],
    ],
];

Above is what a collection's default configuration looks like (the configuration we've been working until now). When configuring a collection, every key is optional, if it doesn't exist, Sheets will use one of these values.

Disk

The disk name where your content is stored. Disks are configured in config/filesystems.php. By default, Sheets will look for a disk with the same name as the collection.

// config/sheets.php
return [
    'collections' => [
        'pages' => [
            'disk' => null, // Uses the 'pages' disk
        ],
    ],
];
// config/sheets.php
return [
    'collections' => [
        'pages' => [
            'disk' => 'sheets', // Uses the 'sheets' disk
        ],
    ],
];

Sheet class

Your content will be casted to Sheet instances. The Sheet class is similar to a trimmed-down Eloquent model: it holds a set of attributes that are available as properties.

$sheet = Sheets::collection('page')->get('hello-world');

echo $sheet->slug;
// 'hello-world'

You can extend the Sheet class to add accessors (just like in Eloquent) and custom behavior.

namespace App;

use Spatie\Sheets\Sheet;

class Page extends Sheet
{
    public function getUrlAttribute(): string
    {
        return url($this->slug);
    }
}
// config/sheets.php
return [
    'collections' => [
        'pages' => [
            'sheet_class' => App\Page::class,
        ],
    ],
];
$sheet = Sheets::collection('pages')->get('hello-world');

echo $sheet->url;
// 'https://example.app/hello-world'

Path parser

Sheets uses the file path to determine part of the Sheet attributes. A path parser is able to parse the path to a set of attributes.

The default path parser is the SlugParser, which simply adds a slug attribute based on the file name.

namespace Spatie\Sheets\PathParsers;

use Spatie\Sheets\PathParser;

class SlugParser implements PathParser
{
    public function parse(string $path): array
    {
        return ['slug' => explode('.', $path)[0]];
    }
}

You can customize the collection's path parser with the path_parser option.

// config/sheets.php
return [
    'collections' => [
        'posts' => [
            'path_parser' => Spatie\Sheets\PathParsers\SlugWithDateParser::class,
        ],
    ],
];

Above, we configured the path parser for posts to the SlugWithDateParser, which allows you to prefix your filenames with a date. This is useful for time-sensitive content like blogs.

posts/
  2018-05-05.my-first-post.md

The above sheet will have two attributes: a date containing an Illuminate\Support\Carbon instance, and a slug my-first-post.

You can write your own path parsers by implementing the Spatie\Sheets\PathParser interface. Path parsers are instantiated through Laravel's container, so you can inject it's dependencies via the __construct method if desired.

Content Parser

Content parsers are similar to path parsers, but are in charge of parsing the file's contents.

The default content parser is the MarkdownWithFrontMatterParser, which extracts front matter and transforms Markdown to HTML.

class MarkdownWithFrontMatterParser implements ContentParser
{
    /** @var \League\CommonMark\CommonMarkConverter */
    protected $commonMarkConverter;

    public function __construct(CommonMarkConverter $commonMarkConverter)
    {
        $this->commonMarkConverter = $commonMarkConverter;
    }

    public function parse(string $contents): array
    {
        $document = YamlFrontMatter::parse($contents);

        return array_merge(
            $document->matter(),
            ['contents' => $this->commonMarkConverter->convertToHtml($document->body())]
        );
    }
}

You can customize the collection's content parser with the content_parser option.

// config/sheets.php
return [
    'collections' => [
        'pages' => [
            'content_parser' => Spatie\Sheets\ContentParsers\MarkdownParser::class,
        ],
    ],
];

Above, we configured the path parser for pages to the MarkdownParser, which parses Markdown files without front matter.

You can write your own content parsers by implementing the Spatie\Sheets\ContentParser interface. Content parsers are instantiated through Laravel's container, so you can inject it's dependencies via the __construct method if desired.

Extension

The file extension used in a collection. Defaults to md.

Default collections

You can call get or all on the Sheets instance without specifying a collection first to query the default collection.

// Return all sheets in the default collection
Sheets::all();

You can specify a default collection in sheets.config. If no default collection is specified, the default collection will be the first collection registered in the collections array.

Here the default collection will implicitly be set to pages:

return [
    'default_collection' => null,

    'collections' => [
        'pages',
    ],
];

Below the default collection is set to pages:

return [
    'default_collection' => 'pages',

    'collections' => [
        'posts',
        'pages',
    ],
];

Route model binding

You can register custom route resolution logic to immediately inject Sheet instances in your controller actions.

// app/Providers/RouteServiceProvider.php

public function boot()
{
    parent::boot();

    Route::bind('sheet', function ($path) {
        return $this->app->make(Spatie\Sheets\Sheets::class)
            ->get($path) ?? abort(404);
    });
}

Now the router will resolve any sheet parameter to a Sheet object.

Route::get('/{sheet}', '[email protected]');

class SheetsController
{
    public function show(Sheet $sheet)
    {
        return view('sheet', ['sheet' => $sheet]);
    }
}

It might be useful to register specific bindings for other collections.

use Spatie\Sheets\Sheets;

Route::bind('post', function ($path) {
    return $this->app->make(Sheets::class)
        ->collection('posts')
        ->get($path) ?? abort(404);
});

The Laravel docs have an entire section on Route Model Binding.

Use subdirectories to organize your sheets

When you want to organize your sheets using (sub)directories, you need to define the route parameter to accept all characters. This way the complete relative path for your sheets will be sent to the controller.

Route::get('/', '[email protected]')->where('sheet', '(.*)');
Route::get('{sheet}', '[email protected]')->where('sheet', '(.*)');

Testing

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].