{"id":24540659,"url":"https://github.com/mistralys/markdown-viewer","last_synced_at":"2025-04-15T08:42:14.044Z","repository":{"id":57017600,"uuid":"348011621","full_name":"Mistralys/markdown-viewer","owner":"Mistralys","description":"PHP based viewer for Markdown files, to view them with fenced code highlighting and navigation.","archived":false,"fork":false,"pushed_at":"2023-07-04T08:17:46.000Z","size":246,"stargazers_count":9,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T03:18:49.482Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mistralys.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-15T14:55:25.000Z","updated_at":"2025-02-25T23:44:52.000Z","dependencies_parsed_at":"2022-08-22T12:00:21.677Z","dependency_job_id":null,"html_url":"https://github.com/Mistralys/markdown-viewer","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mistralys%2Fmarkdown-viewer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mistralys%2Fmarkdown-viewer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mistralys%2Fmarkdown-viewer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mistralys%2Fmarkdown-viewer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mistralys","download_url":"https://codeload.github.com/Mistralys/markdown-viewer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249038887,"owners_count":21202803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-22T18:14:34.512Z","updated_at":"2025-04-15T08:42:14.023Z","avatar_url":"https://github.com/Mistralys.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Markdown documentation viewer\n\nPHP based viewer for Markdown files, to view them with fenced code highlighting and navigation. \n\nIt is designed to be used for viewing markdown-based documentation files, in a fire and forget\nway. The layout is based on [Bootstrap 5](https://getbootstrap.com), and does not need any \nadditional configuration.\n\n## Requirements\n\n- PHP7.4+\n\n## Features\n\n- Automatic jump navigation built using the document's headers.\n- Easily switch between the available documents.\n- Syntax highlighted fenced code blocks.\n- Light and dark modes. \n- Additional support for \"1)\" style ordered lists.\n\n## Installing\n\nThe package is made to be used as a dependency in a documentation project:\nPut it in a folder in a webserver, point it to some markdown files, and it\nwill display them.\n\n1) Create a folder in your webroot from which to serve the documentation.\n2) Create a composer project there.\n3) Require the package: `composer require mistralys/markdown-viewer`.\n4) Create a PHP file (`index.php`) as endpoint for the documentation.\n5) Paste the following code into the file\n6) Edit the list of files you wish to view.\n7) Point your browser to the file.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Mistralys\\MarkdownViewer\\DocsManager;\nuse Mistralys\\MarkdownViewer\\DocsViewer;\n\nif(!file_exists(__DIR__.'/vendor/autoload.php')) {\n    die('Please run \u003ccode\u003ecomposer install\u003c/code\u003e first.');\n}\n\nrequire_once __DIR__.'/vendor/autoload.php';\n\n$manager = new DocsManager();\n\n// Add all the files you wish to view here, along with\n// a title that will be shown in the UI.\n$manager-\u003eaddFile('Title of the file', '/path/to/documentation.md');\n\n// The viewer needs to know the URL to the vendor/ folder, relative\n// to the script. This is needed to load the clientside dependencies,\n// like jQuery and Bootstrap.\n(new DocsViewer($manager, '/url/to/vendor'))\n    -\u003esetTitle('Documentation')\n    -\u003edisplay();\n```\n\n## Adding single files\n\nSingle files can be added using `addFile()`. This allows specifying the\nname that the file will be listed under in the UI.\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsManager;\n\n$manager = new DocsManager();\n\n// Add a single folder, non-recursive.\n$manager-\u003eaddFile('Name of the file', '/path/to/file.md');\n```\n\n## Adding folders\n\nTo add multiple files, use the `addFolder()` method:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsManager;\n\n$manager = new DocsManager();\n\n// Add a single folder, non-recursive.\n$manager-\u003eaddFolder('/path/to/files');\n\n// Add a folder and all its subfolders\n$manager-\u003eaddFolder('/path/to/files', true);\n```\n\nBy default, all files with the `md` extension will be added. A different extension\ncan be specified using the third parameter:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsManager;\n\n$manager = new DocsManager();\n\n// Add all TXT files from a single folder, non-recursive.\n$manager-\u003eaddFolder('/path/to/files', false, 'txt');\n```\n\n  \u003e NOTE: Adding files this way means you cannot specify file IDs (see \"Consistent \n    file permalinks\"). Please double-check that this is okay in your use case.\n\n## Consistent file permalinks\n\nBy default, the viewer will create an ID for each file based on its absolute\npath on disk. This means that the ID will change if the file is moved at some\npoint, or if the viewer is used on different systems. Sharing permalinks risks\nthe links being broken at some point.\n\nTo avoid this issue, specify a unique file ID manually when adding single files:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsManager;\n\n$manager = new DocsManager();\n\n$manager-\u003eaddFile(\n    'Name of the file', \n    '/path/to/file.md',\n    '(Unique file ID)'\n);\n```\n\nThe ID can be any string; the viewer uses it to create the hash that is used in the UI\nto identify the files. This way, permalinks will always stay consistent. \n\n## Dark mode\n\nTo turn on dark mode, simply use `makeDarkMode()`:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsViewer;\nuse Mistralys\\MarkdownViewer\\DocsManager;\n\n$manager = new DocsManager();\n\n// Configure the files\n\n(new DocsViewer($manager, '/url/to/vendor'))\n    -\u003esetTitle('Documentation')\n    -\u003emakeDarkMode()\n    -\u003edisplay();\n```\n\n## Viewing the example\n\nThe bundled example is built exactly like the example above, and will display \nthis `README.md` file. To get it running, follow these steps:\n\n1) Clone the repository into a webserver's document root\n2) Run `composer install` in the package folder to install the dependencies\n3) Point your browser to the package folder's `example.php` file\n\n## Setting options\n\nAll options regarding the parsing of markdown files are handled by the `DocsConfig`\nclass. You can optionally pass a configuration instance to the manager to customize\nsettings:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsManager;\nuse Mistralys\\MarkdownViewer\\DocsConfig;\n\n$config = (new DocsConfig())\n    -\u003eaddIncludePath(__DIR__.'/documentation/includes')\n    -\u003eaddIncludeExtension('php');\n\n$manager = (new DocsManager($config))\n    -\u003eaddFile('Package readme', 'README.md');\n```\n\n## Including external files\n\n### The include command\n\nThe `{include-file}` command allows you to import the content of external files\ninto your documents. This is especially handy for code examples, as it allows\nyou to maintain them separately from the main document.\n\nIf viewed through `example.php`, the following code sample is loaded dynamically, \nfor example:\n\n```php\n{include-file: test-php-highlight.php}\n```\n\nThe command looks like this:\n\n```\n\\{include-file: test-php-highlight.php\\}\n```\n\n\u003e NOTE: It is easy to go overboard with includes. Keep in mind that Markdown files\n\u003e are meant to be read as-is. Splitting them up too much will make them unreadable\n\u003e without the UI. Use them where it makes sense, like for large code samples.\n\n### Setting allowed paths\n\nInclude commands are disallowed by default, as long as no include folders have\nbeen configured:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsConfig;\n\n$config = (new DocsConfig())\n    -\u003eaddIncludePath('/documentation/includes');\n```\n\nPaths in the `{include-file}` command are relative to the configured include paths. \nMultiple folders can be added, and all of them are searched. The first matching file \nname is then used.\n\n### Setting allowed extensions\n\nBy default, **only `md` and `txt` files are allowed** to be included. Additional \nextensions can easily be added:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsConfig;\n\n$config = (new DocsConfig())\n    -\u003eaddIncludeExtension('php');\n```\n\nSeveral extensions can also be added at once:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsConfig;\n\n$extensions = array(\n    'php',\n    'js',\n    'css'\n);\n\n$config = (new DocsConfig())\n    -\u003eaddIncludeExtensions($extensions);\n```\n\n### Restricting file sizes\n\nTo avoid including large files, only **files up to 6Kb may be included** by default. \nThis can be adjusted with the configuration class:\n\n```php\nuse Mistralys\\MarkdownViewer\\DocsConfig;\n\n// Allow files up to 12Kb (12.000 bytes)\n$config = (new DocsConfig())\n    -\u003esetMaxIncludeSize(12000);\n```\n\n### Filtering include file contents\n\nFilters allow the pre-processing of included files before they are rendered by the\nMarkdown renderer. The whole content of the files can be filtered to prepare them\nfor rendering.\n\n#### Example filter class\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse AppUtils\\FileHelper\\FileInfo;\nuse Mistralys\\MarkdownViewer\\DocFile;\nuse Mistralys\\MarkdownViewer\\DocsConfig;\nuse Mistralys\\MarkdownViewer\\Parser\\BaseIncludeFilter;\n\nclass ExampleIncludeFilter extends BaseIncludeFilter\n{\n    public function getExtensions(): array\n    {\n        return array('example');\n    }\n    \n    public function isValidFor(DocFile $sourceFile, DocsConfig $config, FileInfo $includeFile): bool\n    {\n        return true;\n    }\n\n    public function filter(string $content): string\n    {\n        return str_replace('EXAMPLE', '**EXAMPLE**', $content);\n    }\n}\n```\n\nThis filter ensures that all occurrences of `EXAMPLE` in the text are formatted\nas bold text.\n\n#### Adding filters\n\nAdding filters is very easy. Simply add a filter instance to the configuration,\nit will automatically be applied.\n\n```php\n\u003c?php\nuse Mistralys\\MarkdownViewer\\DocsConfig;\n\n$config = (new DocsConfig())\n    -\u003eaddIncludeFilter(new ExampleIncludeFilter());\n```\n\n#### Only filter specific files\n\nBy default, filters are applied to all files that match the filter's file extension(s).\nHowever, if the extension matches, the filter is only applied if the `isValidFor()` \nmethod returns true. This makes it possible to use the provided file and configuration \ninformation to decide whether to filter the content.\n\nThe following example limits the filtering to included files found in the folder \n`/path/to/target/folder`, or any of its subfolders.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse AppUtils\\FileHelper\\FileInfo;\nuse Mistralys\\MarkdownViewer\\DocFile;\nuse Mistralys\\MarkdownViewer\\DocsConfig;\nuse Mistralys\\MarkdownViewer\\Parser\\BaseIncludeFilter;\n\nclass ExampleIncludeFilter extends BaseIncludeFilter\n{\n    public function isValidFor(DocFile $sourceFile, DocsConfig $config, FileInfo $includeFile): bool\n    {\n        return $includeFile-\u003eisWithinPath('/path/to/target/folder');\n    }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmistralys%2Fmarkdown-viewer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmistralys%2Fmarkdown-viewer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmistralys%2Fmarkdown-viewer/lists"}