Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
truncate.lua -- html truncate for luvit lang.
--
-- Created by: Cyril.
-- Created at: 15/6/25 上午12:40
-- Email: houshoushuai@gmail.com
--
local string = require("string")
local find = string.find
_G.indexOf = function(t, x)
if type(t) == 'string' then
return find(t, x, true)
end
for k, v in pairs(t) do
if v == x then
return k
end
end
return nil
end
_G.lastIndexOf = function(t, x)
local idx
if type(t) == "string" then
local i=t:match(".*"..x.."()")
if i==nil then return nil else return i-1 end
end
for k, v in pairs(t) do
if v == x then
idx = k
end
end
return idx
end
_G.pop = function(t)
return table.remove(t)
end
_G.truncate = function(html, option)
option = option or {}
local tolerance = option.tolerance
local image
if type(option.image) == 'boolean' then
image = option.image
else
image = true
end
local maxInt = option.max or 250
local ellipsis = option.ellipsis or "... ..."
local shouldAddEllipsis = false
local tagPartten = "<(%/?)([A-Za-z0-9]+)[^%>]*>"
local escapeTags = {"area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"}
local startTagArray = {}
html = html:gsub(tagPartten, function(a, b)
if b == "script" then
return ""
end
if not(image) then
if b == "img" or b == "figure" then
return ""
end
end
end)
local htmlLen = #html
local i = 0
local bareHtmlLen = 0
while i <= htmlLen and maxInt - bareHtmlLen > 0 do
local afterfix = html:sub(i+1, htmlLen) or ""
local start, stop = afterfix:find(tagPartten)
if not(start or stop) then
bareHtmlLen = maxInt
break
end
local bareHtml = (afterfix:sub(0, start-1) or ""):gsub(tagPartten, function()return "" end)
local _, utfCount = string.gsub(bareHtml, "[^\128-\193]", "")
if maxInt < bareHtmlLen + utfCount then
string.gsub(bareHtml, "([%z\1-\127\194-\244][\128-\191]*)", function(a)
if bareHtmlLen < maxInt then
bareHtmlLen = bareHtmlLen + 1
if #a == 3 then
i = i+3
else
i = i+1
end
end
end)
shouldAddEllipsis = true
else
i = stop + i
bareHtmlLen = bareHtmlLen + utfCount
end
end
html = html:sub(0, i)
local bare = (html or ""):gsub(tagPartten, function(a, b)
if a == "/" then -- End Tag
if indexOf(escapeTags, b) then
else
if startTagArray[#startTagArray] == b then
_G.pop(startTagArray)
else
if tolerance then
-- fault-tolerance
local lastIndex = lastIndexOf(startTagArray, b)
if #startTagArray - lastIndex <= 1 then
_G.pop(startTagArray)
end
end
end
end
else -- Start Tag
if indexOf(escapeTags, b) then
else
table.insert(startTagArray, b)
end
end
return ""
end)
-- fix end tag
local endTagString = ""
for _, v in pairs(startTagArray) do
endTagString = "</".. v .. ">" .. endTagString
end
if #startTagArray and shouldAddEllipsis then
html = html .. " " ..ellipsis
end
html = html .. endTagString
return html
end
-- usage truncate("<p>Hello world <a href="#">link... ...</p></a>", {image = true, ellipsis = "<br/> Read More"})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment