Last active
September 5, 2015 06:19
-
-
Save cyrilis/3a7577ca29561f7b9df6 to your computer and use it in GitHub Desktop.
truncate.lua -- html truncate for luvit lang.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | |
-- Created by: Cyril. | |
-- Created at: 15/6/25 上午12:40 | |
-- Email: [email protected] | |
-- | |
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