aphillipo
Excerpt implementation for Floki
Hello there! I’ve been working on an Excerpt implementation on top of Floki that greedily includes tags. I’d love for the next step to be able to preserve tags but this is a good starting point; any advice on that welcome.
Let me know if there is anything I could improve or if there are any performance issues I’m encountering by using recursion for this. It’s also worth noting this is an adaption
of the DeepText search that comes with Floki for my own needs.
defmodule PayPip.Text do
@moduledoc """
PayPip.Text is a strategy to get text nodes from a HTML tree using a deep search
algorithm limited to a certain length + the full content of the final node. It will
get all string nodes and concat them into an accumulator up to that point.
"""
@type html_tree :: tuple | list
@doc """
Get text nodes of a desired length + final node length.
## Examples
iex> PayPip.Text.get([{"a", [], ["The meaning of life is...", {"strong", [], ["something else"]}] }], 5)
{"The meaning of life is...", 20}
iex> PayPip.Text.get([{"a", [], ["The meaning of life is...", {"strong", [], ["something else"]}] }], 140, " ")
{"The meaning of life is... something else", -101}
"""
@spec get(html_tree, number, binary) :: {binary, number}
def get(html_tree, max_length \\ 255, sep \\ "") do
get_text(html_tree, {"", max_length}, sep)
end
# initial piece of text
defp get_text(text, {"", max_length}, _sep) when is_binary(text), do: {text, max_length - String.length(text)}
# all other text
defp get_text(text, {acc, max_length}, sep) when is_binary(text) do
{Enum.join([acc, text], sep), max_length - String.length(text)}
end
# deal with nodes lists and sort out over count to be correct (negative when under original max_length)
defp get_text(nodes, {acc, max_length}, sep) when is_list(nodes) do
Enum.reduce_while nodes, {acc, max_length}, fn(child, istr) ->
if max_length > 0 do
{final_acc, final_length} = get_text(child, istr, sep)
{:cont, {final_acc, -final_length}}
else
{:halt, {acc, -max_length}}
end
end
end
# ignore comments
defp get_text({:comment, _}, {acc, max_length}, _), do: {acc, max_length}
# turn BR tags into new lines
defp get_text({"br", _, _}, {acc, max_length}, _), do: {acc <> "\n", max_length - 1}
# process children
defp get_text({_, _, nodes}, acc, sep) do
get_text(nodes, acc, sep)
end
end
Popular in Libraries
I’d like to announce a small library called boundaries.
This is an experimental project which explores the idea of enforcing boundaries ...
New
Just looking for a little feedback on a tiny helper library I built -
Sometimes I find the need to convert maps with atom keys to maps...
New
Only 650 LOC, wrote for fun :slight_smile:
New
In short
Plug n’ play OAuth 2.0 provider library. Just set up a resource owner schema with Ecto (your user schema), install the dependen...
New
I’ve published the first version of my Makeup library. It’s a syntax highlighter for Elixir in the spirit of Pygments, Currently it highl...
New
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries.
offset-based pagination with...
New
Hi! Today, after a couple weeks of development I’ve released v0.1 of LiveVue.
It’s a seamless integration of Vue and Phoenix LiveView, i...
New
PhoenixWS - Websockets over Phoenix Channels
Source code on Github here: https://github.com/tmbb/phoenix_ws
Phoenix channels are a great...
New
import Meeseeks.CSS
html = HTTPoison.get!("https://news.ycombinator.com/").body
for story <- Meeseeks.all(html, css("tr.athing")) do...
New
Prometheus metrics and Grafana dashboards for all of your favorite Elixir libraries
I have been put...
New
Other popular topics
Hello!
tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability.
After spen...
New
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine)
This is a plugin that adds support for Elixir to JetBrains IntelliJ...
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set?
Thanks.
New
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch.
This project took far...
New
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
I have a super simple question about elixir - how would I take a file like this
foo bar baz
and output a new file that enumerates th...
New
Hey :wave:t3: Elixir community,
I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New







