Anda dapat membuat halaman dokumentasi untuk buat pada modul Scribunto ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
localyesNo=require("Modul:Yesno") localText={serial="2024-09-21", suite="Text"} --[=[ Text utilities ]=] localfunctionfiatQuote(apply,alien,advance) -- Quote text -- Parameter: -- apply -- string, with text -- alien -- string, with language code -- advance -- number, with level 1 or 2 localr=applyandtostring(apply)or"" alien=alienor"en" advance=tonumber(advance)or0 localsuite localdata=mw.loadData('Modul:Text/data') localQuoteLang=data.QuoteLang localQuoteType=data.QuoteType localslang=alien:match("^(%l+)-") suite=QuoteLang[alien]orslangandQuoteLang[slang]orQuoteLang["en"] ifsuitethen localquotes=QuoteType[suite] ifquotesthen localspace ifquotes[3]then space=" " else space="" end quotes=quotes[advance] ifquotesthen r=mw.ustring.format("%s%s%s%s%s", mw.ustring.char(quotes[1]), space, apply, space, mw.ustring.char(quotes[2])) end else mw.log("fiatQuote() "..suite) end end returnr end-- fiatQuote() Text.char=function(apply,again,accept) -- Create string from codepoints -- Parameter: -- apply -- table (sequence) with numerical codepoints, or nil -- again -- number of repetitions, or nil -- accept -- true, if no error messages to be appended -- Returns: string localr="" apply=type(apply)=="table"andapplyor{} again=math.floor(tonumber(again)or1) ifagain<1then return"" end localbad={} localcodes={} for_,vinipairs(apply)do localn=tonumber(v) ifnotnor(n<32andn~=9andn~=10)then table.insert(bad,tostring(v)) else table.insert(codes,math.floor(n)) end end if#bad>0then ifnotacceptthen r=tostring(mw.html.create("span") :addClass("error") :wikitext("titik kode tidak valid: "..table.concat(bad," "))) end returnr end if#codes>0then r=mw.ustring.char(unpack(codes)) ifagain>1then r=r:rep(again) end end returnr end-- Text.char() localfunctiontrimAndFormat(args,fmt) localresult={} iftype(args)~='table'then args={args} end for_,vinipairs(args)do v=mw.text.trim(tostring(v)) ifv~=""then table.insert(result,fmtandmw.ustring.format(fmt,v)orv) end end returnresult end Text.concatParams=function(args,apply,adapt) -- Concat list items into one string -- Parameter: -- args -- table (sequence) with numKey=string -- apply -- string (optional); separator (default: "|") -- adapt -- string (optional); format including "%s" -- Returns: string localcollect={} returntable.concat(trimAndFormat(args,adapt),applyor"|") end-- Text.concatParams() Text.containsCJK=function(s) -- Is any CJK code within? -- Parameter: -- s -- string -- Returns: true, if CJK detected s=sandtostring(s)or"" localpatternCJK=mw.loadData('Modul:Text/data').PatternCJK returnmw.ustring.find(s,patternCJK)~=nil end-- Text.containsCJK() Text.removeDelimited=function(s,prefix,suffix) -- Remove all text in s delimited by prefix and suffix (inclusive) -- Arguments: -- s = string to process -- prefix = initial delimiter -- suffix = ending delimiter -- Returns: stripped string s=sandtostring(s)or"" prefix=prefixandtostring(prefix)or"" suffix=suffixandtostring(suffix)or"" localprefixLen=mw.ustring.len(prefix) localsuffixLen=mw.ustring.len(suffix) ifprefixLen==0orsuffixLen==0then returns end locali=s:find(prefix,1,true) localr=s localj whileido j=r:find(suffix,i+prefixLen) ifjthen r=r:sub(1,i-1)..r:sub(j+suffixLen) else r=r:sub(1,i-1) end i=r:find(prefix,1,true) end returnr end Text.getPlain=function(adjust) -- Remove wikisyntax from string, except templates -- Parameter: -- adjust -- string -- Returns: string localr=Text.removeDelimited(adjust,"<!--","-->") r=r:gsub("(</?%l[^>]*>)","") :gsub("'''","") :gsub("''","") :gsub(" "," ") returnr end-- Text.getPlain() Text.isLatinRange=function(s) -- Are characters expected to be latin or symbols within latin texts? -- Arguments: -- s = string to analyze -- Returns: true, if valid for latin only s=sandtostring(s)or""--- ensure input is always string localPatternLatin=mw.loadData('Modul:Text/data').PatternLatin returnmw.ustring.match(s,PatternLatin)~=nil end-- Text.isLatinRange() Text.isQuote=function(s) -- Is this character any quotation mark? -- Parameter: -- s = single character to analyze -- Returns: true, if s is quotation mark s=sandtostring(s)or"" ifs==""then returnfalse end localSeekQuote=mw.loadData('Modul:Text/data').SeekQuote returnmw.ustring.find(SeekQuote,s,1,true)~=nil end-- Text.isQuote() Text.listToText=function(args,adapt) -- Format list items similar to mw.text.listToText() -- Parameter: -- args -- table (sequence) with numKey=string -- adapt -- string (optional); format including "%s" -- Returns: string returnmw.text.listToText(trimAndFormat(args,adapt)) end-- Text.listToText() Text.quote=function(apply,alien,advance) -- Quote text -- Parameter: -- apply -- string, with text -- alien -- string, with language code, or nil -- advance -- number, with level 1 or 2, or nil -- Returns: quoted string apply=applyandtostring(apply)or"" localmode,slang iftype(alien)=="string"then slang=mw.text.trim(alien):lower() else slang=mw.title.getCurrentTitle().pageLanguage ifnotslangthen -- TODO FIXME: Introduction expected 2017-04 slang=mw.language.getContentLanguage():getCode() end end ifadvance==2then mode=2 else mode=1 end returnfiatQuote(mw.text.trim(apply),slang,mode) end-- Text.quote() Text.quoteUnquoted=function(apply,alien,advance) -- Quote text, if not yet quoted and not empty -- Parameter: -- apply -- string, with text -- alien -- string, with language code, or nil -- advance -- number, with level 1 or 2, or nil -- Returns: string; possibly quoted localr=mw.text.trim(applyandtostring(apply)or"") locals=mw.ustring.sub(r,1,1) ifs~=""andnotText.isQuote(s,advance)then s=mw.ustring.sub(r,-1,1) ifnotText.isQuote(s)then r=Text.quote(r,alien,advance) end end returnr end-- Text.quoteUnquoted() Text.removeDiacritics=function(adjust) -- Remove all diacritics -- Parameter: -- adjust -- string -- Returns: string; all latin letters should be ASCII -- or basic greek or cyrillic or symbols etc. localcleanup,decomposed localPatternCombined=mw.loadData('Modul:Text/data').PatternCombined decomposed=mw.ustring.toNFD(adjustandtostring(adjust)or"") cleanup=mw.ustring.gsub(decomposed,PatternCombined,"") returnmw.ustring.toNFC(cleanup) end-- Text.removeDiacritics() Text.sentenceTerminated=function(analyse) -- Is string terminated by dot, question or exclamation mark? -- Quotation, link termination and so on granted -- Parameter: -- analyse -- string -- Returns: true, if sentence terminated localr localPatternTerminated=mw.loadData('Modul:Text/data').PatternTerminated ifmw.ustring.find(analyse,PatternTerminated)then r=true else r=false end returnr end-- Text.sentenceTerminated() Text.ucfirstAll=function(adjust) -- Capitalize all words -- Arguments: -- adjust = string to adjust -- Returns: string with all first letters in upper case adjust=adjustandtostring(adjust)or"" localr=mw.text.decode(adjust,true) locali=1 localc,j,m m=(r~=adjust) r=" "..r whileido i=mw.ustring.find(r,"%W%l",i) ifithen j=i+1 c=mw.ustring.upper(mw.ustring.sub(r,j,j)) r=string.format("%s%s%s", mw.ustring.sub(r,1,i), c, mw.ustring.sub(r,i+2)) i=j end end-- while i r=r:sub(2) ifmthen r=mw.text.encode(r) end returnr end-- Text.ucfirstAll() Text.uprightNonlatin=function(adjust) -- Ensure non-italics for non-latin text parts -- One single greek letter might be granted -- Precondition: -- adjust -- string -- Returns: string with non-latin parts enclosed in <span> localr localdata=mw.loadData('Modul:Text/data') localPatternLatin=data.PatternLatin localRangesLatin=data.RangesLatin localNumLatinRanges=data.NumLatinRanges ifmw.ustring.match(adjust,PatternLatin)then -- latin only, horizontal dashes, quotes r=adjust else localc localj=false localk=1 localm=false localn=mw.ustring.len(adjust) localspan="%s%s<span dir='auto' style='font-style:normal'>%s</span>" localflat=function(a) -- isLatin localrange -- NumLatinRanges has to be precomputed because # does not work from loadData fori=1,NumLatinRangesdo range=RangesLatin[i] ifa>=range[1]anda<=range[2]then returntrue end end-- for i end-- flat() localfocus=function(a) -- char is not ambivalent localr=(a>64) ifrthen r=(a<8192ora>8212) else r=(a==38ora==60)-- '&' '<' end returnr end-- focus() localform=function(a) returnstring.format(span, r, mw.ustring.sub(adjust,k,j-1), mw.ustring.sub(adjust,j,a)) end-- form() r="" fori=1,ndo c=mw.ustring.codepoint(adjust,i,i) iffocus(c)then ifflat(c)then ifjthen ifmthen ifi==mthen -- single greek letter. j=false end m=false end ifjthen localnx=i-1 locals="" forix=nx,1,-1do c=mw.ustring.sub(adjust,ix,ix) ifc==" "orc=="("then nx=nx-1 s=c..s else break-- for ix end end-- for ix r=form(nx)..s j=false k=i end end elseifnotjthen j=i ifc>=880andc<=1023then -- single greek letter? m=i+1 else m=false end end elseifmthen m=m+1 end end-- for i ifjand(notmorm<n)then r=form(n) else r=r..mw.ustring.sub(adjust,k) end end returnr end-- Text.uprightNonlatin() Text.test=function(about) localr ifabout=="quote"then data=mw.loadData('Modul:Text/data') r={} r.QuoteLang=data.QuoteLang r.QuoteType=data.QuoteType end returnr end-- Text.test() -- Non Unicode-aware version of mw.text.split and mw.text.gsplit -- based on [[phab:diffusion/ELUA/browse/master/includes/Engines/LuaCommon/lualib/mw.text.lua]] -- These run up to 60 times faster than the Unicode-aware versions Text.split=function(text,pattern,plain) localret={} forminText.gsplit(text,pattern,plain)do ret[#ret+1]=m end returnret end Text.gsplit=function(text,pattern,plain) locals,l=1,string.len(text) returnfunction() ifsthen locale,n=string.find(text,pattern,s,plain) localret ifnotethen ret=string.sub(text,s) s=nil elseifn<ethen -- Empty separator! ret=string.sub(text,s,e) ife<lthen s=e+1 else s=nil end else ret=e>sandstring.sub(text,s,e-1)or'' s=n+1 end returnret end end,nil,nil end -- Export localp={} for_,funcinipairs({'containsCJK','isLatinRange','isQuote','sentenceTerminated'})do p[func]=function(frame) returnText[func](frame.args[1]or"")and"1"or"" end end for_,funcinipairs({'getPlain','removeDiacritics','ucfirstAll','uprightNonlatin'})do p[func]=function(frame) returnText[func](frame.args[1]or"") end end functionp.char(frame) localparams=frame:getParent().args localstory=params[1] localcodes,lenient,multiple ifnotstorythen params=frame.args story=params[1] end ifstorythen localitems=mw.text.split(mw.text.trim(story),"%s+") if#items>0then localj lenient=(yesNo(params.errors)==false) codes={} multiple=tonumber(params["*"]) for_,vinipairs(items)do j=tonumber((v:sub(1,1)=="x"and"0"or"")..v) table.insert(codes,jorv) end end end returnText.char(codes,multiple,lenient) end functionp.concatParams(frame) localargs localtemplate=frame.args.template iftype(template)=="string"then template=mw.text.trim(template) template=(template=="1") end iftemplatethen args=frame:getParent().args else args=frame.args end returnText.concatParams(args, frame.args.separator, frame.args.format) end functionp.listToFormat(frame) locallists={} localpformat=frame.args["format"] localsep=frame.args["sep"]or";" -- Parameter parsen: Listen fork,vinpairs(frame.args)do localknum=tonumber(k) ifknumthenlists[knum]=vend end -- Listen splitten localmaxListLen=0 fori=1,#listsdo lists[i]=mw.text.split(lists[i],sep) if#lists[i]>maxListLenthenmaxListLen=#lists[i]end end -- Ergebnisstring generieren localresult="" localresult_line="" fori=1,maxListLendo result_line=pformat forj=1,#listsdo result_line=mw.ustring.gsub(result_line,"%%s",lists[j][i],1) end result=result..result_line end returnresult end functionp.listToText(frame) localargs localtemplate=frame.args.template iftype(template)=="string"then template=mw.text.trim(template) template=(template=="1") end iftemplatethen args=frame:getParent().args else args=frame.args end returnText.listToText(args,frame.args.format) end functionp.quote(frame) localslang=frame.args[2] iftype(slang)=="string"then slang=mw.text.trim(slang) ifslang==""then slang=false end end returnText.quote(frame.args[1]or"", slang, tonumber(frame.args[3])) end functionp.quoteUnquoted(frame) localslang=frame.args[2] iftype(slang)=="string"then slang=mw.text.trim(slang) ifslang==""then slang=false end end returnText.quoteUnquoted(frame.args[1]or"", slang, tonumber(frame.args[3])) end functionp.zip(frame) locallists={} localseps={} localdefaultsep=frame.args["sep"]or"" localinnersep=frame.args["isep"]or"" localoutersep=frame.args["osep"]or"" -- Parameter parsen fork,vinpairs(frame.args)do localknum=tonumber(k) ifknumthenlists[knum]=velse ifstring.sub(k,1,3)=="sep"then localsepnum=tonumber(string.sub(k,4)) ifsepnumthenseps[sepnum]=vend end end end -- sofern keine expliziten Separatoren angegeben sind, den Standardseparator verwenden fori=1,math.max(#seps,#lists)do ifnotseps[i]thenseps[i]=defaultsepend end -- Listen splitten localmaxListLen=0 fori=1,#listsdo lists[i]=mw.text.split(lists[i],seps[i]) if#lists[i]>maxListLenthenmaxListLen=#lists[i]end end localresult="" fori=1,maxListLendo ifi~=1thenresult=result..outersepend forj=1,#listsdo ifj~=1thenresult=result..innersepend result=result..(lists[j][i]or"") end end returnresult end functionp.split(frame) localtext=frame.args.textorframe.args[1]or'' localpattern=frame.args.patternorframe.args[2]or'' localplain=yesNo(frame.args.plainorframe.args[3]) localindex=tonumber(frame.args.index)ortonumber(frame.args[4])or1 locala=Text.split(text,pattern,plain) ifindex<0thenindex=#a+index+1end returna[index] end functionp.failsafe() returnText.serial end p.Text=function() returnText end-- p.Text returnp