luckyframework / luckyframework/lucky

Adding a strip_tags helper with allow list capabilities

Open
#1,853 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

hacktoberfest
Dominant language
Crystal
Stars
2.7k
Forks
172
PR merge metrics
No merged PRs in 30d

Description

@robacarp came up with this nice little snippet. Maybe we can just plop it in as a helper method

```crystal
require "xml"

class Sanitize
def self.strip_tags(html, allowed_tags : Array(String), allowed_attributes : Array(String)) : String
instance = new html, allowed_tags, allowed_attributes
instance.strip
instance.render
end

def initialize(@dirty : String, @allowed_tags : Array(String), @allowed_attributes : Array(String))
@io = IO::Memory.new
@builder = XML::Builder.new @io
end

def strip
parsed_document = XML.parse_html @dirty, XML::HTMLParserOptions::NOIMPLIED | XML::HTMLParserOptions::NODEFDTD
traverse parsed_document
end

def render : String
@builder.end_document
@builder.flush
@io.to_s
end

def traverse(node : Nil)
end

def traverse(node : XML::Node) : Nil
if node.text?
@builder.text node.content
return
end

if node.document?
return traverse_children node
end

if ! @allowed_tags.includes? node.name
return traverse_children node
end

stripped_attributes = node.attributes.compact_map do |attribute|
if @allowed_attributes.includes? attribute.name
[attribute.name, attribute.content]
end
end.to_h

@builder.element node.name, attributes: stripped_attributes do
traverse_children node
end
end

def traverse_children(node : XML::Node) : Nil
node.children.each do |child|
traverse child
end
end
end

snippets = [
"

hello

",
"

helo

world

",
"

hello

world

"
]

tags_to_allow = ["a", "p", "b"]
attributes_to_allow = ["href"]

snippets.each do |snippet|
puts "starting: #{snippet}"
puts "finished: #{Sanitize.strip_tags snippet, tags_to_allow, attributes_to_allow}"
puts
end
```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No target file or test is named. Start by locating the framework's helper or utility entry point and existing HTML-sanitization tests, then compare the proposed Crystal Sanitize API and allow-list behavior with project conventions. Done means the helper strips disallowed tags and attributes while preserving allowed content, with coverage for the examples shown.

Written by the indexing model from the issue text.

Assessment

Tech stack
crystal
Domain
security
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.