{"id":17766475,"url":"https://github.com/dmitry/acts_as_sanitiled","last_synced_at":"2025-10-23T15:24:13.118Z","repository":{"id":5008204,"uuid":"6166576","full_name":"dmitry/acts_as_sanitiled","owner":"dmitry","description":" acts_as_sanitiled","archived":false,"fork":false,"pushed_at":"2012-10-11T00:33:55.000Z","size":152,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-07T08:49:13.746Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","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/dmitry.png","metadata":{"files":{"readme":"README.rdoc","changelog":"CHANGELOG","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":"2012-10-11T00:33:04.000Z","updated_at":"2013-12-06T05:54:46.000Z","dependencies_parsed_at":"2022-09-02T05:41:40.226Z","dependency_job_id":null,"html_url":"https://github.com/dmitry/acts_as_sanitiled","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmitry%2Facts_as_sanitiled","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmitry%2Facts_as_sanitiled/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmitry%2Facts_as_sanitiled/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmitry%2Facts_as_sanitiled/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmitry","download_url":"https://codeload.github.com/dmitry/acts_as_sanitiled/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246651816,"owners_count":20812030,"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":"2024-10-26T20:30:13.538Z","updated_at":"2025-10-23T15:24:13.007Z","avatar_url":"https://github.com/dmitry.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Acts as Sanitiled\n\nThis plugin, based on Chris Wanstrath's venerable acts_as_textiled, extends the automatic textiling functionality to sanitization as well using as its basis Ryan Grove's powerful yet simple Sanitize gem.\n\n*Important Development Status Update* There used to be a paragraph here about why I liked this approach, but I've come to disagree with it over time.  First, generally because the Rails 3 / rails_xss approach of tainted strings is ultimately better than the bandaid that this provided.  But specifically because the cleverness of the solution outweighs its usefulness.  It's a lot of hacking around internals simply to avoid calling a helper in a view, which while easy to forget, does not usually appear in all that many places or change all that often.  Meanwhile, the internals of the model carry significantly more complexity, and suffer irredeemable breakages when you introduce something like I18n with Globalize2.  Aside from that, any gains that were made are erased the minute you need to emit something other than HTML.  With that in mind, I am still maintaining acts_as_sanitiled to the extent I need it, but I am no longer sanctioning the approach, and I would recommend deprecating your usage of the plugin.\n\n== Requirements\n\nThe officially sanctioned requirements are:\n\n* Sanitize \u003e1.1.0 (prior versions had a whitespace issue)\n* RedCloth \u003e4.1.0\n* ActiveRecord (tested on 2.3.10)\n\nHowever there are a lot of little aberrations in output when you start mixing and matching versions of the various moving parts.  Most recently I am working with REE 1.8.7, Sanitize 2.0.0, RedCloth 4.2.5, and Nokogiri 1.4.4, and I make sure specs pass with that mix.  With other versions things should still work but the output might be slightly different (see known issues)\n\n== Installation\n\n  gem install acts_as_sanitiled\n\n== Known Issues\n\nLine breaks sometime disappear from output which breaks the :plain output.  This issue was not present under 1.8.6, Sanitize 1.1.0 and Nokogiri 1.4.0, but when I switched to 1.8.7 it appears.  I never tracked down the cause, so keep an eye out for this one.\n\nXHTML vs HTML output.  This changed when I upgraded to Sanitize 2.0.0 and Nokogiri 1.4.4.  This must have become the default somewhere, which is fine with me since HTML 5 is the future.  Specs upgraded accordingly.\n\n== Changes from acts_as_textiled\n\nacts_as_sanitiled mostly maintains the API, but one noticeable difference is that it needs to expose the Sanitize config.  Therefore acts_as_textiled use of a hash to provide per-column RedCloth configuration had to be replaced with Sanitize config. RedCloth options can still be passed as an array that applies to all fields listed.\n\nThe other big change is that acts_as_sanitiled uses Sanitize which outputs utf8 rather than HTML entities.  For my own purposes this is preferable anyway, but it might give someone a few headaches getting encoding issues.  My advice: take your lumps now and figure out your encoding pipelines.\n\n== Usage\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_sanitiled :body_text, :description\n  end\n\n  \u003e\u003e story = Story.find(3)\n  =\u003e #\u003cStory:0x245fed8 ... \u003e\n\n  \u003e\u003e story.description\n  =\u003e \"\u003cp\u003eThis is \u003cstrong\u003ecool\u003c/strong\u003e.\u003c/p\u003e\"\n\n  \u003e\u003e story.description(:source)\n  =\u003e \"This is *cool*.\"\n\n  \u003e\u003e story.description(:plain)\n  =\u003e \"This is cool.\"\n\n  \u003e\u003e story.description = \"I _know_!\"\n  =\u003e \"I _know_!\"\n\n  \u003e\u003e story.save\n  =\u003e true\n\n  \u003e\u003e story.description\n  =\u003e \"\u003cp\u003eI \u003cem\u003eknow\u003c/em\u003e!\u003c/p\u003e\"\n\n  \u003e\u003e story.textiled = false\n  =\u003e false\n\n  \u003e\u003e story.description\n  =\u003e \"I _know_!\"\n\n  \u003e\u003e story.textiled = true\n  =\u003e true\n\n  \u003e\u003e story.description\n  =\u003e \"\u003cp\u003eI \u003cem\u003eknow\u003c/em\u003e!\u003c/p\u003e\"\n\n== Different Modes\n\nSanitize supports a detailed configuration hash describing what HTML is allowed (among\nother things). This can be passed at the end of the declaration.  See the Sanitize docs\nfor more information.\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_sanitiled :body_text, :elements =\u003e ['em','strong','div'], :attributes =\u003e {'div' =\u003e ['class','id']}\n  end\n\nRedCloth supports different modes, such as :lite_mode.  To use a mode on\na specific attribute simply pass one or more options in an array after the field names.  Like so:\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_sanitiled :body_text, :description, [ :lite_mode ]\n  end\n\nOf course you can combine them as well:\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_sanitiled :body_text, :description, [ :lite_mode ], :elements =\u003e ['a'], :add_attributes =\u003e {'a' =\u003e {'rel' =\u003e 'nofollow'}}\n  end\n\nSuppose you want to sanitize but not textilize:\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_sanitized :body_text, :elements =\u003e ['br', 'p']\n  end\n\nOr vice-versa:\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_textilized :body_text, [ :lite_mode ]\n  end\n\n== Default options\n\nMost likely you want to use the same options throughout your application, but perhaps not the same options I like.  You can set the default options for both Sanitize and RedCloth like so.\n\n  ActsAsSanitiled.default_redcloth_options = [:no_span_caps]\n  ActsAsSanitiled.default_sanitize_options = {:elements =\u003e ['em','strong','p','br']}\n\nThis should be done in +environment.rb+ or an initializer so it will run before your ActiveRecord classes are defined.\n\n== form_for\n\nAre you using form_for?  If you are, you don't have to change any code at all.\n\n  \u003c% form_for :story, @story do |f| %\u003e\n    Description: \u003cbr/\u003e \u003c%= f.text_field :description %\u003e\n  \u003c% end %\u003e\n\nYou'll see the Textile plaintext in the text field.  It Just Works.\n\n== form tags\n\nIf you're being a bit unconvential, no worries.  You can still get at your\nraw Textile like so:\n\n  Description: \u003cbr/\u003e \u003c%= text_field_tag :description, @story.description(:source) %\u003e\n\nAnd there's always object.textiled = false, as demo'd above.\n\n== Pre-fetching\n\nacts_as_sanitiled locally caches rendered HTML once the attribute in question has\nbeen requested.  Obviously this doesn't bode well for marshalling or caching.\n\nIf you need to force your object to build and cache HTML for all textiled attributes,\ncall the +textilize+ method on your object.\n\nIf you're real crazy you can even do something like this:\n\n  class Story \u003c ActiveRecord::Base\n    acts_as_sanitiled :body_text, :description\n\n    def after_find\n      textilize\n    end\n  end\n\nAll your Textile will now be ready to go in spiffy HTML format.  But you probably\nwon't need to do this.\n\nEnjoy.\n\n* By Chris Wanstrath [ chris[at]ozmm[dot]org ]\n* Butchered and Sanitized by Gabe da Silveira [ gabe[at]websaviour[dot]com ]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmitry%2Facts_as_sanitiled","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmitry%2Facts_as_sanitiled","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmitry%2Facts_as_sanitiled/lists"}