{"id":13593468,"url":"https://github.com/stevebauman/purify","last_synced_at":"2025-05-14T06:11:38.729Z","repository":{"id":31619103,"uuid":"35184153","full_name":"stevebauman/purify","owner":"stevebauman","description":"A Laravel wrapper for HTMLPurifier by ezyang","archived":false,"fork":false,"pushed_at":"2025-02-18T23:08:54.000Z","size":207,"stargazers_count":468,"open_issues_count":0,"forks_count":36,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-11T00:48:25.647Z","etag":null,"topics":["html-purifier","html-sanitizer","laravel","php"],"latest_commit_sha":null,"homepage":"","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/stevebauman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-05-06T21:36:19.000Z","updated_at":"2025-04-10T05:16:47.000Z","dependencies_parsed_at":"2023-02-19T02:30:47.893Z","dependency_job_id":"3d1bb698-3da3-4e55-b820-a7b0351cbd3c","html_url":"https://github.com/stevebauman/purify","commit_stats":{"total_commits":221,"total_committers":18,"mean_commits":"12.277777777777779","dds":"0.23076923076923073","last_synced_commit":"a449299a3d5f5f8ef177e626721b3f69143890a4"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevebauman%2Fpurify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevebauman%2Fpurify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevebauman%2Fpurify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stevebauman%2Fpurify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stevebauman","download_url":"https://codeload.github.com/stevebauman/purify/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254080001,"owners_count":22011307,"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":["html-purifier","html-sanitizer","laravel","php"],"created_at":"2024-08-01T16:01:20.577Z","updated_at":"2025-05-14T06:11:38.708Z","avatar_url":"https://github.com/stevebauman.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ePurify\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\nA Laravel wrapper for \u003ca href=\"https://github.com/ezyang/htmlpurifier\" target=\"_blank\"\u003eHTMLPurifier\u003c/a\u003e by \u003ca href=\"https://github.com/ezyang\" target=\"_blank\"\u003eezyang\u003c/a\u003e.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://github.com/stevebauman/purify/actions\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/stevebauman/purify/run-tests.yml?branch=master\u0026style=flat-square\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://packagist.org/packages/stevebauman/purify\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/packagist/v/stevebauman/purify.svg?style=flat-square\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://packagist.org/packages/stevebauman/purify\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/packagist/dt/stevebauman/purify.svg?style=flat-square\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://packagist.org/packages/stevebauman/purify\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/packagist/l/stevebauman/purify.svg?style=flat-square\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n### Index\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [Cache](#cache)\n- [Practices](#practices)\n- [Upgrading from v4 to v5](#upgrading-from-v4-to-v5)\n- [Upgrading from v5 to v6](#upgrading-from-v5-to-v6)\n\n### Requirements\n\n-   PHP \u003e= 7.4\n-   Laravel \u003e= 7.0\n\n### Installation\n\nTo install Purify, run the following command in the root of your project:\n\n```bash\ncomposer require stevebauman/purify\n```\n\nThen, publish the configuration file using:\n\n```bash\nphp artisan vendor:publish --provider=\"Stevebauman\\Purify\\PurifyServiceProvider\"\n```\n\n### Usage\n\n##### Cleaning a String\n\nTo clean a users input, simply use the clean method:\n\n```php\nuse Stevebauman\\Purify\\Facades\\Purify;\n\n$input = '\u003cscript\u003ealert(\"Harmful Script\");\u003c/script\u003e \u003cp style=\"border:1px solid black\" class=\"text-gray-700\"\u003eTest\u003c/p\u003e';\n\n// Returns '\u003cp\u003eTest\u003c/p\u003e'\n$cleaned = Purify::clean($input);\n```\n\n##### Cleaning an Array\n\nNeed to purify an array of user input? Just pass in an array:\n\n```php\nuse Stevebauman\\Purify\\Facades\\Purify;\n\n$array = [\n    '\u003cscript\u003ealert(\"Harmful Script\");\u003c/script\u003e \u003cp style=\"border:1px solid black\" class=\"text-gray-700\"\u003eTest\u003c/p\u003e',\n    '\u003cscript\u003ealert(\"Harmful Script\");\u003c/script\u003e \u003cp style=\"border:1px solid black\" class=\"text-gray-700\"\u003eTest\u003c/p\u003e',\n];\n\n$cleaned = Purify::clean($array);\n\n// array [\n//  '\u003cp\u003eTest\u003c/p\u003e',\n//  '\u003cp\u003eTest\u003c/p\u003e',\n// ]\nvar_dump($cleaned);\n```\n\n##### Dynamic Configuration\n\nNeed a different configuration for a single input? Pass in a configuration array into the second parameter:\n\n\u003e **Note**: Configuration passed into the second parameter\n\u003e is **not** merged with your default configuration.\n\n```php\nuse Stevebauman\\Purify\\Facades\\Purify;\n\n$config = ['HTML.Allowed' =\u003e 'div,b,a[href]'];\n\n$cleaned = Purify::config($config)-\u003eclean($input);\n```\n\n### Configuration\n\nInside the configuration file, multiple HTMLPurifier configuration sets\ncan be specified, similar to Laravel's built-in `database`, `mail` and `logging` config.\nSimply call `Purify::config($name)-\u003eclean($input)` to use another set of configuration.\n\nFor example, if we need to have a separate configuration for a comment system, we\ncan setup this configuration in the `config/purify.php` file:\n\n```php\n// config/purify.php\n\n'configs' =\u003e [\n    // ...\n\n    'comments' =\u003e [\n        // Some configuration ...\n    ],\n]\n```\n\nThen, utilize it anywhere in your application by its name:\n\n```php\nuse Stevebauman\\Purify\\Facades\\Purify;\n\n$cleanedContent = Purify::config('comments')-\u003eclean(request('content'));\n```\n\nFor HTMLPurifier configuration documentation, please visit the HTMLPurifier Website:\n\nhttp://htmlpurifier.org/live/configdoc/plain.html\n\n### Cache\n\nAfter running Purify once, [HTMLPurifier](https://github.com/ezyang/htmlpurifier) will auto-cache your\nserialized `definitions` into the `serializer.cache` definition you have configured in `config/purify.php`.\n\n\u003e [!Important]\n\u003e\n\u003e If you have configured Purify to utilize the `CacheDefinitionCache` in the `serializer` option, \n\u003e this command will issue a `Cache::clear()` on the cache driver you have configured it to use.\n\u003e \n\u003e If you have configured Purify to utilize the `FilesystemDefinitionCache` in the `serializer` option, \n\u003e this command will clear the directory that you have configured it to store in.\n\u003e\n\u003e It is recommended to setup a unique filesystem path or disk (via `config/filesystems.php`) or cache store \n\u003e (via `config/cache.php`) for Purify if you intended to clear the serialized definitions using this command.\n\nIf you ever update the `definitions` configuration option, you must clear this HTMLPurifier cache.\n\nYou may do so via a `purify:clear` command:\n\n```shell\nphp artisan purify:clear\n```\n\n#### Disabling Caching\n\nTo disable caching all together, you may set the `serializer` path to `null`:\n\n```php\n// config/purify.php\n\n'serializer' =\u003e null,\n```\n\nThis will cause your definitions to be serialized upon each application request.\n\nThis is especially useful when debugging or tweaking definition files to see immediate results.\n\n\u003e [!Important]\n\u003e\n\u003e Caching is recommended in production environments.\n\n### Practices\n\nIf you're looking into sanitization, you're likely wanting to sanitize inputted user HTML\ncontent that is then stored in your database to be rendered onto your application.\n\nIn this scenario, it's likely best practice to sanitize on the _way out_ instead of\nthe on the _way in_. The **database doesn't care what text it contains**.\n\nThis way you can allow anything to be inserted in the database, and have strong sanization rules on the way out.\n\nTo accomplish this, you may use the provided `PurifyHtmlOnGet` cast class on your Eloquent model:\n\n```php\nuse Stevebauman\\Purify\\Casts\\PurifyHtmlOnGet;\n\nclass Post extends Model\n{\n    protected $casts = [\n        'content' =\u003e PurifyHtmlOnGet::class,\n    ];\n}\n```\n\nOr, implement it yourself via an Eloquent attribute mutator:\n\n```php\nuse Stevebauman\\Purify\\Facades\\Purify;\n\nclass Post extends Model\n{\n    public function getContentAttribute($value)\n    {\n        return Purify::clean($value);\n    }\n}\n```\n\nYou can even configure the configuration that is used when casting by appending it's name to the cast:\n\n```php\n// config/purify.php\n\n'configs' =\u003e [\n    // ...\n\n    'other' =\u003e [\n        // Some configuration ...\n    ],\n]\n```\n\n```php\nprotected $casts = [\n    'content' =\u003e PurifyHtmlOnGet::class.':other',\n];\n```\n\nThis helps tremendously if you change your sanization requirements later down\nthe line, then all rendered content will follow these sanization rules.\n\nIf you'd like to purify HTML while setting the value, you can use the inverse `PurifyHtmlOnSet` cast instead.\n\n#### Custom HTML definitions\n\nThe `HTML.Doctype` configuration option denotes the schema to ultimately abide to.\nYou may want to extend these schema definitions to support custom elements or\nattributes (e.g. `\u003cfoo\u003e...\u003c/foo\u003e`, or `\u003cspan foo=\"...\"\u003e`) by specifying a\ncustom HTML element \"definitions\".\n\nPurify ships with additional HTML5 definitions that HTMLPurifier does\nnot (yet) support of the box (via the `Html5Definition` class).\n\nTo create your own HTML definition, create a new class and have it implement `Definition`:\n\n```php\nnamespace App;\n\nuse HTMLPurifier_HTMLDefinition;\nuse Stevebauman\\Purify\\Definitions\\Definition;\n\nclass CustomDefinition implements Definition\n{\n    /**\n     * Apply rules to the HTML Purifier definition.\n     *\n     * @param HTMLPurifier_HTMLDefinition $definition\n     *\n     * @return void\n     */\n    public static function apply(HTMLPurifier_HTMLDefinition $definition)\n    {\n        // Customize the HTML purifier definition.\n    }\n}\n```\n\nThen, reference this class in the `config/purify.php` file in the `definitions` key:\n\n```php\n// config/purify.php\n\n'definitions' =\u003e \\App\\CustomDefinitions::class,\n```\n\nIf you'd like to extend the built-in default `Html5Definition`, you can apply it to your custom definition:\n\n```php\nuse Stevebauman\\Purify\\Definitions\\Html5Definition;\n\nclass CustomDefinition implements Definition\n{\n    public static function apply(HTMLPurifier_HTMLDefinition $definition)\n    {\n        Html5Definition::apply($definition);\n        \n        // ...\n    }\n}\n```\n\n##### Basecamp Trix Definition\n\nHere's an example for customizing the definition in order to support Basecamp's Trix WYSIWYG editor\n(credit to [Antonio Primera](https://github.com/stevebauman/purify/issues/7) \u0026 [Daniel Sun](https://github.com/stevebauman/purify/issues/77)):\n\n```php\nnamespace App;\n\nuse HTMLPurifier_HTMLDefinition;\nuse Stevebauman\\Purify\\Definitions\\Definition;\n\nclass TrixPurifierDefinitions implements Definition\n{\n    /**\n     * Apply rules to the HTML Purifier definition.\n     *\n     * @param HTMLPurifier_HTMLDefinition $definition\n     *\n     * @return void\n     */\n    public static function apply(HTMLPurifier_HTMLDefinition $definition)\n    {\n        $definition-\u003eaddElement('figure', 'Inline', 'Inline', 'Common');\n        $definition-\u003eaddAttribute('figure', 'class', 'Class');\n        $definition-\u003eaddAttribute('figure', 'data-trix-attachment', 'Text');\n        $definition-\u003eaddAttribute('figure', 'data-trix-attributes', 'Text');\n\n        $definition-\u003eaddElement('figcaption', 'Inline', 'Inline', 'Common');\n        $definition-\u003eaddAttribute('figcaption', 'class', 'Class');\n        $definition-\u003eaddAttribute('figcaption', 'data-trix-placeholder', 'Text');\n\n        $definition-\u003eaddAttribute('a', 'rel', 'Text');\n        $definition-\u003eaddAttribute('a', 'tabindex', 'Text');\n        $definition-\u003eaddAttribute('a', 'contenteditable', 'Enum#true,false');\n        $definition-\u003eaddAttribute('a', 'data-trix-attachment', 'Text');\n        $definition-\u003eaddAttribute('a', 'data-trix-content-type', 'Text');\n        $definition-\u003eaddAttribute('a', 'data-trix-id', 'Number');\n\n        $definition-\u003eaddElement('span', 'Block', 'Flow', 'Common');\n        $definition-\u003eaddAttribute('span', 'data-trix-cursor-target', 'Enum#right,left');\n        $definition-\u003eaddAttribute('span', 'data-trix-serialize', 'Enum#true,false');\n\n        $definition-\u003eaddAttribute('img', 'data-trix-mutable', 'Enum#true,false');\n        $definition-\u003eaddAttribute('img', 'data-trix-store-key', 'Text');\n    }\n}\n```\n\n\n#### Custom CSS definitions\n\nIt's possible to override the CSS definitions, this allows you to customize what\ninline styles you allow and their properties and values. This can help fill in\nmissing values for properties such as text-align, which by default is missing start\nand end values. You can do this by creating a CSS definition.\n\nTo create your own CSS definition, create a new class and have it implement `CssDefinition`:\n\n```php\nnamespace App;\n\nuse HTMLPurifier_CSSDefinition;\nuse Stevebauman\\Purify\\Definitions\\CssDefinition;\n\nclass CustomCssDefinition implements CssDefinition\n{\n    /**\n     * Apply rules to the CSS Purifier definition.\n     *\n     * @param HTMLPurifier_CSSDefinition $definition\n     *\n     * @return void\n     */\n    public static function apply(HTMLPurifier_CSSDefinition $definition)\n    {\n        // Customize the CSS purifier definition.\n        $definition-\u003einfo['text-align'] = new \\HTMLPurifier_AttrDef_Enum(\n            ['right', 'left', 'center', 'start', 'end'],\n            false,\n        );\n    }\n}\n```\n\nThen, reference this class in the `config/purify.php` file in the `css-definitions` key:\n\n```php\n// config/purify.php\n\n'css-definitions' =\u003e \\App\\CustomCssDefinition::class,\n```\n\nSee the class HTMLPurifier_CSSDefinition in the HTMLPurifier library for other examples of what can be changed.\n\n### Upgrading from v4 to v5\n\nTo upgrade from v4, install the latest version by running the below command in the root of your project:\n\n```bash\ncomposer require stevebauman/purify\n```\n\nThen, navigate into your published `config/purify.php` configuration file and\ncopy the `settings` array -- except for the following keys:\n\n-   `HTML.DocType`:\n-   `Core.Encoding`:\n-   `Cache.SerializerPath`:\n\n```diff\n'settings' =\u003e [\n-   'Core.Encoding' =\u003e 'utf-8',\n-   'Cache.SerializerPath' =\u003e storage_path('app/purify'),\n-   'HTML.Doctype' =\u003e 'XHTML 1.0 Strict',\n+   'HTML.Allowed' =\u003e 'h1,h2,h3,h4,h5,h6,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',\n+   'HTML.ForbiddenElements' =\u003e '',\n+   'CSS.AllowedProperties' =\u003e 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',\n+   'AutoFormat.AutoParagraph' =\u003e false,\n+   'AutoFormat.RemoveEmpty' =\u003e false,\n],\n```\n\n\u003e **Important**: If you've created a unique storage path for `Cache.SerializerPath`,\n\u003e take note of this as well, so you can migrate it into the new configuration file.\n\nOnce copied, delete the `config/purify.php` file, and run the below command:\n\n```bash\nphp artisan vendor:publish --provider=\"Stevebauman\\Purify\\PurifyServiceProvider\"\n```\n\nThen, inside the newly published `config/purify.php` configuration file, paste\nthe keys (overwriting the current) into the `configs.default` array:\n\n```diff\n'configs' =\u003e [\n    'default' =\u003e [\n        'Core.Encoding' =\u003e 'utf-8',\n        'HTML.Doctype' =\u003e 'HTML 4.01 Transitional',\n+       'HTML.Allowed' =\u003e 'h1,h2,h3,h4,h5,h6,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',\n+       'HTML.ForbiddenElements' =\u003e '',\n+       'CSS.AllowedProperties' =\u003e 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',\n+       'AutoFormat.AutoParagraph' =\u003e false,\n+       'AutoFormat.RemoveEmpty' =\u003e false,\n    ],\n],\n```\n\nIf you've created a unique serializer path (previously set via the old `Cache.SerializerPath` configuration\nkey mentioned above), then you may reconfigure this in the new `serializer` configuration key:\n\n```php\n'serializer' =\u003e storage_path('app/purify'),\n```\n\nYou're all set!\n\n### Upgrading from v5 to v6\n\nIn v6, the HTMLPurifier Serializer storage mechanism was updated for Laravel Vapour support, allowing \nyou to store the serialized HTMLPurifier definitions in a Redis cache, or an external filesystem.\n\nTo upgrade from v5, install the latest version by running the below command in the root of your project:\n\n```bash\ncomposer require stevebauman/purify\n```\n\nThen, navigate into your published `config/purify.php` configuration file and \nreplace the `serializer` configuration option with the below:\n\n```diff\n-    'serializer' =\u003e storage_path('app/purify'),\n\n+    'serializer' =\u003e [\n+       'disk' =\u003e env('FILESYSTEM_DISK', 'local'),\n+       'path' =\u003e 'purify',\n+       'cache' =\u003e \\Stevebauman\\Purify\\Cache\\FilesystemDefinitionCache::class,\n+    ],\n+\n+    // 'serializer' =\u003e [\n+    //    'driver' =\u003e env('CACHE_DRIVER', 'file'),\n+    //    'cache' =\u003e \\Stevebauman\\Purify\\Cache\\CacheDefinitionCache::class,\n+    // ],\n```\n\nThis will update the syntax used to control the serializer cache mechanism. You may now uncomment \nthe below `serializer` cache definition if you would like to use a Laravel Cache driver\n(such as Redis) to store the serialized definitions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevebauman%2Fpurify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstevebauman%2Fpurify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstevebauman%2Fpurify/lists"}