本模块使得可以在页面中嵌入SVG图像。用途包括:实现随wikitext变化的内容;避免小而杂乱的图被上传到共享站;……
本站没有启用<svg>
标签,显示SVG的原理是使用Data URL为<img>
提供源。
参数svg
填SVG代码。前面不要填<?xml …
或<!DOCTYPE svg …
,直接以<svg
开头。
没指定xmlns
的话,会自动加上xmlns="http://www.w3.org/2000/svg"
。
{{svg|svg= <svg width="300" height="200"> <rect width="100%" height="100%" fill="darkturquoise"/> <circle cx="150" cy="100" r="80" fill="cadetblue"/> <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text> </svg> }}
除svg
、src
、srcset
以外的任何参数,如width
、alt
、class
、style
等,会被原封不动地添加到<img>
上。不需要加引号。
{{svg |width=100 |style=border-radius:6px; box-shadow: 0 2px 6px rgba(0, 0, 0, .3); |alt=表情 |svg= <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 93.1 81.3"> <path d="M93.1,44.8v36.5H4.6C0,64.1-.3,51.9,.1,34.3c0-5.9,.3-17.6,5.8-21.7,7,.7,9.8,7.5,16,9.6,9.7-3.7,20.1-4.6,30.1-4.8C58,9.9,62.1,1.5,71.6,0c5.3,2.5,6,7,7.1,11.4,1.6,6.2,2.7,12.5,4.7,18.6,1.9,5.6,3.5,11.8,9.7,14.8Z"/> <circle cx="25.8" cy="47.7" r="9" fill="#fff"/> <circle cx="58.2" cy="42" r="9" fill="#fff"/> <circle cx="22.6" cy="45.6" r="5"/> <circle cx="62" cy="43.6" r="5"/> </svg> }}
作为文字的"
和'
需要换为XML实体("
→"
,'
→'
),否则两者会颠倒。
{{svg|svg= <svg width="300" height="100" style="background:#fff"> <text x="150" y="40" font-size="20" text-anchor="middle">字符:"双引号" '单引号'</text> <text x="150" y="80" font-size="20" text-anchor="middle">实体:"双引号" '单引号'</text> </svg> }}
|
local p = {} local function formSvg(svg) assert(mw.ustring.match(svg, '^<svg[%s>]'), 'svg参数填写错误') --[[ 缩短长度 ]] local SUBSTITUTE = { {'%s+', ' '}, -- 如 <path ... /> -> <path .../> {' ?(</?) ?', '%1'}, {' ?(/?>) ?', '%1'}, -- 如 <path ...></path> -> <path .../> -- ([:%a_][:%w_%-%.]*) - tag name: https://www.w3.org/TR/REC-xml/#NT-Name -- ([^<>]*) - attributes {'<([:%a_][:%w_-.]*)([^<>]*)></%1>', '<%1%2/>'}, } for _i, v in ipairs(SUBSTITUTE) do svg = mw.ustring.gsub(svg, v[1], v[2]) end -- 添加xmlns if not mw.ustring.match(svg, 'xmlns') then svg = '<svg xmlns="http://www.w3.org/2000/svg"' .. string.sub(svg, 5) end return svg end local function formImg(src, attrs) attrs.alt = attrs.alt or 'SVG' local parts = {'<img srcset="', src, '"'} for k, v in pairs(attrs) do table.insert(parts, string.format(' %s="%s"', k, v)) end table.insert(parts, ">") return table.concat(parts) end --[[ -- 该函数借鉴了Taylor Hunt的https://github.com/tigt/mini-svg-data-uri --]] function p.toDataUrl(str) local PATTERN = { -- strip marker格式: -- \127'"`UNIQ--标签-8个16进制数-QINU`"'\127 -- 匹配(用PCRE格式表示,看得清楚些): -- \127'"`UNIQ--(.+?-.+?)-QINU`"'\127 stripMarker = '%%7F%%27%%22%%60UNIQ%-%-(.-%-.-)%-QINU%%60%%22%%27%%7F', hexEncode = '%%%x%x', } local ACCEPTABLE = { ['%22'] = "'", -- 把编码后"换成未编码的' ['%27'] = '%22', -- 把编码后'换成编码后的" ['%28'] = '(', ['%29'] = ')', ['%2C'] = ',', ['%2F'] = '/', ['%3A'] = ':', ['%3D'] = '=', } str = mw.uri.encode(str, 'PATH') -- 恢复strip marker str = string.gsub(str, PATTERN.stripMarker, '\127\'"`UNIQ--%1-QINU`"\'\127') -- 替换部分编码回原字符,减小文件体积 str = string.gsub(str, PATTERN.hexEncode, ACCEPTABLE) return "data:image/svg+xml," .. str end function p._main(args) local allArgs = {} for k, v in pairs(args) do allArgs[string.lower(k)] = v end local svg = formSvg(allArgs.svg) local NOT_IMG_ATTR = { 'svg', -- 并非用于<img> 'src', 'srcset', 'sizes' -- 不由用户指定 } for _i, attr in ipairs(NOT_IMG_ATTR) do allArgs[attr] = nil end return formImg(p.toDataUrl(svg), allArgs) end function p.main(frame) local parent = frame:getParent() if parent and parent:getTitle() == 'Template:Svg' then frame = parent end return p._main(frame.args) end return p