Wikikamus mswiktionary https://ms.wiktionary.org/wiki/Laman_Utama MediaWiki 1.45.0-wmf.6 case-sensitive Media Khas Perbincangan Pengguna Perbincangan pengguna Wikikamus Perbincangan Wikikamus Fail Perbincangan fail MediaWiki Perbincangan MediaWiki Templat Perbincangan templat Bantuan Perbincangan bantuan Kategori Perbincangan kategori Lampiran Perbincangan lampiran Rima Perbincangan rima Tesaurus Perbincangan tesaurus Indeks Perbincangan indeks Petikan Perbincangan petikan Rekonstruksi Perbincangan rekonstruksi Padanan isyarat Perbincangan padanan isyarat Konkordans Perbincangan konkordans TimedText TimedText talk Modul Perbincangan modul Acara Perbincangan acara burung 0 5628 218850 217299 2025-06-20T10:01:06Z Song GK 5715 218850 wikitext text/x-wiki {{wikipedia}} {{ms}} [[Fail:Blue Tit aka.jpg|thumb|Seekor burung.]] ===Sebutan=== * {{dewan|bu|rung}} * {{a|Johor-Selangor}} {{IPA|ms|/buroŋ/}} * {{a|Riau-Lingga}} {{IPA|ms|/burʊŋ/}} * {{rima|ms|uroŋ|roŋ|oŋ}} * {{audio|ms|ms-MY-burung.ogg|Audio (MY)}} * {{a|Sebutan baku; Kamus Dewan Perdana}} {{IPA|ms|/bu.rung/}} * {{audio|ms|LL-Q9237 (msa)-Hakimi97-burung.wav|Audio (MY-zsm)}} ===Terjemahan=== {{ter-atas|haiwan}} * Afrikaan: voël * Albania: {{t-|sq|zog|xs=Albania}} * Arab: {{Arab|طير}} (tˁīr) * Aragon: paxaro {{m}} * Armenia: լժռչուն * Azeri: quş * Banjar: burung * Basque: txori * Belanda: {{t+|nl|vogel|m}} * Bengali: পাখী * Breton: labous {{m}}, laboused {{p}}, evn {{m}}, evned {{p}} * Bosnia: {{t-|bs|ptica|f}} * Bulgaria: {{t+|bg|птица|f|tr=ptitsa|sc=Cyrl}} * Burma: ငဟက္ (hŋeʔ) * Catalonia: au {{m}} {{penerang|kumpulan taksonomi}}, ocell {{m}} {{penerang|burung terbang}} * Cebuano: langgam * Cherokee: ᏥᏍᏆ (tsisqua) * Cina: {{zh-ts|[[鳥]]|[[鸟]]}} (niăo); {{zh-ts|[[鳥類]]|[[鸟类]]}} (niăolèi); {{Hani|[[雀]]}} (què); {{zh-ts|[[雀鳥]]|[[雀鸟]]}} (quèniăo) * Cree: pileshish, peepee * Croatia: {{t+|hr|ptica|f}} * Czech: {{t+|cs|pták|m}} * Denmark: {{t+|da|fugl}} * Erzya: нармунь (narmunj) * Esperanto: {{t-|eo|birdo|xs=Bahasa Esperanto}} * Estonia: {{t-|et|lind}} * Faroe: {{t+|fo|fuglur|m|xs=Bahasa Faroe}} * Farsi: {{FAchar|پَرَندِه}} (pærænde) * Finland: {{t+|fi|lintu}} * Frisia: fûgel * Gaelik Scot: eun {{m}} * Galicia: paxaro * Georgia: ფრინველი (p‘rinveli) * Jerman: {{t+|de|Vogel|m}} * Greek, *: Kuno: ὄρνις (ornis) {{f}}, πτηνό (ptēnó) {{n}} *: Moden: πουλί (poulí) {{n}}, πτηνό (ptēnó) {{n}} * Guaraní: guyra * Gujarati: પનખિદ (pankhida) * Guugu Yimidhirr: dyidyirr * Hawaii: manu * Hindi: चिड़िया (ći.riyā) {{f}}, पंछी (pančī) {{f}}, पक्षी (pakšī) {{m}}, परन्दा (parandā) {{m}}, पखेरू (pakherū) {{m}} * Hungary: {{t+|hu|madár}} * Ibrani: צפור (tzipor) * Iceland: {{t+|is|fugl|m}} * Ido: ucelo * Indonesia: {{t+|id|burung|xs=Bahasa Indonesia}} * Inggeris: {{t+|en|bird}} * Inggeris Lama: {{t-|ang|fugol|xs=Bahasa Inggeris Lama}} * Interlingua: ave * Inuktitut: ᑎᖕᒥᐊᖅ (tingmiaq) * Ireland: éan ''m1'' * Itali: {{t+|it|uccello|m}} * Jepun: [[鳥]] (とり, tori) * Kazakh: құс * Khmer: {{KMchar|បក្សី}} (bʌksēi) * Korea: 새 (sæ) * Kurdi: firrinde, balinde, çivîk, çûçik, teyr, tilûr, terewîl, {{KUchar|باڵنده‌}}, {{KUchar|ته‌یر}} * Ladino: ave, have {{f}}, pášaro, pážaro, pájaro, pásaro {{m}} {{ter-tengah}} * Lao: {{Laoo|ນົກ}} (nok) * Latin: avis, -is * Latvia: putns {{m}} * Lithuania: paũkštis * Macedonia: птица (ptica) * Malagasy: vorona * Malayalam: പക്ഷി, തടവറ, പറവ, വിഹഗം, കിളി, കുരുവി, പെണ്‍കുട്ടി, സ്ത്രീ, ജയില്‍ശിക്ഷ, പ്രത്യേകതയുള്ള വ്യക്തി * Malta: tajra, għasfur * Maori: {{t+|mi|manu|xs=Bahasa_Maori}} * Mi'kmaq: jipji'j * Mohikan: tschèchtschis * Mongolia: {{t+|mn|шувуу|tr=šuvuu|sc=Cyrl|xs=Bahasa_Mongolia}} * Nanticoke: piss-seeques * Nenets: тиртя * Nganasan: тәибәә * Norway: {{t-|no|fugl|m}} * Novial: fogle * Occitan: {{italbrac|Lengadocian}} aucèl {{m}}, {{italbrac|Auvernhàs, Lemosin, Provençau}} aucèu {{m}} {{italbrac|Gascon}} ausèth {{m}} * Ojibwe: bineshiinh * Perancis: {{t+|fr|oiseau|m}} * Poland: {{t+|pl|ptak|m}} * Portugis: {{t+|pt|pássaro|m}}, {{t+|pt|ave|f}} * Potawatomi: pnéshi * Powhatan: tshehip * Punjabi: ਪੰਖੀ * Rohingya: faik * Romania: {{t+|ro|pasăre|f}} * Rusia: {{t+|ru|птица|f|tr=ptítsa|sc=Cyrl}} * Samoa: manu * Sanskrit: {{term|sc=Deva|वि|tr=ví|m}} * Saxon Rendah: Vagel {{m}} * Sepanyol: {{t+|es|pájaro|m}}, {{t+|es|ave|f}} * Serbia: *: Cyril: птица {{f}} *: Rumi: ptica {{f}} * Sicily: aceddu {{m}} * Slovakia: vták {{m}} * Slovenia: {{t+|sl|ptič|m}}, {{t+|sl|ptica|f}} * Somalia: shimbir * Swahili: ndege ''(kata nama 9/10)'' * Sweden: {{t+|sv|fågel|c}} * Tagalog: ibon * Tamazight: ⴰⴳⴹⵉⴹ (agḍiḍ) {{m}} * Telugu: పక్షి, విహంగము, పిట్ట (piTTa) * Thai: {{Thai|นก}} (nók), {{Thai|ปักษา}} (bpàksăa) * Tok Pisin: pisin * Tupinambá: gûyrá * Turan: quş * Turki: {{t+|tr|kuş}} * Ukraine: птах (ptákh) {{m}} * Urdu: {{URchar|چڑیا}} (ći.riyā) {{f}}, {{URchar|پنچھی}} (pančī) {{f}}, {{URchar|پکشی} (pakšī) {{m}}, {{URchar|پرندہ}} (parandā) {{m}}, {{URchar|پکھیرو}} (pakherū) {{m}} * Uzbek: qush * Venice: oseo {{m}} * Vietnam: (con) chim * Volapük: böd * Wales: {{t-|cy|aderyn|m|xs=Wales}} * Yiddish: פֿויגל (foygl) {{m}} {{ter-bawah}} ===Tesaurus=== ; Sinonim: [[manuk]], [[unggas]]. ==Bahasa Banjar== ===Takrifan=== ====Kata nama==== {{inti|bjn|kata kerja}} # burung ==Bahasa Iban== ===Takrifan=== ====Kata nama==== {{inti|iba|kata kerja}} # bisik #: {{cp|iba|Bisi peda kita burung dia?|Kalian ada tengok burung di sana?}} ==Bahasa Indonesia== ===Takrifan=== ====Kata nama==== {{id-kn}} # burung ==Bahasa Kadazandusun== ===Takrifan=== ====Kata kerja==== {{inti|dtp|kata kerja}} # [[bisik]]. #: {{ux|dtp|Au oku korongou tuni '''burung''' nu tu ologod kopio ilo yolo minsinding. |Saya tidak mendengar bunyi '''bisik''' kamu kerana mereka bernyanyi terlalu kuat.}} # sejenis alat bekas diikat di [[pinggang]] ===Sebutan=== * {{IPA|dtp|/ɓʊ.rʊŋ/}} * {{penyempangan|dtp|bu|rung}} [[File:LL-Q5317225 (dtp)-Meqqal-burung.wav|thumb|LL-Q5317225 (dtp)-Meqqal-burung]] ===Kata terbitan=== *{{l|dtp|binurung}} *{{l|dtp|burungo'}} *{{l|dtp|burungai}} *{{l|dtp|binurungan}} *{{l|dtp|koburung}} *{{l|dtp|kobuburung}} *{{l|dtp|murung-burung}} *{{l|dtp|momurung}} *{{l|dtp|momuuburung}} *{{l|dtp|oburungan}} *{{l|dtp|popoburung}} *{{l|dtp|nokoburung}} ===Rujukan=== * {{R:Komoiboros DusunKadazan}} 3n2d6ioudsaewlkr38uaf4oba97hdbf 218851 218850 2025-06-20T10:01:59Z Song GK 5715 218851 wikitext text/x-wiki {{wikipedia}} {{ms}} [[Fail:Blue Tit aka.jpg|thumb|Seekor burung.]] ===Sebutan=== * {{dewan|bu|rung}} * {{a|Johor-Selangor}} {{IPA|ms|/buroŋ/}} * {{a|Riau-Lingga}} {{IPA|ms|/burʊŋ/}} * {{rima|ms|uroŋ|roŋ|oŋ}} * {{audio|ms|ms-MY-burung.ogg|Audio (MY)}} * {{a|Sebutan baku; Kamus Dewan Perdana}} {{IPA|ms|/bu.rung/}} * {{audio|ms|LL-Q9237 (msa)-Hakimi97-burung.wav|Audio (MY-zsm)}} ===Terjemahan=== {{ter-atas|haiwan}} * Afrikaan: voël * Albania: {{t-|sq|zog|xs=Albania}} * Arab: {{Arab|طير}} (tˁīr) * Aragon: paxaro {{m}} * Armenia: լժռչուն * Azeri: quş * Banjar: burung * Basque: txori * Belanda: {{t+|nl|vogel|m}} * Bengali: পাখী * Breton: labous {{m}}, laboused {{p}}, evn {{m}}, evned {{p}} * Bosnia: {{t-|bs|ptica|f}} * Bulgaria: {{t+|bg|птица|f|tr=ptitsa|sc=Cyrl}} * Burma: ငဟက္ (hŋeʔ) * Catalonia: au {{m}} {{penerang|kumpulan taksonomi}}, ocell {{m}} {{penerang|burung terbang}} * Cebuano: langgam * Cherokee: ᏥᏍᏆ (tsisqua) * Cina: {{zh-ts|[[鳥]]|[[鸟]]}} (niăo); {{zh-ts|[[鳥類]]|[[鸟类]]}} (niăolèi); {{Hani|[[雀]]}} (què); {{zh-ts|[[雀鳥]]|[[雀鸟]]}} (quèniăo) * Cree: pileshish, peepee * Croatia: {{t+|hr|ptica|f}} * Czech: {{t+|cs|pták|m}} * Denmark: {{t+|da|fugl}} * Erzya: нармунь (narmunj) * Esperanto: {{t-|eo|birdo|xs=Bahasa Esperanto}} * Estonia: {{t-|et|lind}} * Faroe: {{t+|fo|fuglur|m|xs=Bahasa Faroe}} * Farsi: {{FAchar|پَرَندِه}} (pærænde) * Finland: {{t+|fi|lintu}} * Frisia: fûgel * Gaelik Scot: eun {{m}} * Galicia: paxaro * Georgia: ფრინველი (p‘rinveli) * Jerman: {{t+|de|Vogel|m}} * Greek, *: Kuno: ὄρνις (ornis) {{f}}, πτηνό (ptēnó) {{n}} *: Moden: πουλί (poulí) {{n}}, πτηνό (ptēnó) {{n}} * Guaraní: guyra * Gujarati: પનખિદ (pankhida) * Guugu Yimidhirr: dyidyirr * Hawaii: manu * Hindi: चिड़िया (ći.riyā) {{f}}, पंछी (pančī) {{f}}, पक्षी (pakšī) {{m}}, परन्दा (parandā) {{m}}, पखेरू (pakherū) {{m}} * Hungary: {{t+|hu|madár}} * Ibrani: צפור (tzipor) * Iceland: {{t+|is|fugl|m}} * Ido: ucelo * Indonesia: {{t+|id|burung|xs=Bahasa Indonesia}} * Inggeris: {{t+|en|bird}} * Inggeris Lama: {{t-|ang|fugol|xs=Bahasa Inggeris Lama}} * Interlingua: ave * Inuktitut: ᑎᖕᒥᐊᖅ (tingmiaq) * Ireland: éan ''m1'' * Itali: {{t+|it|uccello|m}} * Jepun: [[鳥]] (とり, tori) * Kazakh: құс * Khmer: {{KMchar|បក្សី}} (bʌksēi) * Korea: 새 (sæ) * Kurdi: firrinde, balinde, çivîk, çûçik, teyr, tilûr, terewîl, {{KUchar|باڵنده‌}}, {{KUchar|ته‌یر}} * Ladino: ave, have {{f}}, pášaro, pážaro, pájaro, pásaro {{m}} {{ter-tengah}} * Lao: {{Laoo|ນົກ}} (nok) * Latin: avis, -is * Latvia: putns {{m}} * Lithuania: paũkštis * Macedonia: птица (ptica) * Malagasy: vorona * Malayalam: പക്ഷി, തടവറ, പറവ, വിഹഗം, കിളി, കുരുവി, പെണ്‍കുട്ടി, സ്ത്രീ, ജയില്‍ശിക്ഷ, പ്രത്യേകതയുള്ള വ്യക്തി * Malta: tajra, għasfur * Maori: {{t+|mi|manu|xs=Bahasa_Maori}} * Mi'kmaq: jipji'j * Mohikan: tschèchtschis * Mongolia: {{t+|mn|шувуу|tr=šuvuu|sc=Cyrl|xs=Bahasa_Mongolia}} * Nanticoke: piss-seeques * Nenets: тиртя * Nganasan: тәибәә * Norway: {{t-|no|fugl|m}} * Novial: fogle * Occitan: {{italbrac|Lengadocian}} aucèl {{m}}, {{italbrac|Auvernhàs, Lemosin, Provençau}} aucèu {{m}} {{italbrac|Gascon}} ausèth {{m}} * Ojibwe: bineshiinh * Perancis: {{t+|fr|oiseau|m}} * Poland: {{t+|pl|ptak|m}} * Portugis: {{t+|pt|pássaro|m}}, {{t+|pt|ave|f}} * Potawatomi: pnéshi * Powhatan: tshehip * Punjabi: ਪੰਖੀ * Rohingya: faik * Romania: {{t+|ro|pasăre|f}} * Rusia: {{t+|ru|птица|f|tr=ptítsa|sc=Cyrl}} * Samoa: manu * Sanskrit: {{term|sc=Deva|वि|tr=ví|m}} * Saxon Rendah: Vagel {{m}} * Sepanyol: {{t+|es|pájaro|m}}, {{t+|es|ave|f}} * Serbia: *: Cyril: птица {{f}} *: Rumi: ptica {{f}} * Sicily: aceddu {{m}} * Slovakia: vták {{m}} * Slovenia: {{t+|sl|ptič|m}}, {{t+|sl|ptica|f}} * Somalia: shimbir * Swahili: ndege ''(kata nama 9/10)'' * Sweden: {{t+|sv|fågel|c}} * Tagalog: ibon * Tamazight: ⴰⴳⴹⵉⴹ (agḍiḍ) {{m}} * Telugu: పక్షి, విహంగము, పిట్ట (piTTa) * Thai: {{Thai|นก}} (nók), {{Thai|ปักษา}} (bpàksăa) * Tok Pisin: pisin * Tupinambá: gûyrá * Turan: quş * Turki: {{t+|tr|kuş}} * Ukraine: птах (ptákh) {{m}} * Urdu: {{URchar|چڑیا}} (ći.riyā) {{f}}, {{URchar|پنچھی}} (pančī) {{f}}, {{URchar|پکشی} (pakšī) {{m}}, {{URchar|پرندہ}} (parandā) {{m}}, {{URchar|پکھیرو}} (pakherū) {{m}} * Uzbek: qush * Venice: oseo {{m}} * Vietnam: (con) chim * Volapük: böd * Wales: {{t-|cy|aderyn|m|xs=Wales}} * Yiddish: פֿויגל (foygl) {{m}} {{ter-bawah}} ===Tesaurus=== ; Sinonim: [[manuk]], [[unggas]]. ==Bahasa Banjar== ===Takrifan=== ====Kata nama==== {{inti|bjn|kata nama}} # burung ==Bahasa Iban== ===Takrifan=== ====Kata nama==== {{inti|iba|kata nama}} # bisik #: {{cp|iba|Bisi peda kita '''burung''' dia?|Kalian ada tengok '''burung''' di sana?}} ==Bahasa Indonesia== ===Takrifan=== ====Kata nama==== {{id-kn}} # burung ==Bahasa Kadazandusun== ===Takrifan=== ====Kata kerja==== {{inti|dtp|kata kerja}} # [[bisik]]. #: {{ux|dtp|Au oku korongou tuni '''burung''' nu tu ologod kopio ilo yolo minsinding. |Saya tidak mendengar bunyi '''bisik''' kamu kerana mereka bernyanyi terlalu kuat.}} # sejenis alat bekas diikat di [[pinggang]] ===Sebutan=== * {{IPA|dtp|/ɓʊ.rʊŋ/}} * {{penyempangan|dtp|bu|rung}} [[File:LL-Q5317225 (dtp)-Meqqal-burung.wav|thumb|LL-Q5317225 (dtp)-Meqqal-burung]] ===Kata terbitan=== *{{l|dtp|binurung}} *{{l|dtp|burungo'}} *{{l|dtp|burungai}} *{{l|dtp|binurungan}} *{{l|dtp|koburung}} *{{l|dtp|kobuburung}} *{{l|dtp|murung-burung}} *{{l|dtp|momurung}} *{{l|dtp|momuuburung}} *{{l|dtp|oburungan}} *{{l|dtp|popoburung}} *{{l|dtp|nokoburung}} ===Rujukan=== * {{R:Komoiboros DusunKadazan}} 2qrjqklr4agsqxh8fqru8k9ps2qf4ar Modul:string utilities 828 11594 218836 185162 2025-06-19T22:43:20Z Sponge2490 8927 Mengemaskini berdasarkan Module:string utilities pada 14 Jun 2025 (85118790) 218836 Scribunto text/plain local export = {} local function_module = "Module:fun" local load_module = "Module:load" local memoize_module = "Module:memoize" local string_char_module = "Module:string/char" local string_charset_escape_module = "Module:string/charsetEscape" local mw = mw local string = string local table = table local ustring = mw.ustring local byte = string.byte local char = string.char local concat = table.concat local find = string.find local format = string.format local gmatch = string.gmatch local gsub = string.gsub local insert = table.insert local len = string.len local lower = string.lower local match = string.match local next = next local require = require local reverse = string.reverse local select = select local sort = table.sort local sub = string.sub local tonumber = tonumber local tostring = tostring local type = type local ucodepoint = ustring.codepoint local ufind = ustring.find local ugcodepoint = ustring.gcodepoint local ugmatch = ustring.gmatch local ugsub = ustring.gsub local ulower = ustring.lower local umatch = ustring.match local unpack = unpack or table.unpack -- Lua 5.2 compatibility local upper = string.upper local usub = ustring.sub local uupper = ustring.upper local memoize = require(memoize_module) -- Defined below. local codepoint local explode_utf8 local format_fun local get_charset local gsplit local pattern_escape local pattern_simplifier local replacement_escape local title_case local trim local ucfirst local ulen --[==[ Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls. ]==] local function charset_escape(...) charset_escape = require(string_charset_escape_module) return charset_escape(...) end local function is_callable(...) is_callable = require(function_module).is_callable return is_callable(...) end local function load_data(...) load_data = require(load_module).load_data return load_data(...) end local function u(...) u = require(string_char_module) return u(...) end local function prepare_iter(str, pattern, str_lib, plain) local callable = is_callable(pattern) if str_lib or plain then return pattern, #str, string, callable elseif not callable then local simple = pattern_simplifier(pattern) if simple then return simple, #str, string, false end end return pattern, ulen(str), ustring, callable end --[==[ Returns {nil} if the input value is the empty string, or otherwise the same value. If the input is a string and `do_trim` is set, the input value will be trimmed before returning; if the trimmed value is the empty string, returns {nil}. If `quote_delimiters` is set, then any outer pair of quotation marks ({' '} or {" "}) surrounding the rest of the input string will be stripped, if present. The string will not be trimmed again, converted to {nil}, or have further quotation marks stripped, as it exists as a way to embed spaces or the empty string in an input. Genuine quotation marks may also be embedded this way (e.g. {"''foo''"} returns {"'foo'"}). ]==] function export.is_not_empty(str, do_trim, quote_delimiters) if str == "" then return nil elseif not (str and type(str) == "string") then return str elseif do_trim then str = trim(str) if str == "" then return nil end end return quote_delimiters and gsub(str, "^(['\"])(.*)%1$", "%2") or str end --[==[ Explodes a string into an array of UTF-8 characters. '''Warning''': this function assumes that the input is valid UTF-8 in order to optimize speed and memory use. Passing in an input containing non-UTF-8 byte sequences could result in unexpected behaviour. ]==] function export.explode_utf8(str) local text, i = {}, 0 for ch in gmatch(str, ".[\128-\191]*") do i = i + 1 text[i] = ch end return text end explode_utf8 = export.explode_utf8 --[==[ Returns {true} if `str` is a valid UTF-8 string. This is true if, for each character, all of the following are true: * It has the expected number of bytes, which is determined by value of the leading byte: 1-byte characters are `0x00` to `0x7F`, 2-byte characters start with `0xC2` to `0xDF`, 3-byte characters start with `0xE0` to `0xEF`, and 4-byte characters start with `0xF0` to `0xF4`. * The leading byte must not fall outside of the above ranges. * The trailing byte(s) (if any), must be between `0x80` to `0xBF`. * The character's codepoint must be between U+0000 (`0x00`) and U+10FFFF (`0xF4 0x8F 0xBF 0xBF`). * The character cannot have an overlong encoding: for each byte length, the lowest theoretical encoding is equivalent to U+0000 (e.g. `0xE0 0x80 0x80`, the lowest theoretical 3-byte encoding, is exactly equivalent to U+0000). Encodings that use more than the minimum number of bytes are not considered valid, meaning that the first valid 3-byte character is `0xE0 0xA0 0x80` (U+0800), and the first valid 4-byte character is `0xF0 0x90 0x80 0x80` (U+10000). Formally, 2-byte characters have leading bytes ranging from `0xC0` to `0xDF` (rather than `0xC2` to `0xDF`), but `0xC0 0x80` to `0xC1 0xBF` are overlong encodings, so it is simpler to say that the 2-byte range begins at `0xC2`. If `allow_surrogates` is set, surrogates (U+D800 to U+DFFF) will be treated as valid UTF-8. Surrogates are used in UTF-16, which encodes codepoints U+0000 to U+FFFF with 2 bytes, and codepoints from U+10000 upwards using a pair of surrogates, which are taken together as a 4-byte unit. Since surrogates have no use in UTF-8, as it encodes higher codepoints in a different way, they are not considered valid in UTF-8 text. However, there are limited circumstances where they may be necessary: for instance, JSON escapes characters using the format `\u0000`, which must contain exactly 4 hexadecimal digits; under the scheme, codepoints above U+FFFF must be escaped as the equivalent pair of surrogates, even though the text itself must be encoded in UTF-8 (e.g. U+10000 becomes `\uD800\uDC00`). ]==] function export.isutf8(str, allow_surrogates) for ch in gmatch(str, "[\128-\255][\128-\191]*") do if #ch > 4 then return false end local b1, b2, b3, b4 = byte(ch, 1, 4) if not (b2 and b2 >= 0x80 and b2 <= 0xBF) then return false -- 1-byte is always invalid, as gmatch excludes 0x00 to 0x7F elseif not b3 then -- 2-byte if not (b1 >= 0xC2 and b1 <= 0xDF) then -- b1 == 0xC0 or b1 == 0xC1 is overlong return false end elseif not (b3 >= 0x80 and b3 <= 0xBF) then -- trailing byte return false elseif not b4 then -- 3-byte if b1 > 0xEF then return false elseif b2 < 0xA0 then if b1 < 0xE1 then -- b1 == 0xE0 and b2 < 0xA0 is overlong return false end elseif b1 < 0xE0 or (b1 == 0xED and not allow_surrogates) then -- b1 == 0xED and b2 >= 0xA0 is a surrogate return false end elseif not (b4 >= 0x80 and b4 <= 0xBF) then -- 4-byte return false elseif b2 < 0x90 then if not (b1 >= 0xF1 and b1 <= 0xF4) then -- b1 == 0xF0 and b2 < 0x90 is overlong return false end elseif not (b1 >= 0xF0 and b1 <= 0xF3) then -- b1 == 0xF4 and b2 >= 0x90 is too high return false end end return true end do local charset_chars = { ["\0"] = "%z", ["%"] = "%%", ["-"] = "%-", ["]"] = "%]", ["^"] = "%^" } charset_chars.__index = charset_chars local chars = setmetatable({ ["$"] = "%$", ["("] = "%(", [")"] = "%)", ["*"] = "%*", ["+"] = "%+", ["."] = "%.", ["?"] = "%?", ["["] = "%[" }, charset_chars) --[==[ Escapes the magic characters used in a [[mw:Extension:Scribunto/Lua reference manual#Patterns|pattern]] (Lua's version of regular expressions): {$%()*+-.?[]^}, and converts the null character to {%z}. For example, {"^$()%.[]*+-?\0"} becomes {"%^%$%(%)%%%.%[%]%*%+%-%?%z"}. This is necessary when constructing a pattern involving arbitrary text (e.g. from user input). ]==] function export.pattern_escape(str) return (gsub(str, "[%z$%%()*+%-.?[%]^]", chars)) end pattern_escape = export.pattern_escape --[==[ Escapes only {%}, which is the only magic character used in replacement [[mw:Extension:Scribunto/Lua reference manual#Patterns|patterns]] with string.gsub and mw.ustring.gsub. ]==] function export.replacement_escape(str) return (gsub(str, "%%", "%%%%")) end replacement_escape = export.replacement_escape local function case_insensitive_char(ch) local upper_ch = uupper(ch) if upper_ch == ch then ch = ulower(ch) if ch == upper_ch then return chars[ch] or ch end end return "[" .. (charset_chars[upper_ch] or upper_ch) .. (charset_chars[ch] or ch) .. "]" end local function iterate(str, str_len, text, n, start, _gsub, _sub, loc1, loc2) if not (loc1 and start <= str_len) then -- Add final chunk and return. n = n + 1 text[n] = _gsub(_sub(str, start), ".", chars) return elseif loc2 < loc1 then if _sub == sub then local b = byte(str, loc1) if b and b >= 128 then loc1 = loc1 + (b < 224 and 1 or b < 240 and 2 or 3) end end n = n + 1 text[n] = _gsub(_sub(str, start, loc1), ".", chars) start = loc1 + 1 if start > str_len then return end else -- Add chunk up to the current match. n = n + 1 text[n] = _gsub(_sub(str, start, loc1 - 1), ".", chars) -- Add current match. n = n + 1 text[n] = _gsub(_sub(str, loc1, loc2), ".", case_insensitive_char) start = loc2 + 1 end return n, start end --[==[ Escapes the magic characters used in a [[mw:Extension:Scribunto/Lua reference manual#Patterns|pattern]], and makes all characters case-insensitive. An optional pattern or find function (see {split}) may be supplied as the second argument, the third argument (`str_lib`) forces use of the string library, while the fourth argument (`plain`) turns any pattern matching facilities off in the optional pattern supplied. ]==] function export.case_insensitive_pattern(str, pattern_or_func, str_lib, plain) if pattern_or_func == nil then return (gsub(str, str_lib and "[^\128-\255]" or ".[\128-\191]*", case_insensitive_char)) end local text, n, start, str_len, _string, callable = {}, 0, 1 pattern_or_func, str_len, _string, callable = prepare_iter(str, pattern_or_func, str_lib, plain) local _find, _gsub, _sub = _string.find, _string.gsub, _string.sub if callable then repeat n, start = iterate(str, str_len, text, n, start, _gsub, _sub, pattern_or_func(str, start)) until not start -- Special case if the pattern is anchored to the start: "^" always -- anchors to the start position, not the start of the string, so get -- around this by only attempting one match with the pattern, then match -- the end of the string. elseif byte(pattern_or_func) == 0x5E then -- ^ n, start = iterate(str, str_len, text, n, start, _gsub, _sub, _find(str, pattern_or_func, start, plain)) if start ~= nil then iterate(str, str_len, text, n, start, _gsub, _sub, _find(str, "$", start, plain)) end else repeat n, start = iterate(str, str_len, text, n, start, _gsub, _sub, _find(str, pattern_or_func, start, plain)) until not start end return concat(text) end end do local character_classes local function get_character_classes() character_classes, get_character_classes = { [0x41] = true, [0x61] = true, -- Aa [0x43] = true, [0x63] = true, -- Cc [0x44] = true, [0x64] = true, -- Dd [0x4C] = true, [0x6C] = true, -- Ll [0x50] = true, [0x70] = true, -- Pp [0x53] = true, [0x73] = true, -- Ss [0x55] = true, [0x75] = true, -- Uu [0x57] = true, [0x77] = true, -- Ww [0x58] = true, [0x78] = true, -- Xx [0x5A] = true, -- z dealt with separately. }, nil return character_classes end local function check_sets_equal(set1, set2) local k2 for k1, v1 in next, set1 do local v2 = set2[k1] if v1 ~= v2 and (v2 == nil or not check_sets_equal(v1, v2)) then return false end k2 = next(set2, k2) end return next(set2, k2) == nil end local function check_sets(bytes) local key, set1, set = next(bytes) if set1 == true then return true elseif not check_sets(set1) then return false end while true do key, set = next(bytes, key) if not key then return true elseif not check_sets_equal(set, set1) then return false end end end local function make_charset(range) if #range == 1 then return char(range[1]) end sort(range) local compressed, n, start = {}, 0, range[1] for i = 1, #range do local this, nxt = range[i], range[i + 1] if nxt ~= this + 1 then n = n + 1 compressed[n] = this == start and char(this) or char(start) .. "-" .. char(this) start = nxt end end return "[" .. concat(compressed) .. "]" end local function parse_1_byte_charset(pattern, pos) local ch while true do pos, ch = match(pattern, "()([%%%]\192-\255])", pos) if ch == "%" then local nxt = byte(pattern, pos + 1) if not nxt or nxt >= 128 or (character_classes or get_character_classes())[nxt] then -- acdlpsuwxACDLPSUWXZ, but not z return false end pos = pos + 2 elseif ch == "]" then pos = pos + 1 return pos else return false end end end --[==[ Parses `pattern`, a ustring library pattern, and attempts to convert it into a string library pattern. If conversion isn't possible, returns false. ]==] function pattern_simplifier(pattern) if type(pattern) == "number" then return tostring(pattern) end local pos, capture_groups, start, n, output, ch, nxt_pos = 1, 0, 1, 0 while true do -- FIXME: use "()([%%(.[\128-\255])[\128-\191]?[\128-\191]?[\128-\191]?()" and ensure non-UTF8 always fails. pos, ch, nxt_pos = match(pattern, "()([%%(.[\192-\255])[\128-\191]*()", pos) if not ch then break end local nxt = byte(pattern, nxt_pos) if ch == "%" then if nxt == 0x62 then -- b local nxt2, nxt3 = byte(pattern, pos + 2, pos + 3) if not (nxt2 and nxt2 < 128 and nxt3 and nxt3 < 128) then return false end pos = pos + 4 elseif nxt == 0x66 then -- f nxt_pos = nxt_pos + 2 local nxt2, nxt3 = byte(pattern, nxt_pos - 1, nxt_pos) -- Only possible to convert a positive %f charset which is -- all ASCII, so use parse_1_byte_charset. if not (nxt2 == 0x5B and nxt3 and nxt3 ~= 0x5E and nxt3 < 128) then -- [^ return false elseif nxt3 == 0x5D then -- Initial ] is non-magic. nxt_pos = nxt_pos + 1 end pos = parse_1_byte_charset(pattern, nxt_pos) if not pos then return false end elseif nxt == 0x5A then -- Z nxt = byte(pattern, nxt_pos + 1) if nxt == 0x2A or nxt == 0x2D then -- *- pos = pos + 3 else if output == nil then output = {} end local ins = sub(pattern, start, pos - 1) .. "[\1-\127\192-\255]" n = n + 1 if nxt == 0x2B then -- + output[n] = ins .. "%Z*" pos = pos + 3 elseif nxt == 0x3F then -- ? output[n] = ins .. "?[\128-\191]*" pos = pos + 3 else output[n] = ins .. "[\128-\191]*" pos = pos + 2 end start = pos end elseif not nxt or (character_classes or get_character_classes())[nxt] then -- acdlpsuwxACDLPSUWX, but not Zz return false -- Skip the next character if it's ASCII. Otherwise, we will -- still need to do length checks. else pos = pos + (nxt < 128 and 2 or 1) end elseif ch == "(" then if nxt == 0x29 or capture_groups == 32 then -- ) return false end capture_groups = capture_groups + 1 pos = pos + 1 elseif ch == "." then if nxt == 0x2A or nxt == 0x2D then -- *- pos = pos + 2 else if output == nil then output = {} end local ins = sub(pattern, start, pos - 1) .. "[^\128-\191]" n = n + 1 if nxt == 0x2B then -- + output[n] = ins .. ".*" pos = pos + 2 elseif nxt == 0x3F then -- ? output[n] = ins .. "?[\128-\191]*" pos = pos + 2 else output[n] = ins .. "[\128-\191]*" pos = pos + 1 end start = pos end elseif ch == "[" then -- Fail negative charsets. TODO: 1-byte charsets should be safe. if nxt == 0x5E then -- ^ return false -- If the first character is "%", ch_len is determined by the -- next one instead. elseif nxt == 0x25 then -- % nxt = byte(pattern, nxt_pos + 1) elseif nxt == 0x5D then -- Initial ] is non-magic. nxt_pos = nxt_pos + 1 end if not nxt then return false end local ch_len = nxt < 128 and 1 or nxt < 224 and 2 or nxt < 240 and 3 or 4 if ch_len == 1 then -- Single-byte charset. pos = parse_1_byte_charset(pattern, nxt_pos) if not pos then return false end else -- Multibyte charset. -- TODO: 1-byte chars should be safe to mix with multibyte chars. CONFIRM THIS FIRST. local charset_pos, bytes = pos pos = pos + 1 while true do -- TODO: non-ASCII charset ranges. pos, ch, nxt_pos = match(pattern, "^()([^\128-\191])[\128-\191]*()", pos) -- If escaped, get the next character. No need to -- distinguish magic characters or character classes, -- as they'll all fail for having the wrong length -- anyway. if ch == "%" then pos, ch, nxt_pos = match(pattern, "^()([^\128-\191])[\128-\191]*()", nxt_pos) elseif ch == "]" then pos = nxt_pos break end if not (ch and nxt_pos - pos == ch_len) then return false elseif bytes == nil then bytes = {} end local bytes, last = bytes, nxt_pos - 1 for i = pos, last - 1 do local b = byte(pattern, i) local bytes_b = bytes[b] if bytes_b == nil then bytes_b = {} bytes[b] = bytes_b end bytes[b], bytes = bytes_b, bytes_b end bytes[byte(pattern, last)] = true pos = nxt_pos end if not pos then return false end nxt = byte(pattern, pos) if ( (nxt == 0x2A or nxt == 0x2D or nxt == 0x3F) or -- *-? (nxt == 0x2B and ch_len > 2) or -- + not check_sets(bytes) ) then return false end local ranges, b, key, next_byte = {}, 0 repeat key, next_byte = next(bytes) local range, n = {key}, 1 -- Loop starts on the second iteration. for key in next, bytes, key do n = n + 1 range[n] = key end b = b + 1 ranges[b] = range bytes = next_byte until next_byte == true if nxt == 0x2B then -- + local range1, range2 = ranges[1], ranges[2] ranges[1], ranges[3] = make_charset(range1), make_charset(range2) local n = #range2 for i = 1, #range1 do n = n + 1 range2[n] = range1[i] end ranges[2] = make_charset(range2) .. "*" pos = pos + 1 else for i = 1, #ranges do ranges[i] = make_charset(ranges[i]) end end if output == nil then output = {} end nxt = byte(pattern, pos) n = n + 1 output[n] = sub(pattern, start, charset_pos - 1) .. concat(ranges) .. ((nxt == 0x2A or nxt == 0x2B or nxt == 0x2D or nxt == 0x3F) and "%" or "") -- following *+-? now have to be escaped start = pos end elseif not nxt then break elseif nxt == 0x2B then -- + if nxt_pos - pos ~= 2 then return false elseif output == nil then output = {} end pos, nxt_pos = pos + 1, nxt_pos + 1 nxt = byte(pattern, nxt_pos) local ch2 = sub(pattern, pos, pos) n = n + 1 output[n] = sub(pattern, start, pos - 1) .. "[" .. ch .. ch2 .. "]*" .. ch2 .. ((nxt == 0x2A or nxt == 0x2B or nxt == 0x2D or nxt == 0x3F) and "%" or "") -- following *+-? now have to be escaped pos, start = nxt_pos, nxt_pos elseif nxt == 0x2A or nxt == 0x2D or nxt == 0x3F then -- *-? return false else pos = nxt_pos end end if start == 1 then return pattern end return concat(output) .. sub(pattern, start) end pattern_simplifier = memoize(pattern_simplifier, true) export.pattern_simplifier = pattern_simplifier end --[==[ Parses `charset`, the interior of a string or ustring library character set, and normalizes it into a string or ustring library pattern (e.g. {"abcd-g"} becomes {"[abcd-g]"}, and {"[]"} becomes {"[[%]]"}). The negative (`^`), range (`-`) and literal (`%`) magic characters work as normal, and character classes may be used (e.g. `%d` and `%w`), but opening and closing square brackets are sanitized so that they behave like ordinary characters. ]==] function get_charset(charset) if type(charset) == "number" then return tostring(charset) end local pos, start, n, output = 1, 1, 0 if byte(charset) == 0x5E then -- ^ pos = pos + 1 end -- FIXME: "]" is non-magic if it's the first character in a charset. local nxt_pos, nxt while true do local new_pos, ch = match(charset, "()([%%%-%]])", pos) if not ch then break -- Skip percent escapes. Ranges can't start with them, either. elseif ch == "%" then pos = new_pos + 2 else -- If `ch` is a hyphen, get the character before iff it's at or ahead of `pos`. if ch == "-" and new_pos > pos then pos, nxt_pos, nxt = new_pos - 1, new_pos, ch ch = sub(charset, pos, pos) else pos, nxt_pos = new_pos, new_pos + 1 nxt = sub(charset, nxt_pos, nxt_pos) end -- Range. if nxt == "-" then if output == nil then output = {} end n = n + 1 output[n] = sub(charset, start, pos - 1) nxt_pos = nxt_pos + 1 nxt = sub(charset, nxt_pos, nxt_pos) -- Ranges fail if they end with a percent escape, so escape the hyphen to avoid undefined behaviour. if nxt == "" or nxt == "%" then n = n + 1 output[n] = (ch == "]" and "%]" or ch) .. "%-" start = nxt_pos nxt_pos = nxt_pos + 2 -- Since ranges can't contain "%]", since it's escaped, range inputs like "]-z" or "a-]" must be -- adjusted to the character before or after, plus "%]" (e.g. "%]^-z" or "a-\\%]"). The escaped "%]" is -- omitted if the range would be empty (i.e. if the first byte is greater than the second). else n = n + 1 output[n] = (ch == "]" and (byte(nxt) >= 0x5D and "%]^" or "^") or ch) .. "-" .. (nxt == "]" and (byte(ch) <= 0x5D and "\\%]" or "\\") or nxt) nxt_pos = nxt_pos + 1 start = nxt_pos end elseif ch == "-" or ch == "]" then if output == nil then output = {} end n = n + 1 output[n] = sub(charset, start, pos - 1) .. "%" .. ch start = nxt_pos end pos = nxt_pos end end if start == 1 then return "[" .. charset .. "]" end return "[" .. concat(output) .. sub(charset, start) .. "]" end get_charset = memoize(get_charset, true) export.get_charset = get_charset function export.len(str) return type(str) == "number" and len(str) or #str - #gsub(str, "[^\128-\191]+", "") end ulen = export.len function export.sub(str, i, j) str, i = type(str) == "number" and tostring(str) or str, i or 1 if i < 0 or j and j < 0 then return usub(str, i, j) elseif j and i > j or i > #str then return "" end local n, new_i = 0 for loc1, loc2 in gmatch(str, "()[^\128-\191]+()[\128-\191]*") do n = n + loc2 - loc1 if not new_i and n >= i then new_i = loc2 - (n - i) - 1 if not j then return sub(str, new_i) end end if j and n > j then return sub(str, new_i, loc2 - (n - j) - 1) end end return new_i and sub(str, new_i) or "" end do local function _find(str, loc1, loc2, ...) if loc1 and not match(str, "^()[^\128-\255]*$") then -- Use raw values of loc1 and loc2 to get loc1 and the length of the match. loc1, loc2 = ulen(sub(str, 1, loc1)), ulen(sub(str, loc1, loc2)) -- Offset length with loc1 to get loc2. loc2 = loc1 + loc2 - 1 end return loc1, loc2, ... end --[==[A version of find which uses string.find when possible, but otherwise uses mw.ustring.find.]==] function export.find(str, pattern, init, plain) init = init or 1 if init ~= 1 and not match(str, "^()[^\128-\255]*$") then return ufind(str, pattern, init, plain) elseif plain then return _find(str, find(str, pattern, init, true)) end local simple = pattern_simplifier(pattern) if simple then return _find(str, find(str, simple, init)) end return ufind(str, pattern, init) end end --[==[A version of match which uses string.match when possible, but otherwise uses mw.ustring.match.]==] function export.match(str, pattern, init) init = init or 1 if init ~= 1 and not match(str, "^()[^\128-\255]*$") then return umatch(str, pattern, init) end local simple = pattern_simplifier(pattern) if simple then return match(str, simple, init) end return umatch(str, pattern, init) end --[==[A version of gmatch which uses string.gmatch when possible, but otherwise uses mw.ustring.gmatch.]==] function export.gmatch(str, pattern) local simple = pattern_simplifier(pattern) if simple then return gmatch(str, simple) end return ugmatch(str, pattern) end --[==[A version of gsub which uses string.gsub when possible, but otherwise uses mw.ustring.gsub.]==] function export.gsub(str, pattern, repl, n) local simple = pattern_simplifier(pattern) if simple then return gsub(str, simple, repl, n) end return ugsub(str, pattern, repl, n) end --[==[ Like gsub, but pattern-matching facilities are turned off, so `pattern` and `repl` (if a string) are treated as literal. ]==] function export.plain_gsub(str, pattern, repl, n) return gsub(str, pattern_escape(pattern), type(repl) == "string" and replacement_escape(repl) or repl, n) end --[==[ Reverses a UTF-8 string; equivalent to string.reverse. ]==] function export.reverse(str) return reverse((gsub(str, "[\192-\255][\128-\191]*", reverse))) end function export.char(...) -- To be moved to [[Module:string/char]]. return u(...) end do local function utf8_err(func_name) error(format("bad argument #1 to '%s' (string is not UTF-8)", func_name), 4) end local function get_codepoint(func_name, b1, b2, b3, b4) if b1 <= 0x7F then return b1, 1 elseif not (b2 and b2 >= 0x80 and b2 <= 0xBF) then utf8_err(func_name) elseif b1 <= 0xDF then local cp = 0x40 * b1 + b2 - 0x3080 return cp >= 0x80 and cp or utf8_err(func_name), 2 elseif not (b3 and b3 >= 0x80 and b3 <= 0xBF) then utf8_err(func_name) elseif b1 <= 0xEF then local cp = 0x1000 * b1 + 0x40 * b2 + b3 - 0xE2080 return cp >= 0x800 and cp or utf8_err(func_name), 3 elseif not (b4 and b4 >= 0x80 and b4 <= 0xBF) then utf8_err(func_name) end local cp = 0x40000 * b1 + 0x1000 * b2 + 0x40 * b3 + b4 - 0x3C82080 return cp >= 0x10000 and cp <= 0x10FFFF and cp or utf8_err(func_name), 4 end function export.codepoint(str, i, j) if str == "" then return -- return nothing elseif type(str) == "number" then return byte(str, i, j) end i, j = i or 1, j == -1 and #str or i or 1 if i == 1 and j == 1 then return (get_codepoint("codepoint", byte(str, 1, 4))) elseif i < 0 or j < 0 then return ucodepoint(str, i, j) -- FIXME end local n, nb, ret, nr = 0, 1, {}, 0 while n < j do n = n + 1 if n < i then local b = byte(str, nb) nb = nb + (b < 128 and 1 or b < 224 and 2 or b < 240 and 3 or 4) else local b1, b2, b3, b4 = byte(str, nb, nb + 3) if not b1 then break end nr = nr + 1 local add ret[nr], add = get_codepoint("codepoint", b1, b2, b3, b4) nb = nb + add end end return unpack(ret) end codepoint = export.codepoint function export.gcodepoint(str, i, j) i, j = i or 1, j ~= -1 and j or nil if i < 0 or j and j < 0 then return ugcodepoint(str, i, j) -- FIXME end local n, nb = 1, 1 while n < i do local b = byte(str, nb) if not b then break end nb = nb + (b < 128 and 1 or b < 224 and 2 or b < 240 and 3 or 4) n = n + 1 end return function() if j and n > j then return nil end n = n + 1 local b1, b2, b3, b4 = byte(str, nb, nb + 3) if not b1 then return nil end local ret, add = get_codepoint("gcodepoint", b1, b2, b3, b4) nb = nb + add return ret end end end do local _ulower = ulower --[==[A version of lower which uses string.lower when possible, but otherwise uses mw.ustring.lower.]==] function export.lower(str) return (match(str, "^()[^\128-\255]*$") and lower or _ulower)(str) end end do local _uupper = uupper --[==[A version of upper which uses string.upper when possible, but otherwise uses mw.ustring.upper.]==] function export.upper(str) return (match(str, "^()[^\128-\255]*$") and upper or _uupper)(str) end end do local function add_captures(t, n, ...) if ... == nil then return end -- Insert any captures from the splitting pattern. local offset, capture = n - 1, ... while capture do n = n + 1 t[n] = capture capture = select(n - offset, ...) end return n end --[==[ Reimplementation of mw.text.split() that includes any capturing groups in the splitting pattern. This works like Python's re.split() function, except that it has Lua's behavior when the split pattern is empty (i.e. advancing by one character at a time; Python returns the whole remainder of the string). When possible, it will use the string library, but otherwise uses the ustring library. There are two optional parameters: `str_lib` forces use of the string library, while `plain` turns any pattern matching facilities off, treating `pattern` as literal. In addition, `pattern` may be a custom find function (or callable table), which takes the input string and start index as its two arguments, and must return the start and end index of the match, plus any optional captures, or nil if there are no further matches. By default, the start index will be calculated using the ustring library, unless `str_lib` or `plain` is set. ]==] function export.split(str, pattern_or_func, str_lib, plain) local iter, t, n = gsplit(str, pattern_or_func, str_lib, plain), {}, 0 repeat n = add_captures(t, n, iter()) until n == nil return t end export.capturing_split = export.split -- To be removed. end --[==[ Returns an iterator function, which iterates over the substrings returned by {split}. The first value returned is the string up the splitting pattern, with any capture groups being returned as additional values on that iteration. ]==] function export.gsplit(str, pattern_or_func, str_lib, plain) local start, final, str_len, _string, callable = 1 pattern_or_func, str_len, _string, callable = prepare_iter(str, pattern_or_func, str_lib, plain) local _find, _sub = _string.find, _string.sub local function iter(loc1, loc2, ...) -- If no match, or there is but we're past the end of the string -- (which happens when the match is the empty string), then return -- the final chunk. if not loc1 then final = true return _sub(str, start) end -- Special case: If we match the empty string, then eat the -- next character; this avoids an infinite loop, and makes -- splitting by the empty string work the way mw.text.gsplit() does -- (including non-adjacent empty string matches with %f). If we -- reach the end of the string this way, set `final` to true, so we -- don't get stuck matching the empty string at the end. local chunk if loc2 < loc1 then -- If using the string library, we need to make sure we advance -- by one UTF-8 character. if _sub == sub then local b = byte(str, loc1) if b and b >= 128 then loc1 = loc1 + (b < 224 and 1 or b < 240 and 2 or 3) end end chunk = _sub(str, start, loc1) if loc1 >= str_len then final = true else start = loc1 + 1 end -- Eat chunk up to the current match. else chunk = _sub(str, start, loc1 - 1) start = loc2 + 1 end return chunk, ... end if callable then return function() if not final then return iter(pattern_or_func(str, start)) end end -- Special case if the pattern is anchored to the start: "^" always -- anchors to the start position, not the start of the string, so get -- around this by only attempting one match with the pattern, then match -- the end of the string. elseif byte(pattern_or_func) == 0x5E then -- ^ local returned return function() if not returned then returned = true return iter(_find(str, pattern_or_func, start, plain)) elseif not final then return iter(_find(str, "$", start, plain)) end end end return function() if not final then return iter(_find(str, pattern_or_func, start, plain)) end end end gsplit = export.gsplit function export.count(str, pattern, plain) if plain then return select(2, gsub(str, pattern_escape(pattern), "")) end local simple = pattern_simplifier(pattern) if simple then return select(2, gsub(str, pattern, "")) end return select(2, ugsub(str, pattern, "")) end function export.trim(str, charset, str_lib, plain) if charset == nil then -- "^.*%S" is the fastest trim algorithm except when strings only consist of characters to be trimmed, which are -- very slow due to catastrophic backtracking. gsub with "^%s*" gets around this by trimming such strings to "" -- first. return match(gsub(str, "^%s*", ""), "^.*%S") or "" elseif charset == "" then return str end charset = plain and ("[" .. charset_escape(charset) .. "]") or get_charset(charset) -- The pattern uses a non-greedy quantifier instead of the algorithm used for %s, because negative character sets -- are non-trivial to compute (e.g. "[^^-z]" becomes "[%^_-z]"). Plus, if the ustring library has to be used, there -- would be two callbacks into PHP, which is slower. local pattern = "^" .. charset .. "*(.-)" .. charset .. "*$" if not str_lib then local simple = pattern_simplifier(pattern) if not simple then return umatch(str, pattern) end pattern = simple end return match(str, pattern) end trim = export.trim do local entities local function get_entities() entities, get_entities = load_data("Module:data/entities"), nil return entities end local function decode_entity(hash, x, code) if hash == "" then return (entities or get_entities())[x .. code] end local cp if x == "" then cp = match(code, "^()%d+$") and tonumber(code) else cp = match(code, "^()%x+$") and tonumber(code, 16) end return cp and (cp <= 0xD7FF or cp >= 0xE000 and cp <= 0x10FFFF) and u(cp) or nil end -- Non-ASCII characters aren't valid in proper HTML named entities, but MediaWiki uses them in some custom aliases -- which have also been included in [[Module:data/entities]]. function export.decode_entities(str) local amp = find(str, "&", nil, true) return amp and find(str, ";", amp, true) and gsub(str, "&(#?)([xX]?)([%w\128-\255]+);", decode_entity) or str end end do local entities local function get_entities() -- Memoized HTML entities (taken from mw.text.lua). entities, get_entities = { ["\""] = "&quot;", ["&"] = "&amp;", ["'"] = "&#039;", ["<"] = "&lt;", [">"] = "&gt;", ["\194\160"] = "&nbsp;", }, nil return entities end local function encode_entity(ch) local entity = (entities or get_entities())[ch] if entity == nil then local cp = codepoint(ch) -- U+D800 to U+DFFF are surrogates, so can't be encoded as entities. entity = cp and (cp <= 0xD7FF or cp >= 0xE000) and format("&#%d;", cp) or false entities[ch] = entity end return entity or nil end function export.encode_entities(str, charset, str_lib, plain) if charset == nil then return (gsub(str, "[\"&'<>\194]\160?", entities or get_entities())) elseif charset == "" then return str end local pattern = plain and ("[" .. charset_escape(charset) .. "]") or charset == "." and charset or get_charset(charset) if not str_lib then local simple = pattern_simplifier(pattern) if not simple then return (ugsub(str, pattern, encode_entity)) end pattern = simple end return (gsub(str, pattern, encode_entity)) end end do local function decode_path(code) return char(tonumber(code, 16)) end local function decode(lead, trail) if lead == "+" or lead == "_" then return " " .. trail elseif #trail == 2 then return decode_path(trail) end return lead .. trail end function export.decode_uri(str, enctype) enctype = enctype and upper(enctype) or "QUERY" if enctype == "PATH" then return find(str, "%", nil, true) and gsub(str, "%%(%x%x)", decode_path) or str elseif enctype == "QUERY" then return (find(str, "%", nil, true) or find(str, "+", nil, true)) and gsub(str, "([%%%+])(%x?%x?)", decode) or str elseif enctype == "WIKI" then return (find(str, "%", nil, true) or find(str, "_", nil, true)) and gsub(str, "([%%_])(%x?%x?)", decode) or str end error("bad argument #2 to 'decode_uri' (expected QUERY, PATH, or WIKI)", 2) end end do local function _remove_comments(str, pre) local head = find(str, "<!--", nil, true) if not head then return str end local ret, n = {sub(str, 1, head - 1)}, 1 while true do local loc = find(str, "-->", head + 4, true) if not loc then return pre and concat(ret) or concat(ret) .. sub(str, head) end head = loc + 3 loc = find(str, "<!--", head, true) if not loc then return concat(ret) .. sub(str, head) end n = n + 1 ret[n] = sub(str, head, loc - 1) head = loc end end --[==[ Removes any HTML comments from the input text. `stage` can be one of three options: * {"PRE"} (default) applies the method used by MediaWiki's preprocessor: all {{code|html|<nowiki><!-- ... --></nowiki>}} pairs are removed, as well as any text after an unclosed {{code|html|<nowiki><!--</nowiki>}}. This is generally suitable when parsing raw template or [[mw:Parser extension tags|parser extension tag]] code. (Note, however, that the actual method used by the preprocessor is considerably more complex and differs under certain conditions (e.g. comments inside nowiki tags); if full accuracy is absolutely necessary, use [[Module:template parser]] instead). * {"POST"} applies the method used to generate the final page output once all templates have been expanded: it loops over the text, removing any {{code|html|<nowiki><!-- ... --></nowiki>}} pairs until no more are found (e.g. {{code|html|<nowiki><!-<!-- ... -->- ... --></nowiki>}} would be fully removed), but any unclosed {{code|html|<nowiki><!--</nowiki>}} is ignored. This is suitable for handling links embedded in template inputs, where the {"PRE"} method will have already been applied by the native parser. * {"BOTH"} applies {"PRE"} then {"POST"}. ]==] function export.remove_comments(str, stage) if not stage or stage == "PRE" then return _remove_comments(str, true) end local processed = stage == "POST" and _remove_comments(str) or stage == "BOTH" and _remove_comments(str, true) or error("bad argument #2 to 'remove_comments' (expected PRE, POST, or BOTH)", 2) while processed ~= str do str = processed processed = _remove_comments(str) end return str end end do local byte_escapes local function get_byte_escapes() byte_escapes, get_byte_escapes = load_data("Module:string utilities/data").byte_escapes, nil return byte_escapes end local function escape_byte(b) return (byte_escapes or get_byte_escapes())[b] or format("\\%03d", byte(b)) end function export.escape_bytes(str) return (gsub(str, ".", escape_byte)) end end function export.format_fun(str, fun) return (gsub(str, "{(\\?)((\\?)[^{}]*)}", function(p1, name, p2) if #p1 + #p2 == 1 then return name == "op" and "{" or name == "cl" and "}" or error(mw.getCurrentFrame():getTitle() .. " format: unrecognized escape sequence '{\\" .. name .. "}'") elseif fun(name) and type(fun(name)) ~= "string" then error(mw.getCurrentFrame():getTitle() .. " format: \"" .. name .. "\" is a " .. type(fun(name)) .. ", not a string") end return fun(name) or error(mw.getCurrentFrame():getTitle() .. " format: \"" .. name .. "\" not found in table") end)) end format_fun = export.format_fun --[==[ This function, unlike {string.format} and {mw.ustring.format}, takes just two parameters, a format string and a table, and replaces all instances of { {param_name} } in the format string with the table's entry for {param_name}. The opening and closing brace characters can be escaped with { {\op} } and { {\cl} }, respectively. A table entry beginning with a slash can be escaped by doubling the initial slash. ====Examples==== * {string_utilities.format("{foo} fish, {bar} fish, {baz} fish, {quux} fish", {["foo"]="one", ["bar"]="two", ["baz"]="red", ["quux"]="blue"}) } *: produces: {"one fish, two fish, red fish, blue fish"} * {string_utilities.format("The set {\\op}1, 2, 3{\\cl} contains {\\\\hello} elements.", {["\\hello"]="three"})} *: produces: {"The set {1, 2, 3} contains three elements."} *:* Note that the single and double backslashes should be entered as double and quadruple backslashes when quoted in a literal string. ]==] function export.format(str, tbl) return format_fun(str, function(key) return tbl[key] end) end do local function do_uclcfirst(str, case_func) -- Re-case the first letter. local first, remainder = match(str, "^(.[\128-\191]*)(.*)") return first and (case_func(first) .. remainder) or "" end local function uclcfirst(str, case_func) -- Strip off any HTML tags at the beginning. This currently does not handle comments or <ref>...</ref> -- correctly; it's intended for text wrapped in <span> or the like, as happens when passing text through -- [[Module:links]]. local html_at_beginning = nil if str:match("^<") then while true do local html_tag, rest = str:match("^(<.->)(.*)$") if not html_tag then break end if not html_at_beginning then html_at_beginning = {} end insert(html_at_beginning, html_tag) str = rest end end -- If there's a link at the beginning, re-case the first letter of the -- link text. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local link, linktext, remainder = match(str, "^%[%[([^|%]]+)%|?(.-)%]%](.*)$") local retval if link then retval = "[[" .. link .. "|" .. do_uclcfirst(linktext ~= "" and linktext or link, case_func) .. "]]" .. remainder else retval = do_uclcfirst(str, case_func) end if html_at_beginning then retval = concat(html_at_beginning) .. retval end return retval end --[==[ Uppercase the first character of the input string, correctly handling one-part and two-part links, optionally surrounded by HTML tags such as `<nowiki><span>...</span></nowiki>`, possibly nested. Intended to correctly uppercase the first character of text that may include links that have been passed through `full_link()` in [[Module:links]] or a similar function. ]==] function export.ucfirst(str) return uclcfirst(str, uupper) end ucfirst = export.ucfirst --[==[ Lowercase the first character of the input string, correctly handling one-part and two-part links, optionally surrounded by HTML tags such as `<nowiki><span>...</span></nowiki>`, possibly nested. Intended to correctly lowercase the first character of text that may include links that have been passed through `full_link()` in [[Module:links]] or a similar function. ]==] function export.lcfirst(str) return uclcfirst(str, ulower) end --[==[Capitalizes each word of the input string. WARNING: May be broken in the presence of multiword links.]==] function export.capitalize(str) -- Capitalize multi-word that is separated by spaces -- by uppercasing the first letter of each part. return (ugsub(str, "%w+", ucfirst)) end local function do_title_case(first, remainder) first = uupper(first) return remainder == "" and first or (first .. ulower(remainder)) end --[==[ Capitalizes each word of the input string, with any further letters in each word being converted to lowercase. ]==] function export.title_case(str) return str == "" and "" or ugsub(str, "(%w)(%w*)", do_title_case) end title_case = export.title_case --[==[ Converts the input string to {{w|Camel case|CamelCase}}. Any non-word characters are treated as breaks between words. If `lower_first` is set, then the first character of the string will be lowercase (e.g. camelCase). ]==] function export.camel_case(str, lower_first) str = ugsub(str, "%W*(%w*)", title_case) return lower_first and do_uclcfirst(str, ulower) or str end end do local function do_snake_case(nonword, word) return nonword == "" and word or "_" .. word end --[==[ Converts the input string to {{w|Snake case|snake_case}}. Any non-word characters are treated as breaks between words. ]==] function export.snake_case(str) return (ugsub(str, "(%W*)(%w*)", do_snake_case)) end end return export ndjfpg4lokleft04xzto19wigx7fczh 218837 218836 2025-06-19T22:46:30Z Sponge2490 8927 Membatalkan semakan [[Special:Diff/218836|218836]] oleh [[Special:Contributions/Sponge2490|Sponge2490]] ([[User talk:Sponge2490|perbincangan]]) Ralat 218837 Scribunto text/plain local mw = mw local string = string local table = table local ustring = mw.ustring local byte = string.byte local char = string.char local concat = table.concat local find = string.find local format = string.format local gmatch = string.gmatch local gsub = string.gsub local len = string.len local load_data = mw.loadData local lower = string.lower local match = string.match local next = next local reverse = string.reverse local select = select local sort = table.sort local sub = string.sub local toNFD = ustring.toNFD local tonumber = tonumber local tostring = tostring local type = type local ucodepoint = ustring.codepoint local ufind = ustring.find local ugcodepoint = ustring.gcodepoint local ugmatch = ustring.gmatch local ugsub = ustring.gsub local ulower = ustring.lower local umatch = ustring.match local unpack = unpack local upper = string.upper local usub = ustring.sub local uupper = ustring.upper -- Defined below. local charset_escape local codepoint local explode_utf8 local format_fun local get_indefinite_article local pattern_escape local pattern_simplifier local php_trim local replacement_escape local u local ulen local module_name = "string_utilities" local export = {} --[==[Explodes a string into an array of UTF-8 characters. '''Warning''': this function has no safety checks for non-UTF-8 byte sequences, to optimize speed and memory use. Inputs containing them therefore result in undefined behaviour.]==] function export.explode_utf8(str) local text, i = {}, 0 for ch in gmatch(str, ".[\128-\191]*") do i = i + 1 text[i] = ch end return text end explode_utf8 = export.explode_utf8 do local chars = { ["\0"] = "%z", ["$"] = "%$", ["%"] = "%%", ["("] = "%(", [")"] = "%)", ["*"] = "%*", ["+"] = "%+", ["-"] = "%-", ["."] = "%.", ["?"] = "%?", ["["] = "%[", ["]"] = "%]", ["^"] = "%^" } --[==[Escapes the magic characters used in [[mw:Extension:Scribunto/Lua reference manual#Patterns|patterns]] (Lua's version of regular expressions): <code>$%()*+-.?[]^</code>, and converts the null character to <code>%z</code>. For example, {{code|lua|"^$()%.[]*+-?\0"}} becomes {{code|lua|"%^%$%(%)%%%.%[%]%*%+%-%?%z"}}. This is necessary when constructing a pattern involving arbitrary text (e.g. from user input).]==] function export.pattern_escape(str) return (gsub(str, "[%z$%%()*+%-.?[%]^]", chars)) end pattern_escape = export.pattern_escape --[==[Escapes the magic characters used in [[mw:Extension:Scribunto/Lua reference manual#Patterns|pattern]] character sets: <code>%-]^</code>, and converts the null character to <code>%z</code>.]==] function export.charset_escape(str) return (gsub(str, "[%z%%%-%]^]", chars)) end charset_escape = export.charset_escape end --[==[Escapes only <code>%</code>, which is the only magic character used in replacement [[mw:Extension:Scribunto/Lua reference manual#Patterns|patterns]] with string.gsub and mw.ustring.gsub.]==] function export.replacement_escape(str) return (gsub(str, "%%", "%%%%")) end replacement_escape = export.replacement_escape do local function check_sets_equal(set1, set2) local k2 for k1, v1 in next, set1 do local v2 = set2[k1] if v1 ~= v2 and (v2 == nil or not check_sets_equal(v1, v2)) then return false end k2 = next(set2, k2) end return next(set2, k2) == nil end local function check_sets(bytes) local key, set1, set = next(bytes) if set1 == true then return true elseif not check_sets(set1) then return false end while true do key, set = next(bytes, key) if not key then return true elseif not check_sets_equal(set, set1) then return false end end end local function make_charset(range) if #range == 1 then return char(range[1]) end sort(range) local compressed, n, start = {}, 0, range[1] for i = 1, #range do local this, nxt = range[i], range[i + 1] if nxt ~= this + 1 then n = n + 1 compressed[n] = this == start and char(this) or char(start) .. "-" .. char(this) start = nxt end end return "[" .. concat(compressed) .. "]" end local function parse_1_byte_charset(pattern, pos) while true do local ch, nxt_pos pos, ch, nxt_pos = match(pattern, "()([%%%]\194-\244][\128-\191]*)()", pos) if not ch then return false elseif ch == "%" then if match(pattern, "^[acdlpsuwxACDLPSUWXZ\128-\255]", nxt_pos) then return false end pos = pos + 2 elseif ch == "]" then pos = nxt_pos return pos else return false end end end --[==[Parses `pattern`, a ustring library pattern, and attempts to convert it into a string library pattern. If conversion isn't possible, returns false.]==] pattern_simplifier = require("Module:fun").memoize(function(pattern) if type(pattern) == "number" then return tostring(pattern) end local pos, captures, start, n, output = 1, 0, 1, 0 while true do local ch, nxt_pos pos, ch, nxt_pos = match(pattern, "()([%%(.[\194-\244][\128-\191]*)()", pos) if not ch then break end local nxt = sub(pattern, nxt_pos, nxt_pos) if ch == "%" then if nxt == "b" then if not match(pattern, "^()[^\128-\255][^\128-\255]", pos + 2) then return false end pos = pos + 4 elseif nxt == "f" then pos = pos + 2 if not match(pattern, "^()%[[^^]", pos) then return false end -- Only possible to convert a %f charset which is all -- ASCII, so use parse_1_byte_charset. pos = parse_1_byte_charset(pattern, pos) if not pos then return false end elseif nxt == "Z" then pos = pos + 2 nxt = sub(pattern, pos, pos) if nxt == "*" or nxt == "+" or nxt == "-" then pos = pos + 1 else output = output or {} n = n + 1 if nxt == "?" then output[n] = sub(pattern, start, pos - 3) .. "[\1-\127\194-\244]?[\128-\191]*" pos = pos + 1 else output[n] = sub(pattern, start, pos - 3) .. "[\1-\127\194-\244][\128-\191]*" end start = pos end elseif find("acdlpsuwxACDLPSUWX", nxt, 1, true) then return false -- Skip the next character if it's ASCII. Otherwise, we will -- still need to do length checks. else pos = pos + (byte(nxt) < 128 and 2 or 1) end elseif ch == "(" then if nxt == ")" or captures == 32 then return false end captures = captures + 1 pos = pos + 1 elseif ch == "." then if nxt == "*" or nxt == "+" or nxt == "-" then pos = pos + 2 else output = output or {} n = n + 1 if nxt == "?" then output[n] = sub(pattern, start, pos - 1) .. "[^\128-\191]?[\128-\191]*" pos = pos + 2 else output[n] = sub(pattern, start, pos - 1) .. "[^\128-\191][\128-\191]*" pos = pos + 1 end start = pos end elseif ch == "[" then -- Fail negative charsets. TODO: 1-byte charsets should be safe. if nxt == "^" then return false -- If the first character is "%", ch_len is determined by the -- next one instead. elseif nxt == "%" then nxt_pos = nxt_pos + 1 nxt = sub(pattern, nxt_pos, nxt_pos) end local ch_len = #match(pattern, "^.[\128-\191]*", nxt_pos) if ch_len == 1 then -- Single-byte charset. pos = parse_1_byte_charset(pattern, pos + 1) if not pos then return false end else -- Multibyte charset. local charset_pos, bytes = pos pos = pos + 1 while true do -- TODO: non-ASCII charset ranges. pos, ch, nxt_pos = match(pattern, "()([^\128-\191][\128-\191]*)()", pos) if not ch then return false -- If escaped, get the next character. No need to -- distinguish magic characters or character classes, -- as they'll all fail for having the wrong length -- anyway. elseif ch == "%" then pos, ch, nxt_pos = match(pattern, "()([^\128-\191][\128-\191]*)()", pos) elseif ch == "]" then pos = nxt_pos break end if ch_len ~= #ch then return false end bytes = bytes or {} local bytes = bytes for i = 1, ch_len - 1 do local b = byte(ch, i, i) bytes[b] = bytes[b] or {} bytes = bytes[b] end bytes[byte(ch, -1)] = true pos = nxt_pos end if not pos then return false end local nxt = sub(pattern, pos, pos) if ( (nxt == "?" or nxt == "*" or nxt == "-") or (nxt == "+" and ch_len > 2) or not check_sets(bytes) ) then return false end local ranges, b, key, next_byte = {}, 0 repeat key, next_byte = next(bytes) local range, n = {key}, 1 -- Loop starts on the second iteration. for key in next, bytes, key do n = n + 1 range[n] = key end b = b + 1 ranges[b] = range bytes = next_byte until next_byte == true if nxt == "+" then local range1, range2 = ranges[1], ranges[2] ranges[1] = make_charset(range1) ranges[3] = make_charset(range2) local n = #range2 for i = 1, #range1 do n = n + 1 range2[n] = range1[i] end ranges[2] = make_charset(range2) .. "*" pos = pos + 1 else for i = 1, #ranges do ranges[i] = make_charset(ranges[i]) end end output = output or {} n = n + 1 output[n] = sub(pattern, start, charset_pos - 1) .. concat(ranges) start = pos end elseif nxt == "+" then if #ch ~= 2 then return false end output = output or {} n = n + 1 output[n] = sub(pattern, start, pos) .. "[" .. ch .. "]*" .. sub(ch, 2, 2) pos = nxt_pos + 1 start = pos elseif nxt == "?" or nxt == "*" or nxt == "-" then return false else pos = nxt_pos end end if start == 1 then return pattern end return concat(output) .. sub(pattern, start) end, true) export.pattern_simplifier = pattern_simplifier -- For testing. end function export.len(str) return type(str) == "number" and len(str) or #str - #gsub(str, "[^\128-\191]+", "") end ulen = export.len function export.sub(str, i, j) str, i = type(str) == "number" and tostring(str) or str, i or 1 if i < 0 or j and j < 0 then return usub(str, i, j) elseif j and i > j or i > #str then return "" end local n, new_i = 0 for loc1, loc2 in gmatch(str, "()[^\128-\191]+()[\128-\191]*") do n = n + loc2 - loc1 if not new_i and n >= i then new_i = loc2 - (n - i) - 1 if not j then return sub(str, new_i) end end if j and n > j then return sub(str, new_i, loc2 - (n - j) - 1) end end return new_i and sub(str, new_i) or "" end do local function _find(str, loc1, loc2, ...) if loc1 and not match(str, "^()[^\128-\255]*$") then -- Use raw values of loc1 and loc2 to get loc1 and the length of the match. loc1, loc2 = ulen(sub(str, 1, loc1)), ulen(sub(str, loc1, loc2)) -- Offset length with loc1 to get loc2. loc2 = loc1 + loc2 - 1 end return loc1, loc2, ... end --[==[A version of find which uses string.find when possible, but otherwise uses mw.ustring.find.]==] function export.find(str, pattern, init, plain) init = init or 1 if init ~= 1 and not match(str, "^()[^\128-\255]*$") then return ufind(str, pattern, init, plain) elseif plain then return _find(str, find(str, pattern, init, true)) end local simple = pattern_simplifier(pattern) if simple then return _find(str, find(str, simple, init)) end return ufind(str, pattern, init) end end --[==[A version of match which uses string.match when possible, but otherwise uses mw.ustring.match.]==] function export.match(str, pattern, init) init = init or 1 if init ~= 1 and not match(str, "^()[^\128-\255]*$") then return umatch(str, pattern, init) end local simple = pattern_simplifier(pattern) if simple then return match(str, simple, init) end return umatch(str, pattern, init) end --[==[A version of gmatch which uses string.gmatch when possible, but otherwise uses mw.ustring.gmatch.]==] function export.gmatch(str, pattern) local simple = pattern_simplifier(pattern) if simple then return gmatch(str, simple) end return ugmatch(str, pattern) end --[==[A version of gsub which uses string.gsub when possible, but otherwise uses mw.ustring.gsub.]==] function export.gsub(str, pattern, repl, n) local simple = pattern_simplifier(pattern) if simple then return gsub(str, simple, repl, n) end return ugsub(str, pattern, repl, n) end --[==[Like gsub, but pattern-matching facilities are turned off, so `pattern` and `repl` (if a string) are treated as literal.]==] function export.plain_gsub(str, pattern, repl, n) return gsub(str, pattern_escape(pattern), type(repl) == "string" and replacement_escape(repl) or repl, n) end --[==[Reverses a UTF-8 string; equivalent to string.reverse.]==] function export.reverse(str) return reverse(gsub(str, "[\194-\244][\128-\191]*", reverse)) end do local function err(cp) error("Codepoint " .. cp .. " is out of range: codepoints must be between 0x0 and 0x10FFFF.", 2) end local function utf8_char(cp) cp = tonumber(cp) if cp < 0 then err(format("-0x%X", -cp)) elseif cp < 0x80 then return char(cp) elseif cp < 0x800 then return char( 0xC0 + cp / 0x40, 0x80 + cp % 0x40 ) elseif cp < 0x10000 then if cp >= 0xD800 and cp < 0xE000 then return "?" -- mw.ustring.char returns "?" for surrogates. end return char( 0xE0 + cp / 0x1000, 0x80 + cp / 0x40 % 0x40, 0x80 + cp % 0x40 ) elseif cp < 0x110000 then return char( 0xF0 + cp / 0x40000, 0x80 + cp / 0x1000 % 0x40, 0x80 + cp / 0x40 % 0x40, 0x80 + cp % 0x40 ) end err(format("0x%X", cp)) end function export.char(cp, ...) if ... == nil then return utf8_char(cp) end local ret = {cp, ...} for i = 1, select("#", cp, ...) do ret[i] = utf8_char(ret[i]) end return concat(ret) end u = export.char end do local function get_codepoint(b1, b2, b3, b4) if b1 < 128 then return b1, 1 elseif b1 < 224 then return 0x40 * b1 + b2 - 0x3080, 2 elseif b1 < 240 then return 0x1000 * b1 + 0x40 * b2 + b3 - 0xE2080, 3 end return 0x40000 * b1 + 0x1000 * b2 + 0x40 * b3 + b4 - 0x3C82080, 4 end function export.codepoint(str, i, j) if type(str) == "number" then return byte(str, i, j) end i, j = i or 1, j == -1 and #str or i or 1 if i == 1 and j == 1 then return (get_codepoint(byte(str, 1, 4))) elseif i < 0 or j < 0 then return ucodepoint(str, i, j) -- FIXME end local n, nb, ret, nr = 0, 1, {}, 0 while n < j do n = n + 1 if n < i then local b = byte(str, nb) nb = nb + (b < 128 and 1 or b < 224 and 2 or b < 240 and 3 or 4) else local b1, b2, b3, b4 = byte(str, nb, nb + 3) if not b1 then break end nr = nr + 1 local add ret[nr], add = get_codepoint(b1, b2, b3, b4) nb = nb + add end end return unpack(ret) end codepoint = export.codepoint function export.gcodepoint(str, i, j) i, j = i or 1, j ~= -1 and j or nil if i < 0 or j and j < 0 then return ugcodepoint(str, i, j) -- FIXME end local n, nb = 1, 1 while n < i do local b = byte(str, nb) if not b then break end nb = nb + (b < 128 and 1 or b < 224 and 2 or b < 240 and 3 or 4) n = n + 1 end return function() if j and n > j then return nil end n = n + 1 local b1, b2, b3, b4 = byte(str, nb, nb + 3) if not b1 then return nil end local ret, add = get_codepoint(b1, b2, b3, b4) nb = nb + add return ret end end end --[==[A version of lower which uses string.lower when possible, but otherwise uses mw.ustring.lower.]==] function export.lower(str) return (match(str, "^()[^\128-\255]*$") and lower or ulower)(str) end --[==[A version of upper which uses string.upper when possible, but otherwise uses mw.ustring.upper.]==] function export.upper(str) return (match(str, "^()[^\128-\255]*$") and upper or uupper)(str) end do local function add_captures(text, n, ...) -- Insert any captures from the splitting pattern. local offset, capture = n - 1, ... while capture do n = n + 1 text[n] = capture capture = select(n - offset, ...) end return n end local function iterate(str, str_len, text, n, start, _sub, loc1, loc2, ...) if not (loc1 and start <= str_len) then -- If no match, or there is but we're past the end of the string -- (which happens when the match is the empty string), then add -- the final chunk and return. n = n + 1 text[n] = _sub(str, start) return elseif loc2 < loc1 then -- Special case: If we match the empty string, then include the -- next character; this avoids an infinite loop, and makes -- splitting by an empty string work the way mw.text.split() does -- (including non-adjacent empty string matches with %f). If we -- reach the end of the string this way, return immediately, so we -- don't get a final empty string. If using the string library, we -- need to make sure we advance by one UTF-8 character. if _sub == sub then loc1 = loc1 + #match(str, "^[\128-\191]*", loc1 + 1) end n = n + 1 text[n] = _sub(str, start, loc1) start = loc1 + 1 if start > str_len then return ... and add_captures(text, n, ...) or n end else -- Add chunk up to the current match. n = n + 1 text[n] = _sub(str, start, loc1 - 1) start = loc2 + 1 end return (... and add_captures(text, n, ...) or n), start end local function _split(str, get_next, str_len, _sub, _find, func, plain) local text, n, start = {}, 0, 1 if func then repeat n, start = iterate(str, str_len, text, n, start, _sub, get_next(str, start)) until not start else repeat n, start = iterate(str, str_len, text, n, start, _sub, _find(str, get_next, start, plain)) until not start end return text end --[==[Reimplementation of mw.text.split() that includes any capturing groups in the splitting pattern. This works like Python's re.split() function, except that it has Lua's behavior when the split pattern is empty (i.e. advancing by one character at a time; Python returns the whole remainder of the string). When possible, it will use the string library, but otherwise uses the ustring library. There are two optional parameters: `str_lib` forces use of the string library, while `plain` turns any pattern matching facilities off, treating `pattern` as literal. In addition, `pattern` may be a custom find function, which takes the input string and start index as its two arguments, and must return the start and end index of the match, plus any optional captures, or nil if there are no further matches. By default, the start index will be calculated using the ustring library, unless `str_lib` or `plain` is set.]==] function export.split(str, pattern, str_lib, plain) local func = type(pattern) == "function" if str_lib or plain then return _split(str, pattern, #str, sub, find, func, plain) elseif not func then local simple = pattern_simplifier(pattern) if simple then return _split(str, simple, #str, sub, find) end end return _split(str, pattern, ulen(str), usub, ufind, func) end export.capturing_split = export.split -- To be removed. end do -- TODO: merge this with export.split. Not clear how to do this while -- maintaining the same level of performance, as gsplit is slower. local function _split(str, pattern, str_len, _sub, _find, plain) local start, final = 1 local function iter(loc1, loc2, ...) -- If no match, return the final chunk. if not loc1 then final = true return _sub(str, start) end -- Special case: If we match the empty string, then eat the -- next character; this avoids an infinite loop, and makes -- splitting by the empty string work the way mw.text.gsplit() does -- (including non-adjacent empty string matches with %f). If we -- reach the end of the string this way, set `final` to true, so we -- don't get stuck matching the empty string at the end. local chunk if loc2 < loc1 then -- If using the string library, we need to make sure we advance -- by one UTF-8 character. if _sub == sub then loc1 = loc1 + #match(str, "^[\128-\191]*", loc1 + 1) end chunk = _sub(str, start, loc1) if loc1 >= str_len then final = true else start = loc1 + 1 end -- Eat chunk up to the current match. else chunk = _sub(str, start, loc1 - 1) start = loc2 + 1 end return chunk, ... end return function() if not final then return iter(_find(str, pattern, start, plain)) end return nil end end function export.gsplit(str, pattern, str_lib, plain) if str_lib or plain then return _split(str, pattern, #str, sub, find, plain) end local simple = pattern_simplifier(pattern) if simple then return _split(str, simple, #str, sub, find) end return _split(str, pattern, ulen(str), usub, ufind) end end function export.trim(str, charset) if not charset then return match(str, "^()%s*$") and "" or match(str, "^%s*(.*%S)") elseif match(charset, "^()[^\128-\255]*$") then return match(str, "^()[" .. charset .. "]*$") and "" or match(str, "^[" .. charset .. "]*(.*[^" .. charset .. "])") end return umatch(str, "^[" .. charset .. "]*(.-)[" .. charset .. "]*$") end do local entities local function decode_numeric_entity(code, pattern, base) local cp = match(code, pattern) and tonumber(code, base) return cp and cp < 0x110000 and u(cp) or nil end local function decode_entity(hash, x, code) if hash == "#" then return x == "" and decode_numeric_entity(code, "^%d+$") or decode_numeric_entity(code, "^%x+$", 16) end entities = entities or load_data("Module:data/entities") return entities[x .. code] end -- Non-ASCII characters aren't valid in proper HTML named entities, but MediaWiki uses them in some custom aliases which have also been included in [[Module:data/entities]]. function export.decode_entities(str) return find(str, "&", 1, true) and gsub(str, "&(#?)([xX]?)([%w\128-\255]+);", decode_entity) or str end end do local html_entities local function encode_entity(ch) local entity = html_entities[ch] if entity then return entity end entity = "&#" .. codepoint(ch) .. ";" html_entities[ch] = entity return entity end function export.encode_entities(str, charset, str_lib, plain) -- Memoized HTML entities (taken from mw.text.lua). html_entities = html_entities or { ["\""] = "&quot;", ["&"] = "&amp;", ["'"] = "&#039;", ["<"] = "&lt;", [">"] = "&gt;", ["\194\160"] = "&nbsp;", } if not charset then return (gsub(str, "[\"&'<>\194]\160?", html_entities)) elseif plain then return (gsub(str, "[" .. charset_escape(charset) .. "]", encode_entity)) elseif str_lib then if not match(charset, "^()[^\128-\255]*$") then error("Cannot use the string library with a character set that contains a character with a codepoint above U+007F.") end return (gsub(str, "[" .. charset .. "]", encode_entity)) end local pattern = charset and "[" .. charset .. "]" local simple = pattern_simplifier(pattern) if simple then return (gsub(str, simple, encode_entity)) end return (ugsub(str, pattern, encode_entity)) end end do local function decode_path(code) return char(tonumber(code, 16)) end local function decode(lead, trail) if lead == "+" or lead == "_" then return " " .. trail elseif #trail == 2 then return decode_path(trail) end return lead .. trail end function export.decode_uri(str, enctype) enctype = enctype and upper(enctype) or "QUERY" if enctype == "PATH" then return find(str, "%", 1, true) and gsub(str, "%%(%x%x)", decode_path) or str elseif enctype == "QUERY" then return (find(str, "%", 1, true) or find(str, "+", 1, true)) and gsub(str, "([%%%+])(%x?%x?)", decode) or str elseif enctype == "WIKI" then return (find(str, "%", 1, true) or find(str, "_", 1, true)) and gsub(str, "([%%_])(%x?%x?)", decode) or str end error("bad argument #2 to \"decode_uri\" (expected QUERY, PATH, or WIKI)", 2) end end do local function _remove_comments(str, pre) local head = find(str, "<!--", 1, true) if not head then return str end local ret, n = {sub(str, 1, head - 1)}, 1 while true do local loc = find(str, "-->", head + 4, true) if not loc then return pre and concat(ret) or concat(ret) .. sub(str, head) end head = loc + 3 loc = find(str, "<!--", head, true) if not loc then return concat(ret) .. sub(str, head) end n = n + 1 ret[n] = sub(str, head, loc - 1) head = loc end end --[==[Removes any HTML comments from the input text. `stage` can be one of three options: * {{lua|"PRE"}} (default) applies the method used by MediaWiki's preprocessor: all {{code||<nowiki><!-- ... --></nowiki>}} pairs are removed, as well as any text after an unclosed {{code||<nowiki><!--</nowiki>}}. This is generally suitable when parsing raw template or [[mw:Parser extension tags|parser extension tag]] code. (Note, however, that the actual method used by the preprocessor is considerably more complex and differs under certain conditions (e.g. comments inside nowiki tags); if full accuracy is absolutely necessary, use [[Module:template parser]] instead). * {{lua|"POST"}} applies the method used to generate the final page output once all templates have been expanded: it loops over the text, removing any {{code||<nowiki><!-- ... --></nowiki>}} pairs until no more are found (e.g. {{code||<nowiki><!-<!-- ... -->- ... --></nowiki>}} would be fully removed), but any unclosed {{code||<nowiki><!--</nowiki>}} is ignored. This is suitable for handling links embedded in template inputs, where the {{lua|"PRE"}} method will have already been applied by the native parser. * {{lua|"BOTH"}} applies {{lua|"PRE"}} then {{lua|"POST"}}.]==] function export.remove_comments(str, stage) if not stage or stage == "PRE" then return _remove_comments(str, true) end local processed = stage == "POST" and _remove_comments(str) or stage == "BOTH" and _remove_comments(str, true) or error("bad argument #2 to \"remove_comments\" (expected PRE, POST, or BOTH)", 2) while processed ~= str do str = processed processed = _remove_comments(str) end return str end end --[==[Lua equivalent of PHP's {{code|php|trim($string)}}, which trims {{code|lua|"\0"}}, {{code|lua|"\t"}}, {{code|lua|"\n"}}, {{code|lua|"\v"}}, {{code|lua|"\r"}} and {{code|lua|" "}}. This is useful when dealing with template parameters, since the native parser trims them like this.]==] function export.php_trim(str) return match(str, "%f[^%z\t\n\v\r ].*%f[%z\t\n\v\r ]") or "" end php_trim = export.php_trim --[==[Takes a parameter name as an input, and returns the Scribunto-normalized form (i.e. the key that that parameter would have in a {{code|lua|frame.args}} table). For example, {{code|lua|"1"}} is normalized to {{code|lua|1}} (a number), and {{code|lua|" foo "}} is normalized to {{code|lua|"foo"}}. If the input is not a string, it is returned unchanged. After being trimmed with {{code|lua|export.php_trim}}, strings are converted to numbers if: # They are integers, with no decimals (2.0) or leading zeroes (02). # They are ≤ 2{{sup|53}} and ≥ -2{{sup|53}}. # For positive values, they do not have a leading {{code|lua|+}} sign.]==] function export.scribunto_param_key(key) if type(key) ~= "string" then return key end key = php_trim(key) if match(key, "^-?[1-9]%d*$") then local num = tonumber(key) -- Lua integers are only accurate to 2^53 - 1, so we have to specifically check for 2^53 and -2^53, since 2^53 == 2^53 + 1 evaluates to true. return ( num <= 9007199254740991 and num >= -9007199254740991 or key == "9007199254740992" or key == "-9007199254740992" ) and num or key elseif key == "0" then return 0 end return key end do local byte_escapes local function escape_byte(b) return byte_escapes[b] or format("\\%03d", byte(b)) end function export.escape_bytes(str) byte_escapes = byte_escapes or load_data("Module:string utilities/data").byte_escapes return (gsub(str, ".", escape_byte)) end end function export.format_fun(str, fun) return (gsub(str, "{(\\?)((\\?)[^{}]*)}", function(p1, name, p2) if #p1 + #p2 == 1 then return name == "op" and "{" or name == "cl" and "}" or error(module_name .. ".format: unrecognized escape sequence '{\\" .. name .. "}'") elseif fun(name) and type(fun(name)) ~= "string" then error(module_name .. ".format: \"" .. name .. "\" is a " .. type(fun(name)) .. ", not a string") end return fun(name) or error(module_name .. ".format: \"" .. name .. "\" not found in table") end)) end format_fun = export.format_fun --[==[This function, unlike {{code|lua|string.format}} and {{code|lua|mw.ustring.format}}, takes just two parameters—a format string and a table—and replaces all instances of {{code|lua|{param_name}}} in the format string with the table's entry for {{code|lua|param_name}}. The opening and closing brace characters can be escaped with <code>{\op}</code> and <code>{\cl}</code>, respectively. A table entry beginning with a slash can be escaped by doubling the initial slash. ====Examples==== * {{code|lua|2=string_utilities.format("{foo} fish, {bar} fish, {baz} fish, {quux} fish", {["foo"]="one", ["bar"]="two", ["baz"]="red", ["quux"]="blue"})}} *: produces: {{code|lua|"one fish, two fish, red fish, blue fish"}} * {{code|lua|2=string_utilities.format("The set {\\op}1, 2, 3{\\cl} contains {\\\\hello} elements.", {["\\hello"]="three"})}} *: produces: {{code|lua|"The set {1, 2, 3} contains three elements."}} *:* Note that the single and double backslashes should be entered as double and quadruple backslashes when quoted in a literal string.]==] function export.format(str, tbl) return format_fun(str, function(key) return tbl[key] end) end do local function do_uclcfirst(str, case_func) -- Actual function to re-case of the first letter. local first_letter = case_func(match(str, "^.[\128-\191]*") or "") return first_letter .. sub(str, #first_letter + 1) end local function uclcfirst(str, case_func) -- If there's a link at the beginning, re-case the first letter of the -- link text. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local link, linktext, remainder = match(str, "^%[%[([^|%]]+)%|?(.-)%]%](.*)$") if link then return "[[" .. link .. "|" .. do_uclcfirst(linktext ~= "" and linktext or link, case_func) .. "]]" .. remainder end return do_uclcfirst(str, case_func) end function export.ucfirst(str) return uclcfirst(str, uupper) end function export.lcfirst(str) return uclcfirst(str, ulower) end local function capitalize(w) return uclcfirst(w, uupper) end --[==[Capitalize each word of a string. WARNING: May be broken in the presence of multiword links.]==] function export.capitalize(str) if type(str) == "table" then -- allow calling from a template str = str.args[1] end -- Capitalize multi-word that is separated by spaces -- by uppercasing the first letter of each part. -- I assume nobody will input all CAP text. return (ugsub(str, "%S+", capitalize)) end end function export.pluralize(str) -- To be removed once all calling modules have been changed to call Module:en-utilities directly. return require("Module:en-utilities").pluralize(str) end do local function do_singularize(str) -- (not applicable to Malay Wiktionary) local sing = match(str, "^(.-)$") if sing then return sing .. "" end -- Handle cases like "[[parish]]es" (not applicable to Malay Wiktionary) return match(str, "^(.-[cs]h%]*)$") or -- not -zhes -- Handle cases like "[[box]]es" (not applicable to Malay Wiktionary) match(str, "^(.-x%]*)$") or -- not -ses or -zes -- Handle regular plurals (not applicable to Malay Wiktionary) match(str, "^(.-)$") or -- Otherwise, return input str end local function collapse_link(link, linktext) if link == linktext then return "[[" .. link .. "]]" end return "[[" .. link .. "|" .. linktext .. "]]" end --[==[ Singularize a word in a smart fashion, according to normal English rules. Works analogously to {pluralize()}. '''NOTE''': This doesn't always work as well as {pluralize()}. Beware. It will mishandle cases like "passes" -> "passe", "eyries" -> "eyry". # If word ends in -ies, replace -ies with -y. # If the word ends in -xes, -shes, -ches, remove -es. [Does not affect -ses, cf. "houses", "impasses".] # Otherwise, remove -s. This handles links correctly: # If a piped link, change the second part appropriately. Collapse the link to a simple link if both parts end up the same. # If a non-piped link, singularize the link. # A link like "[[parish]]es" will be handled correctly because the code that checks for -shes etc. allows ] characters between the 'sh' etc. and final -es. ]==] function export.singularize(str) if type(str) == "table" then -- allow calling from a template str = str.args[1] end -- Check for a link. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local beginning, link, linktext = match(str, "^(.*)%[%[([^|%]]+)%|?(.-)%]%]$") if not link then return do_singularize(str) elseif linktext ~= "" then return beginning .. collapse_link(link, do_singularize(linktext)) end return beginning .. "[[" .. do_singularize(link) .. "]]" end end --[==[ Return the appropriate indefinite article to prefix to `str`. Correctly handles links and capitalized text. Does not correctly handle words like [[union]], [[uniform]] and [[university]] that take "a" despite beginning with a 'u'. The returned article will have its first letter capitalized if `ucfirst` is specified, otherwise lowercase. ]==] function export.get_indefinite_article(str, ucfirst) str = str or "" local is_vowel = false -- If there's a link at the beginning, examine the first letter of the -- link text. This pattern matches both piped and unpiped links. -- If the link is not piped, the second capture (linktext) will be empty. local link, linktext = match(str, "^%[%[([^|%]]+)%|?(.-)%]%]") if link then is_vowel = find(linktext ~= "" and linktext or link, "^[AEIOUaeiou]") else is_vowel = find(str, "^[AEIOUaeiou]") end return is_vowel and (ucfirst and "An" or "an") or (ucfirst and "A" or "a") end get_indefinite_article = export.get_indefinite_article --[==[ Prefix `text` with the appropriate indefinite article to prefix to `text`. Correctly handles links and capitalized text. Does not correctly handle words like [[union]], [[uniform]] and [[university]] that take "a" despite beginning with a 'u'. The returned article will have its first letter capitalized if `ucfirst` is specified, otherwise lowercase. ]==] function export.add_indefinite_article(text, ucfirst) return get_indefinite_article(text, ucfirst) .. " " .. text end return export p2bd29sdmm5onk4gw6hipjam6fp958v kata seerti 0 24347 218852 186824 2025-06-20T11:46:54Z 2001:D08:EA:81E2:E89B:5E9D:5AD:7F2A Dibenci 218852 wikitext text/x-wiki di benci == Bahasa Melayu == {{Wikipedia}} === Takrifan === ==== Kata nama ==== {{ms-kn|j=کات سأرتي}} # Perkataan-perkataan yang memiliki [[makna]] yang [[sama]]; [[sinonim]]. === Sebutan === * {{dewan|ka|ta||se|er|ti}} === Pautan luar === * {{R:PRPM}} {{C|ms|Semantik}} 6eyhideo6spw3wlz0srdbnqwfyo3o1r Modul:data/entities 828 41384 218835 155268 2025-06-19T22:39:25Z Sponge2490 8927 Mengemaskini berdasarkan Module:data/entities pada 17 Disember 2023 (77232189) 218835 Scribunto text/plain return { aacute = "\195\161", -- á Aacute = "\195\129", -- Á abreve = "\196\131", -- ă Abreve = "\196\130", -- Ă ac = "\226\136\190", -- ∾ acd = "\226\136\191", -- ∿ acE = "\226\136\190\204\179", -- ∾̳ acirc = "\195\162", -- â Acirc = "\195\130", --  acute = "\194\180", -- ´ acy = "\208\176", -- а Acy = "\208\144", -- А aelig = "\195\166", -- æ AElig = "\195\134", -- Æ af = "\226\129\161", -- [function application] afr = "\240\157\148\158", -- 𝔞 Afr = "\240\157\148\132", -- 𝔄 agrave = "\195\160", -- à Agrave = "\195\128", -- À alefsym = "\226\132\181", -- ℵ aleph = "\226\132\181", -- ℵ alpha = "\206\177", -- α Alpha = "\206\145", -- Α amacr = "\196\129", -- ā Amacr = "\196\128", -- Ā amalg = "\226\168\191", -- ⨿ amp = "\38", -- & AMP = "\38", -- & ["and"] = "\226\136\167", -- ∧ And = "\226\169\147", -- ⩓ andand = "\226\169\149", -- ⩕ andd = "\226\169\156", -- ⩜ andslope = "\226\169\152", -- ⩘ andv = "\226\169\154", -- ⩚ ang = "\226\136\160", -- ∠ ange = "\226\166\164", -- ⦤ angle = "\226\136\160", -- ∠ angmsd = "\226\136\161", -- ∡ angmsdaa = "\226\166\168", -- ⦨ angmsdab = "\226\166\169", -- ⦩ angmsdac = "\226\166\170", -- ⦪ angmsdad = "\226\166\171", -- ⦫ angmsdae = "\226\166\172", -- ⦬ angmsdaf = "\226\166\173", -- ⦭ angmsdag = "\226\166\174", -- ⦮ angmsdah = "\226\166\175", -- ⦯ angrt = "\226\136\159", -- ∟ angrtvb = "\226\138\190", -- ⊾ angrtvbd = "\226\166\157", -- ⦝ angsph = "\226\136\162", -- ∢ angst = "\195\133", -- Å angzarr = "\226\141\188", -- ⍼ aogon = "\196\133", -- ą Aogon = "\196\132", -- Ą aopf = "\240\157\149\146", -- 𝕒 Aopf = "\240\157\148\184", -- 𝔸 ap = "\226\137\136", -- ≈ apacir = "\226\169\175", -- ⩯ ape = "\226\137\138", -- ≊ apE = "\226\169\176", -- ⩰ apid = "\226\137\139", -- ≋ apos = "\39", -- ' ApplyFunction = "\226\129\161", -- [function application] approx = "\226\137\136", -- ≈ approxeq = "\226\137\138", -- ≊ aring = "\195\165", -- å Aring = "\195\133", -- Å ascr = "\240\157\146\182", -- 𝒶 Ascr = "\240\157\146\156", -- 𝒜 Assign = "\226\137\148", -- ≔ ast = "\42", -- * asymp = "\226\137\136", -- ≈ asympeq = "\226\137\141", -- ≍ atilde = "\195\163", -- ã Atilde = "\195\131", -- à auml = "\195\164", -- ä Auml = "\195\132", -- Ä awconint = "\226\136\179", -- ∳ awint = "\226\168\145", -- ⨑ backcong = "\226\137\140", -- ≌ backepsilon = "\207\182", -- ϶ backprime = "\226\128\181", -- ‵ backsim = "\226\136\189", -- ∽ backsimeq = "\226\139\141", -- ⋍ Backslash = "\226\136\150", -- ∖ Barv = "\226\171\167", -- ⫧ barvee = "\226\138\189", -- ⊽ barwed = "\226\140\133", -- ⌅ Barwed = "\226\140\134", -- ⌆ barwedge = "\226\140\133", -- ⌅ bbrk = "\226\142\181", -- ⎵ bbrktbrk = "\226\142\182", -- ⎶ bcong = "\226\137\140", -- ≌ bcy = "\208\177", -- б Bcy = "\208\145", -- Б bdquo = "\226\128\158", -- „ becaus = "\226\136\181", -- ∵ because = "\226\136\181", -- ∵ Because = "\226\136\181", -- ∵ bemptyv = "\226\166\176", -- ⦰ bepsi = "\207\182", -- ϶ bernou = "\226\132\172", -- ℬ Bernoullis = "\226\132\172", -- ℬ beta = "\206\178", -- β Beta = "\206\146", -- Β beth = "\226\132\182", -- ℶ between = "\226\137\172", -- ≬ bfr = "\240\157\148\159", -- 𝔟 Bfr = "\240\157\148\133", -- 𝔅 bigcap = "\226\139\130", -- ⋂ bigcirc = "\226\151\175", -- ◯ bigcup = "\226\139\131", -- ⋃ bigodot = "\226\168\128", -- ⨀ bigoplus = "\226\168\129", -- ⨁ bigotimes = "\226\168\130", -- ⨂ bigsqcup = "\226\168\134", -- ⨆ bigstar = "\226\152\133", -- ★ bigtriangledown = "\226\150\189", -- ▽ bigtriangleup = "\226\150\179", -- △ biguplus = "\226\168\132", -- ⨄ bigvee = "\226\139\129", -- ⋁ bigwedge = "\226\139\128", -- ⋀ bkarow = "\226\164\141", -- ⤍ blacklozenge = "\226\167\171", -- ⧫ blacksquare = "\226\150\170", -- ▪ blacktriangle = "\226\150\180", -- ▴ blacktriangledown = "\226\150\190", -- ▾ blacktriangleleft = "\226\151\130", -- ◂ blacktriangleright = "\226\150\184", -- ▸ blank = "\226\144\163", -- ␣ blk12 = "\226\150\146", -- ▒ blk14 = "\226\150\145", -- ░ blk34 = "\226\150\147", -- ▓ block = "\226\150\136", -- █ bne = "\61\226\131\165", -- =⃥ bnequiv = "\226\137\161\226\131\165", -- ≡⃥ bnot = "\226\140\144", -- ⌐ bNot = "\226\171\173", -- ⫭ bopf = "\240\157\149\147", -- 𝕓 Bopf = "\240\157\148\185", -- 𝔹 bot = "\226\138\165", -- ⊥ bottom = "\226\138\165", -- ⊥ bowtie = "\226\139\136", -- ⋈ boxbox = "\226\167\137", -- ⧉ boxdl = "\226\148\144", -- ┐ boxdL = "\226\149\149", -- ╕ boxDl = "\226\149\150", -- ╖ boxDL = "\226\149\151", -- ╗ boxdr = "\226\148\140", -- ┌ boxdR = "\226\149\146", -- ╒ boxDr = "\226\149\147", -- ╓ boxDR = "\226\149\148", -- ╔ boxh = "\226\148\128", -- ─ boxH = "\226\149\144", -- ═ boxhd = "\226\148\172", -- ┬ boxhD = "\226\149\165", -- ╥ boxHd = "\226\149\164", -- ╤ boxHD = "\226\149\166", -- ╦ boxhu = "\226\148\180", -- ┴ boxhU = "\226\149\168", -- ╨ boxHu = "\226\149\167", -- ╧ boxHU = "\226\149\169", -- ╩ boxminus = "\226\138\159", -- ⊟ boxplus = "\226\138\158", -- ⊞ boxtimes = "\226\138\160", -- ⊠ boxul = "\226\148\152", -- ┘ boxuL = "\226\149\155", -- ╛ boxUl = "\226\149\156", -- ╜ boxUL = "\226\149\157", -- ╝ boxur = "\226\148\148", -- └ boxuR = "\226\149\152", -- ╘ boxUr = "\226\149\153", -- ╙ boxUR = "\226\149\154", -- ╚ boxv = "\226\148\130", -- │ boxV = "\226\149\145", -- ║ boxvh = "\226\148\188", -- ┼ boxvH = "\226\149\170", -- ╪ boxVh = "\226\149\171", -- ╫ boxVH = "\226\149\172", -- ╬ boxvl = "\226\148\164", -- ┤ boxvL = "\226\149\161", -- ╡ boxVl = "\226\149\162", -- ╢ boxVL = "\226\149\163", -- ╣ boxvr = "\226\148\156", -- ├ boxvR = "\226\149\158", -- ╞ boxVr = "\226\149\159", -- ╟ boxVR = "\226\149\160", -- ╠ bprime = "\226\128\181", -- ‵ breve = "\203\152", -- ˘ Breve = "\203\152", -- ˘ brvbar = "\194\166", -- ¦ bscr = "\240\157\146\183", -- 𝒷 Bscr = "\226\132\172", -- ℬ bsemi = "\226\129\143", -- ⁏ bsim = "\226\136\189", -- ∽ bsime = "\226\139\141", -- ⋍ bsol = "\92", -- \ bsolb = "\226\167\133", -- ⧅ bsolhsub = "\226\159\136", -- ⟈ bull = "\226\128\162", -- • bullet = "\226\128\162", -- • bump = "\226\137\142", -- ≎ bumpe = "\226\137\143", -- ≏ bumpE = "\226\170\174", -- ⪮ bumpeq = "\226\137\143", -- ≏ Bumpeq = "\226\137\142", -- ≎ cacute = "\196\135", -- ć Cacute = "\196\134", -- Ć cap = "\226\136\169", -- ∩ Cap = "\226\139\146", -- ⋒ capand = "\226\169\132", -- ⩄ capbrcup = "\226\169\137", -- ⩉ capcap = "\226\169\139", -- ⩋ capcup = "\226\169\135", -- ⩇ capdot = "\226\169\128", -- ⩀ CapitalDifferentialD = "\226\133\133", -- ⅅ caps = "\226\136\169\239\184\128", -- ∩︀ caret = "\226\129\129", -- ⁁ caron = "\203\135", -- ˇ Cayleys = "\226\132\173", -- ℭ ccaps = "\226\169\141", -- ⩍ ccaron = "\196\141", -- č Ccaron = "\196\140", -- Č ccedil = "\195\167", -- ç Ccedil = "\195\135", -- Ç ccirc = "\196\137", -- ĉ Ccirc = "\196\136", -- Ĉ Cconint = "\226\136\176", -- ∰ ccups = "\226\169\140", -- ⩌ ccupssm = "\226\169\144", -- ⩐ cdot = "\196\139", -- ċ Cdot = "\196\138", -- Ċ cedil = "\194\184", -- ¸ Cedilla = "\194\184", -- ¸ cemptyv = "\226\166\178", -- ⦲ cent = "\194\162", -- ¢ centerdot = "\194\183", -- · CenterDot = "\194\183", -- · cfr = "\240\157\148\160", -- 𝔠 Cfr = "\226\132\173", -- ℭ chcy = "\209\135", -- ч CHcy = "\208\167", -- Ч check = "\226\156\147", -- ✓ checkmark = "\226\156\147", -- ✓ chi = "\207\135", -- χ Chi = "\206\167", -- Χ cir = "\226\151\139", -- ○ circ = "\203\134", -- ˆ circeq = "\226\137\151", -- ≗ circlearrowleft = "\226\134\186", -- ↺ circlearrowright = "\226\134\187", -- ↻ circledast = "\226\138\155", -- ⊛ circledcirc = "\226\138\154", -- ⊚ circleddash = "\226\138\157", -- ⊝ CircleDot = "\226\138\153", -- ⊙ circledR = "\194\174", -- ® circledS = "\226\147\136", -- Ⓢ CircleMinus = "\226\138\150", -- ⊖ CirclePlus = "\226\138\149", -- ⊕ CircleTimes = "\226\138\151", -- ⊗ cire = "\226\137\151", -- ≗ cirE = "\226\167\131", -- ⧃ cirfnint = "\226\168\144", -- ⨐ cirmid = "\226\171\175", -- ⫯ cirscir = "\226\167\130", -- ⧂ ClockwiseContourIntegral = "\226\136\178", -- ∲ CloseCurlyDoubleQuote = "\226\128\157", -- ” CloseCurlyQuote = "\226\128\153", -- ’ clubs = "\226\153\163", -- ♣ clubsuit = "\226\153\163", -- ♣ colon = "\58", -- : Colon = "\226\136\183", -- ∷ colone = "\226\137\148", -- ≔ Colone = "\226\169\180", -- ⩴ coloneq = "\226\137\148", -- ≔ comma = "\44", -- , commat = "\64", -- @ comp = "\226\136\129", -- ∁ compfn = "\226\136\152", -- ∘ complement = "\226\136\129", -- ∁ complexes = "\226\132\130", -- ℂ cong = "\226\137\133", -- ≅ congdot = "\226\169\173", -- ⩭ Congruent = "\226\137\161", -- ≡ conint = "\226\136\174", -- ∮ Conint = "\226\136\175", -- ∯ ContourIntegral = "\226\136\174", -- ∮ copf = "\240\157\149\148", -- 𝕔 Copf = "\226\132\130", -- ℂ coprod = "\226\136\144", -- ∐ Coproduct = "\226\136\144", -- ∐ copy = "\194\169", -- © COPY = "\194\169", -- © copysr = "\226\132\151", -- ℗ CounterClockwiseContourIntegral = "\226\136\179", -- ∳ crarr = "\226\134\181", -- ↵ cross = "\226\156\151", -- ✗ Cross = "\226\168\175", -- ⨯ cscr = "\240\157\146\184", -- 𝒸 Cscr = "\240\157\146\158", -- 𝒞 csub = "\226\171\143", -- ⫏ csube = "\226\171\145", -- ⫑ csup = "\226\171\144", -- ⫐ csupe = "\226\171\146", -- ⫒ ctdot = "\226\139\175", -- ⋯ cudarrl = "\226\164\184", -- ⤸ cudarrr = "\226\164\181", -- ⤵ cuepr = "\226\139\158", -- ⋞ cuesc = "\226\139\159", -- ⋟ cularr = "\226\134\182", -- ↶ cularrp = "\226\164\189", -- ⤽ cup = "\226\136\170", -- ∪ Cup = "\226\139\147", -- ⋓ cupbrcap = "\226\169\136", -- ⩈ cupcap = "\226\169\134", -- ⩆ CupCap = "\226\137\141", -- ≍ cupcup = "\226\169\138", -- ⩊ cupdot = "\226\138\141", -- ⊍ cupor = "\226\169\133", -- ⩅ cups = "\226\136\170\239\184\128", -- ∪︀ curarr = "\226\134\183", -- ↷ curarrm = "\226\164\188", -- ⤼ curlyeqprec = "\226\139\158", -- ⋞ curlyeqsucc = "\226\139\159", -- ⋟ curlyvee = "\226\139\142", -- ⋎ curlywedge = "\226\139\143", -- ⋏ curren = "\194\164", -- ¤ curvearrowleft = "\226\134\182", -- ↶ curvearrowright = "\226\134\183", -- ↷ cuvee = "\226\139\142", -- ⋎ cuwed = "\226\139\143", -- ⋏ cwconint = "\226\136\178", -- ∲ cwint = "\226\136\177", -- ∱ cylcty = "\226\140\173", -- ⌭ dagger = "\226\128\160", -- † Dagger = "\226\128\161", -- ‡ daleth = "\226\132\184", -- ℸ darr = "\226\134\147", -- ↓ dArr = "\226\135\147", -- ⇓ Darr = "\226\134\161", -- ↡ dash = "\226\128\144", -- ‐ dashv = "\226\138\163", -- ⊣ Dashv = "\226\171\164", -- ⫤ dbkarow = "\226\164\143", -- ⤏ dblac = "\203\157", -- ˝ dcaron = "\196\143", -- ď Dcaron = "\196\142", -- Ď dcy = "\208\180", -- д Dcy = "\208\148", -- Д dd = "\226\133\134", -- ⅆ DD = "\226\133\133", -- ⅅ ddagger = "\226\128\161", -- ‡ ddarr = "\226\135\138", -- ⇊ DDotrahd = "\226\164\145", -- ⤑ ddotseq = "\226\169\183", -- ⩷ deg = "\194\176", -- ° Del = "\226\136\135", -- ∇ delta = "\206\180", -- δ Delta = "\206\148", -- Δ demptyv = "\226\166\177", -- ⦱ dfisht = "\226\165\191", -- ⥿ dfr = "\240\157\148\161", -- 𝔡 Dfr = "\240\157\148\135", -- 𝔇 dHar = "\226\165\165", -- ⥥ dharl = "\226\135\131", -- ⇃ dharr = "\226\135\130", -- ⇂ DiacriticalAcute = "\194\180", -- ´ DiacriticalDot = "\203\153", -- ˙ DiacriticalDoubleAcute = "\203\157", -- ˝ DiacriticalGrave = "\96", -- ` DiacriticalTilde = "\203\156", -- ˜ diam = "\226\139\132", -- ⋄ diamond = "\226\139\132", -- ⋄ Diamond = "\226\139\132", -- ⋄ diamondsuit = "\226\153\166", -- ♦ diams = "\226\153\166", -- ♦ die = "\194\168", -- ¨ DifferentialD = "\226\133\134", -- ⅆ digamma = "\207\157", -- ϝ disin = "\226\139\178", -- ⋲ div = "\195\183", -- ÷ divide = "\195\183", -- ÷ divideontimes = "\226\139\135", -- ⋇ divonx = "\226\139\135", -- ⋇ djcy = "\209\146", -- ђ DJcy = "\208\130", -- Ђ dlcorn = "\226\140\158", -- ⌞ dlcrop = "\226\140\141", -- ⌍ dollar = "\36", -- $ dopf = "\240\157\149\149", -- 𝕕 Dopf = "\240\157\148\187", -- 𝔻 dot = "\203\153", -- ˙ Dot = "\194\168", -- ¨ DotDot = "\226\131\156", -- ⃜ doteq = "\226\137\144", -- ≐ doteqdot = "\226\137\145", -- ≑ DotEqual = "\226\137\144", -- ≐ dotminus = "\226\136\184", -- ∸ dotplus = "\226\136\148", -- ∔ dotsquare = "\226\138\161", -- ⊡ doublebarwedge = "\226\140\134", -- ⌆ DoubleContourIntegral = "\226\136\175", -- ∯ DoubleDot = "\194\168", -- ¨ DoubleDownArrow = "\226\135\147", -- ⇓ DoubleLeftArrow = "\226\135\144", -- ⇐ DoubleLeftRightArrow = "\226\135\148", -- ⇔ DoubleLeftTee = "\226\171\164", -- ⫤ DoubleLongLeftArrow = "\226\159\184", -- ⟸ DoubleLongLeftRightArrow = "\226\159\186", -- ⟺ DoubleLongRightArrow = "\226\159\185", -- ⟹ DoubleRightArrow = "\226\135\146", -- ⇒ DoubleRightTee = "\226\138\168", -- ⊨ DoubleUpArrow = "\226\135\145", -- ⇑ DoubleUpDownArrow = "\226\135\149", -- ⇕ DoubleVerticalBar = "\226\136\165", -- ∥ downarrow = "\226\134\147", -- ↓ Downarrow = "\226\135\147", -- ⇓ DownArrow = "\226\134\147", -- ↓ DownArrowBar = "\226\164\147", -- ⤓ DownArrowUpArrow = "\226\135\181", -- ⇵ DownBreve = "\204\145", -- ̑ downdownarrows = "\226\135\138", -- ⇊ downharpoonleft = "\226\135\131", -- ⇃ downharpoonright = "\226\135\130", -- ⇂ DownLeftRightVector = "\226\165\144", -- ⥐ DownLeftTeeVector = "\226\165\158", -- ⥞ DownLeftVector = "\226\134\189", -- ↽ DownLeftVectorBar = "\226\165\150", -- ⥖ DownRightTeeVector = "\226\165\159", -- ⥟ DownRightVector = "\226\135\129", -- ⇁ DownRightVectorBar = "\226\165\151", -- ⥗ DownTee = "\226\138\164", -- ⊤ DownTeeArrow = "\226\134\167", -- ↧ drbkarow = "\226\164\144", -- ⤐ drcorn = "\226\140\159", -- ⌟ drcrop = "\226\140\140", -- ⌌ dscr = "\240\157\146\185", -- 𝒹 Dscr = "\240\157\146\159", -- 𝒟 dscy = "\209\149", -- ѕ DScy = "\208\133", -- Ѕ dsol = "\226\167\182", -- ⧶ dstrok = "\196\145", -- đ Dstrok = "\196\144", -- Đ dtdot = "\226\139\177", -- ⋱ dtri = "\226\150\191", -- ▿ dtrif = "\226\150\190", -- ▾ duarr = "\226\135\181", -- ⇵ duhar = "\226\165\175", -- ⥯ dwangle = "\226\166\166", -- ⦦ dzcy = "\209\159", -- џ DZcy = "\208\143", -- Џ dzigrarr = "\226\159\191", -- ⟿ eacute = "\195\169", -- é Eacute = "\195\137", -- É easter = "\226\169\174", -- ⩮ ecaron = "\196\155", -- ě Ecaron = "\196\154", -- Ě ecir = "\226\137\150", -- ≖ ecirc = "\195\170", -- ê Ecirc = "\195\138", -- Ê ecolon = "\226\137\149", -- ≕ ecy = "\209\141", -- э Ecy = "\208\173", -- Э eDDot = "\226\169\183", -- ⩷ edot = "\196\151", -- ė eDot = "\226\137\145", -- ≑ Edot = "\196\150", -- Ė ee = "\226\133\135", -- ⅇ efDot = "\226\137\146", -- ≒ efr = "\240\157\148\162", -- 𝔢 Efr = "\240\157\148\136", -- 𝔈 eg = "\226\170\154", -- ⪚ egrave = "\195\168", -- è Egrave = "\195\136", -- È egs = "\226\170\150", -- ⪖ egsdot = "\226\170\152", -- ⪘ el = "\226\170\153", -- ⪙ Element = "\226\136\136", -- ∈ elinters = "\226\143\167", -- ⏧ ell = "\226\132\147", -- ℓ els = "\226\170\149", -- ⪕ elsdot = "\226\170\151", -- ⪗ emacr = "\196\147", -- ē Emacr = "\196\146", -- Ē empty = "\226\136\133", -- ∅ emptyset = "\226\136\133", -- ∅ EmptySmallSquare = "\226\151\187", -- ◻ emptyv = "\226\136\133", -- ∅ EmptyVerySmallSquare = "\226\150\171", -- ▫ emsp = "\226\128\131", -- [em space] emsp13 = "\226\128\132", -- [three-per-em space] emsp14 = "\226\128\133", -- [four-per-em space] eng = "\197\139", -- ŋ ENG = "\197\138", -- Ŋ ensp = "\226\128\130", -- [en space] eogon = "\196\153", -- ę Eogon = "\196\152", -- Ę eopf = "\240\157\149\150", -- 𝕖 Eopf = "\240\157\148\188", -- 𝔼 epar = "\226\139\149", -- ⋕ eparsl = "\226\167\163", -- ⧣ eplus = "\226\169\177", -- ⩱ epsi = "\206\181", -- ε epsilon = "\206\181", -- ε Epsilon = "\206\149", -- Ε epsiv = "\207\181", -- ϵ eqcirc = "\226\137\150", -- ≖ eqcolon = "\226\137\149", -- ≕ eqsim = "\226\137\130", -- ≂ eqslantgtr = "\226\170\150", -- ⪖ eqslantless = "\226\170\149", -- ⪕ Equal = "\226\169\181", -- ⩵ equals = "\61", -- = EqualTilde = "\226\137\130", -- ≂ equest = "\226\137\159", -- ≟ Equilibrium = "\226\135\140", -- ⇌ equiv = "\226\137\161", -- ≡ equivDD = "\226\169\184", -- ⩸ eqvparsl = "\226\167\165", -- ⧥ erarr = "\226\165\177", -- ⥱ erDot = "\226\137\147", -- ≓ escr = "\226\132\175", -- ℯ Escr = "\226\132\176", -- ℰ esdot = "\226\137\144", -- ≐ esim = "\226\137\130", -- ≂ Esim = "\226\169\179", -- ⩳ eta = "\206\183", -- η Eta = "\206\151", -- Η eth = "\195\176", -- ð ETH = "\195\144", -- Ð euml = "\195\171", -- ë Euml = "\195\139", -- Ë euro = "\226\130\172", -- € excl = "\33", -- ! exist = "\226\136\131", -- ∃ Exists = "\226\136\131", -- ∃ expectation = "\226\132\176", -- ℰ exponentiale = "\226\133\135", -- ⅇ ExponentialE = "\226\133\135", -- ⅇ fallingdotseq = "\226\137\146", -- ≒ fcy = "\209\132", -- ф Fcy = "\208\164", -- Ф female = "\226\153\128", -- ♀ ffilig = "\239\172\131", -- ffi fflig = "\239\172\128", -- ff ffllig = "\239\172\132", -- ffl ffr = "\240\157\148\163", -- 𝔣 Ffr = "\240\157\148\137", -- 𝔉 filig = "\239\172\129", -- fi FilledSmallSquare = "\226\151\188", -- ◼ FilledVerySmallSquare = "\226\150\170", -- ▪ fjlig = "\102\106", -- fj flat = "\226\153\173", -- ♭ fllig = "\239\172\130", -- fl fltns = "\226\150\177", -- ▱ fnof = "\198\146", -- ƒ fopf = "\240\157\149\151", -- 𝕗 Fopf = "\240\157\148\189", -- 𝔽 forall = "\226\136\128", -- ∀ ForAll = "\226\136\128", -- ∀ fork = "\226\139\148", -- ⋔ forkv = "\226\171\153", -- ⫙ Fouriertrf = "\226\132\177", -- ℱ fpartint = "\226\168\141", -- ⨍ frac12 = "\194\189", -- ½ frac13 = "\226\133\147", -- ⅓ frac14 = "\194\188", -- ¼ frac15 = "\226\133\149", -- ⅕ frac16 = "\226\133\153", -- ⅙ frac18 = "\226\133\155", -- ⅛ frac23 = "\226\133\148", -- ⅔ frac25 = "\226\133\150", -- ⅖ frac34 = "\194\190", -- ¾ frac35 = "\226\133\151", -- ⅗ frac38 = "\226\133\156", -- ⅜ frac45 = "\226\133\152", -- ⅘ frac56 = "\226\133\154", -- ⅚ frac58 = "\226\133\157", -- ⅝ frac78 = "\226\133\158", -- ⅞ frasl = "\226\129\132", -- ⁄ frown = "\226\140\162", -- ⌢ fscr = "\240\157\146\187", -- 𝒻 Fscr = "\226\132\177", -- ℱ gacute = "\199\181", -- ǵ gamma = "\206\179", -- γ Gamma = "\206\147", -- Γ gammad = "\207\157", -- ϝ Gammad = "\207\156", -- Ϝ gap = "\226\170\134", -- ⪆ gbreve = "\196\159", -- ğ Gbreve = "\196\158", -- Ğ Gcedil = "\196\162", -- Ģ gcirc = "\196\157", -- ĝ Gcirc = "\196\156", -- Ĝ gcy = "\208\179", -- г Gcy = "\208\147", -- Г gdot = "\196\161", -- ġ Gdot = "\196\160", -- Ġ ge = "\226\137\165", -- ≥ gE = "\226\137\167", -- ≧ gel = "\226\139\155", -- ⋛ gEl = "\226\170\140", -- ⪌ geq = "\226\137\165", -- ≥ geqq = "\226\137\167", -- ≧ geqslant = "\226\169\190", -- ⩾ ges = "\226\169\190", -- ⩾ gescc = "\226\170\169", -- ⪩ gesdot = "\226\170\128", -- ⪀ gesdoto = "\226\170\130", -- ⪂ gesdotol = "\226\170\132", -- ⪄ gesl = "\226\139\155\239\184\128", -- ⋛︀ gesles = "\226\170\148", -- ⪔ gfr = "\240\157\148\164", -- 𝔤 Gfr = "\240\157\148\138", -- 𝔊 gg = "\226\137\171", -- ≫ Gg = "\226\139\153", -- ⋙ ggg = "\226\139\153", -- ⋙ gimel = "\226\132\183", -- ℷ gjcy = "\209\147", -- ѓ GJcy = "\208\131", -- Ѓ gl = "\226\137\183", -- ≷ gla = "\226\170\165", -- ⪥ glE = "\226\170\146", -- ⪒ glj = "\226\170\164", -- ⪤ gnap = "\226\170\138", -- ⪊ gnapprox = "\226\170\138", -- ⪊ gne = "\226\170\136", -- ⪈ gnE = "\226\137\169", -- ≩ gneq = "\226\170\136", -- ⪈ gneqq = "\226\137\169", -- ≩ gnsim = "\226\139\167", -- ⋧ gopf = "\240\157\149\152", -- 𝕘 Gopf = "\240\157\148\190", -- 𝔾 grave = "\96", -- ` GreaterEqual = "\226\137\165", -- ≥ GreaterEqualLess = "\226\139\155", -- ⋛ GreaterFullEqual = "\226\137\167", -- ≧ GreaterGreater = "\226\170\162", -- ⪢ GreaterLess = "\226\137\183", -- ≷ GreaterSlantEqual = "\226\169\190", -- ⩾ GreaterTilde = "\226\137\179", -- ≳ gscr = "\226\132\138", -- ℊ Gscr = "\240\157\146\162", -- 𝒢 gsim = "\226\137\179", -- ≳ gsime = "\226\170\142", -- ⪎ gsiml = "\226\170\144", -- ⪐ gt = "\62", -- > Gt = "\226\137\171", -- ≫ GT = "\62", -- > gtcc = "\226\170\167", -- ⪧ gtcir = "\226\169\186", -- ⩺ gtdot = "\226\139\151", -- ⋗ gtlPar = "\226\166\149", -- ⦕ gtquest = "\226\169\188", -- ⩼ gtrapprox = "\226\170\134", -- ⪆ gtrarr = "\226\165\184", -- ⥸ gtrdot = "\226\139\151", -- ⋗ gtreqless = "\226\139\155", -- ⋛ gtreqqless = "\226\170\140", -- ⪌ gtrless = "\226\137\183", -- ≷ gtrsim = "\226\137\179", -- ≳ gvertneqq = "\226\137\169\239\184\128", -- ≩︀ gvnE = "\226\137\169\239\184\128", -- ≩︀ Hacek = "\203\135", -- ˇ hairsp = "\226\128\138", -- [hair space] half = "\194\189", -- ½ hamilt = "\226\132\139", -- ℋ hardcy = "\209\138", -- ъ HARDcy = "\208\170", -- Ъ harr = "\226\134\148", -- ↔ hArr = "\226\135\148", -- ⇔ harrcir = "\226\165\136", -- ⥈ harrw = "\226\134\173", -- ↭ Hat = "\94", -- ^ hbar = "\226\132\143", -- ℏ hcirc = "\196\165", -- ĥ Hcirc = "\196\164", -- Ĥ hearts = "\226\153\165", -- ♥ heartsuit = "\226\153\165", -- ♥ hellip = "\226\128\166", -- … hercon = "\226\138\185", -- ⊹ hfr = "\240\157\148\165", -- 𝔥 Hfr = "\226\132\140", -- ℌ HilbertSpace = "\226\132\139", -- ℋ hksearow = "\226\164\165", -- ⤥ hkswarow = "\226\164\166", -- ⤦ hoarr = "\226\135\191", -- ⇿ homtht = "\226\136\187", -- ∻ hookleftarrow = "\226\134\169", -- ↩ hookrightarrow = "\226\134\170", -- ↪ hopf = "\240\157\149\153", -- 𝕙 Hopf = "\226\132\141", -- ℍ horbar = "\226\128\149", -- ― HorizontalLine = "\226\148\128", -- ─ hscr = "\240\157\146\189", -- 𝒽 Hscr = "\226\132\139", -- ℋ hslash = "\226\132\143", -- ℏ hstrok = "\196\167", -- ħ Hstrok = "\196\166", -- Ħ HumpDownHump = "\226\137\142", -- ≎ HumpEqual = "\226\137\143", -- ≏ hybull = "\226\129\131", -- ⁃ hyphen = "\226\128\144", -- ‐ iacute = "\195\173", -- í Iacute = "\195\141", -- Í ic = "\226\129\163", -- [invisible separator] icirc = "\195\174", -- î Icirc = "\195\142", -- Î icy = "\208\184", -- и Icy = "\208\152", -- И Idot = "\196\176", -- İ iecy = "\208\181", -- е IEcy = "\208\149", -- Е iexcl = "\194\161", -- ¡ iff = "\226\135\148", -- ⇔ ifr = "\240\157\148\166", -- 𝔦 Ifr = "\226\132\145", -- ℑ igrave = "\195\172", -- ì Igrave = "\195\140", -- Ì ii = "\226\133\136", -- ⅈ iiiint = "\226\168\140", -- ⨌ iiint = "\226\136\173", -- ∭ iinfin = "\226\167\156", -- ⧜ iiota = "\226\132\169", -- ℩ ijlig = "\196\179", -- ij IJlig = "\196\178", -- IJ Im = "\226\132\145", -- ℑ imacr = "\196\171", -- ī Imacr = "\196\170", -- Ī image = "\226\132\145", -- ℑ ImaginaryI = "\226\133\136", -- ⅈ imagline = "\226\132\144", -- ℐ imagpart = "\226\132\145", -- ℑ imath = "\196\177", -- ı imof = "\226\138\183", -- ⊷ imped = "\198\181", -- Ƶ Implies = "\226\135\146", -- ⇒ ["in"] = "\226\136\136", -- ∈ incare = "\226\132\133", -- ℅ infin = "\226\136\158", -- ∞ infintie = "\226\167\157", -- ⧝ inodot = "\196\177", -- ı int = "\226\136\171", -- ∫ Int = "\226\136\172", -- ∬ intcal = "\226\138\186", -- ⊺ integers = "\226\132\164", -- ℤ Integral = "\226\136\171", -- ∫ intercal = "\226\138\186", -- ⊺ Intersection = "\226\139\130", -- ⋂ intlarhk = "\226\168\151", -- ⨗ intprod = "\226\168\188", -- ⨼ InvisibleComma = "\226\129\163", -- [invisible separator] InvisibleTimes = "\226\129\162", -- [invisible times] iocy = "\209\145", -- ё IOcy = "\208\129", -- Ё iogon = "\196\175", -- į Iogon = "\196\174", -- Į iopf = "\240\157\149\154", -- 𝕚 Iopf = "\240\157\149\128", -- 𝕀 iota = "\206\185", -- ι Iota = "\206\153", -- Ι iprod = "\226\168\188", -- ⨼ iquest = "\194\191", -- ¿ iscr = "\240\157\146\190", -- 𝒾 Iscr = "\226\132\144", -- ℐ isin = "\226\136\136", -- ∈ isindot = "\226\139\181", -- ⋵ isinE = "\226\139\185", -- ⋹ isins = "\226\139\180", -- ⋴ isinsv = "\226\139\179", -- ⋳ isinv = "\226\136\136", -- ∈ it = "\226\129\162", -- [invisible times] itilde = "\196\169", -- ĩ Itilde = "\196\168", -- Ĩ iukcy = "\209\150", -- і Iukcy = "\208\134", -- І iuml = "\195\175", -- ï Iuml = "\195\143", -- Ï jcirc = "\196\181", -- ĵ Jcirc = "\196\180", -- Ĵ jcy = "\208\185", -- й Jcy = "\208\153", -- Й jfr = "\240\157\148\167", -- 𝔧 Jfr = "\240\157\148\141", -- 𝔍 jmath = "\200\183", -- ȷ jopf = "\240\157\149\155", -- 𝕛 Jopf = "\240\157\149\129", -- 𝕁 jscr = "\240\157\146\191", -- 𝒿 Jscr = "\240\157\146\165", -- 𝒥 jsercy = "\209\152", -- ј Jsercy = "\208\136", -- Ј jukcy = "\209\148", -- є Jukcy = "\208\132", -- Є kappa = "\206\186", -- κ Kappa = "\206\154", -- Κ kappav = "\207\176", -- ϰ kcedil = "\196\183", -- ķ Kcedil = "\196\182", -- Ķ kcy = "\208\186", -- к Kcy = "\208\154", -- К kfr = "\240\157\148\168", -- 𝔨 Kfr = "\240\157\148\142", -- 𝔎 kgreen = "\196\184", -- ĸ khcy = "\209\133", -- х KHcy = "\208\165", -- Х kjcy = "\209\156", -- ќ KJcy = "\208\140", -- Ќ kopf = "\240\157\149\156", -- 𝕜 Kopf = "\240\157\149\130", -- 𝕂 kscr = "\240\157\147\128", -- 𝓀 Kscr = "\240\157\146\166", -- 𝒦 lAarr = "\226\135\154", -- ⇚ lacute = "\196\186", -- ĺ Lacute = "\196\185", -- Ĺ laemptyv = "\226\166\180", -- ⦴ lagran = "\226\132\146", -- ℒ lambda = "\206\187", -- λ Lambda = "\206\155", -- Λ lang = "\226\159\168", -- ⟨ Lang = "\226\159\170", -- ⟪ langd = "\226\166\145", -- ⦑ langle = "\226\159\168", -- ⟨ lap = "\226\170\133", -- ⪅ Laplacetrf = "\226\132\146", -- ℒ laquo = "\194\171", -- « larr = "\226\134\144", -- ← lArr = "\226\135\144", -- ⇐ Larr = "\226\134\158", -- ↞ larrb = "\226\135\164", -- ⇤ larrbfs = "\226\164\159", -- ⤟ larrfs = "\226\164\157", -- ⤝ larrhk = "\226\134\169", -- ↩ larrlp = "\226\134\171", -- ↫ larrpl = "\226\164\185", -- ⤹ larrsim = "\226\165\179", -- ⥳ larrtl = "\226\134\162", -- ↢ lat = "\226\170\171", -- ⪫ latail = "\226\164\153", -- ⤙ lAtail = "\226\164\155", -- ⤛ late = "\226\170\173", -- ⪭ lates = "\226\170\173\239\184\128", -- ⪭︀ lbarr = "\226\164\140", -- ⤌ lBarr = "\226\164\142", -- ⤎ lbbrk = "\226\157\178", -- ❲ lbrace = "\123", -- { lbrack = "\91", -- [ lbrke = "\226\166\139", -- ⦋ lbrksld = "\226\166\143", -- ⦏ lbrkslu = "\226\166\141", -- ⦍ lcaron = "\196\190", -- ľ Lcaron = "\196\189", -- Ľ lcedil = "\196\188", -- ļ Lcedil = "\196\187", -- Ļ lceil = "\226\140\136", -- ⌈ lcub = "\123", -- { lcy = "\208\187", -- л Lcy = "\208\155", -- Л ldca = "\226\164\182", -- ⤶ ldquo = "\226\128\156", -- “ ldquor = "\226\128\158", -- „ ldrdhar = "\226\165\167", -- ⥧ ldrushar = "\226\165\139", -- ⥋ ldsh = "\226\134\178", -- ↲ le = "\226\137\164", -- ≤ lE = "\226\137\166", -- ≦ LeftAngleBracket = "\226\159\168", -- ⟨ leftarrow = "\226\134\144", -- ← Leftarrow = "\226\135\144", -- ⇐ LeftArrow = "\226\134\144", -- ← LeftArrowBar = "\226\135\164", -- ⇤ LeftArrowRightArrow = "\226\135\134", -- ⇆ leftarrowtail = "\226\134\162", -- ↢ LeftCeiling = "\226\140\136", -- ⌈ LeftDoubleBracket = "\226\159\166", -- ⟦ LeftDownTeeVector = "\226\165\161", -- ⥡ LeftDownVector = "\226\135\131", -- ⇃ LeftDownVectorBar = "\226\165\153", -- ⥙ LeftFloor = "\226\140\138", -- ⌊ leftharpoondown = "\226\134\189", -- ↽ leftharpoonup = "\226\134\188", -- ↼ leftleftarrows = "\226\135\135", -- ⇇ leftrightarrow = "\226\134\148", -- ↔ Leftrightarrow = "\226\135\148", -- ⇔ LeftRightArrow = "\226\134\148", -- ↔ leftrightarrows = "\226\135\134", -- ⇆ leftrightharpoons = "\226\135\139", -- ⇋ leftrightsquigarrow = "\226\134\173", -- ↭ LeftRightVector = "\226\165\142", -- ⥎ LeftTee = "\226\138\163", -- ⊣ LeftTeeArrow = "\226\134\164", -- ↤ LeftTeeVector = "\226\165\154", -- ⥚ leftthreetimes = "\226\139\139", -- ⋋ LeftTriangle = "\226\138\178", -- ⊲ LeftTriangleBar = "\226\167\143", -- ⧏ LeftTriangleEqual = "\226\138\180", -- ⊴ LeftUpDownVector = "\226\165\145", -- ⥑ LeftUpTeeVector = "\226\165\160", -- ⥠ LeftUpVector = "\226\134\191", -- ↿ LeftUpVectorBar = "\226\165\152", -- ⥘ LeftVector = "\226\134\188", -- ↼ LeftVectorBar = "\226\165\146", -- ⥒ leg = "\226\139\154", -- ⋚ lEg = "\226\170\139", -- ⪋ leq = "\226\137\164", -- ≤ leqq = "\226\137\166", -- ≦ leqslant = "\226\169\189", -- ⩽ les = "\226\169\189", -- ⩽ lescc = "\226\170\168", -- ⪨ lesdot = "\226\169\191", -- ⩿ lesdoto = "\226\170\129", -- ⪁ lesdotor = "\226\170\131", -- ⪃ lesg = "\226\139\154\239\184\128", -- ⋚︀ lesges = "\226\170\147", -- ⪓ lessapprox = "\226\170\133", -- ⪅ lessdot = "\226\139\150", -- ⋖ lesseqgtr = "\226\139\154", -- ⋚ lesseqqgtr = "\226\170\139", -- ⪋ LessEqualGreater = "\226\139\154", -- ⋚ LessFullEqual = "\226\137\166", -- ≦ LessGreater = "\226\137\182", -- ≶ lessgtr = "\226\137\182", -- ≶ LessLess = "\226\170\161", -- ⪡ lesssim = "\226\137\178", -- ≲ LessSlantEqual = "\226\169\189", -- ⩽ LessTilde = "\226\137\178", -- ≲ lfisht = "\226\165\188", -- ⥼ lfloor = "\226\140\138", -- ⌊ lfr = "\240\157\148\169", -- 𝔩 Lfr = "\240\157\148\143", -- 𝔏 lg = "\226\137\182", -- ≶ lgE = "\226\170\145", -- ⪑ lHar = "\226\165\162", -- ⥢ lhard = "\226\134\189", -- ↽ lharu = "\226\134\188", -- ↼ lharul = "\226\165\170", -- ⥪ lhblk = "\226\150\132", -- ▄ ljcy = "\209\153", -- љ LJcy = "\208\137", -- Љ ll = "\226\137\170", -- ≪ Ll = "\226\139\152", -- ⋘ llarr = "\226\135\135", -- ⇇ llcorner = "\226\140\158", -- ⌞ Lleftarrow = "\226\135\154", -- ⇚ llhard = "\226\165\171", -- ⥫ lltri = "\226\151\186", -- ◺ lmidot = "\197\128", -- ŀ Lmidot = "\196\191", -- Ŀ lmoust = "\226\142\176", -- ⎰ lmoustache = "\226\142\176", -- ⎰ lnap = "\226\170\137", -- ⪉ lnapprox = "\226\170\137", -- ⪉ lne = "\226\170\135", -- ⪇ lnE = "\226\137\168", -- ≨ lneq = "\226\170\135", -- ⪇ lneqq = "\226\137\168", -- ≨ lnsim = "\226\139\166", -- ⋦ loang = "\226\159\172", -- ⟬ loarr = "\226\135\189", -- ⇽ lobrk = "\226\159\166", -- ⟦ longleftarrow = "\226\159\181", -- ⟵ Longleftarrow = "\226\159\184", -- ⟸ LongLeftArrow = "\226\159\181", -- ⟵ longleftrightarrow = "\226\159\183", -- ⟷ Longleftrightarrow = "\226\159\186", -- ⟺ LongLeftRightArrow = "\226\159\183", -- ⟷ longmapsto = "\226\159\188", -- ⟼ longrightarrow = "\226\159\182", -- ⟶ Longrightarrow = "\226\159\185", -- ⟹ LongRightArrow = "\226\159\182", -- ⟶ looparrowleft = "\226\134\171", -- ↫ looparrowright = "\226\134\172", -- ↬ lopar = "\226\166\133", -- ⦅ lopf = "\240\157\149\157", -- 𝕝 Lopf = "\240\157\149\131", -- 𝕃 loplus = "\226\168\173", -- ⨭ lotimes = "\226\168\180", -- ⨴ lowast = "\226\136\151", -- ∗ lowbar = "\95", -- _ LowerLeftArrow = "\226\134\153", -- ↙ LowerRightArrow = "\226\134\152", -- ↘ loz = "\226\151\138", -- ◊ lozenge = "\226\151\138", -- ◊ lozf = "\226\167\171", -- ⧫ lpar = "\40", -- ( lparlt = "\226\166\147", -- ⦓ lrarr = "\226\135\134", -- ⇆ lrcorner = "\226\140\159", -- ⌟ lrhar = "\226\135\139", -- ⇋ lrhard = "\226\165\173", -- ⥭ lrm = "\226\128\142", -- [left-to-right mark] lrtri = "\226\138\191", -- ⊿ lsaquo = "\226\128\185", -- ‹ lscr = "\240\157\147\129", -- 𝓁 Lscr = "\226\132\146", -- ℒ lsh = "\226\134\176", -- ↰ Lsh = "\226\134\176", -- ↰ lsim = "\226\137\178", -- ≲ lsime = "\226\170\141", -- ⪍ lsimg = "\226\170\143", -- ⪏ lsqb = "\91", -- [ lsquo = "\226\128\152", -- ‘ lsquor = "\226\128\154", -- ‚ lstrok = "\197\130", -- ł Lstrok = "\197\129", -- Ł lt = "\60", -- < Lt = "\226\137\170", -- ≪ LT = "\60", -- < ltcc = "\226\170\166", -- ⪦ ltcir = "\226\169\185", -- ⩹ ltdot = "\226\139\150", -- ⋖ lthree = "\226\139\139", -- ⋋ ltimes = "\226\139\137", -- ⋉ ltlarr = "\226\165\182", -- ⥶ ltquest = "\226\169\187", -- ⩻ ltri = "\226\151\131", -- ◃ ltrie = "\226\138\180", -- ⊴ ltrif = "\226\151\130", -- ◂ ltrPar = "\226\166\150", -- ⦖ lurdshar = "\226\165\138", -- ⥊ luruhar = "\226\165\166", -- ⥦ lvertneqq = "\226\137\168\239\184\128", -- ≨︀ lvnE = "\226\137\168\239\184\128", -- ≨︀ macr = "\194\175", -- ¯ male = "\226\153\130", -- ♂ malt = "\226\156\160", -- ✠ maltese = "\226\156\160", -- ✠ map = "\226\134\166", -- ↦ Map = "\226\164\133", -- ⤅ mapsto = "\226\134\166", -- ↦ mapstodown = "\226\134\167", -- ↧ mapstoleft = "\226\134\164", -- ↤ mapstoup = "\226\134\165", -- ↥ marker = "\226\150\174", -- ▮ mcomma = "\226\168\169", -- ⨩ mcy = "\208\188", -- м Mcy = "\208\156", -- М mdash = "\226\128\148", -- — mDDot = "\226\136\186", -- ∺ measuredangle = "\226\136\161", -- ∡ MediumSpace = "\226\129\159", -- [medium mathematical space] Mellintrf = "\226\132\179", -- ℳ mfr = "\240\157\148\170", -- 𝔪 Mfr = "\240\157\148\144", -- 𝔐 mho = "\226\132\167", -- ℧ micro = "\194\181", -- µ mid = "\226\136\163", -- ∣ midast = "\42", -- * midcir = "\226\171\176", -- ⫰ middot = "\194\183", -- · minus = "\226\136\146", -- − minusb = "\226\138\159", -- ⊟ minusd = "\226\136\184", -- ∸ minusdu = "\226\168\170", -- ⨪ MinusPlus = "\226\136\147", -- ∓ mlcp = "\226\171\155", -- ⫛ mldr = "\226\128\166", -- … mnplus = "\226\136\147", -- ∓ models = "\226\138\167", -- ⊧ mopf = "\240\157\149\158", -- 𝕞 Mopf = "\240\157\149\132", -- 𝕄 mp = "\226\136\147", -- ∓ mscr = "\240\157\147\130", -- 𝓂 Mscr = "\226\132\179", -- ℳ mstpos = "\226\136\190", -- ∾ mu = "\206\188", -- μ Mu = "\206\156", -- Μ multimap = "\226\138\184", -- ⊸ mumap = "\226\138\184", -- ⊸ nabla = "\226\136\135", -- ∇ nacute = "\197\132", -- ń Nacute = "\197\131", -- Ń nang = "\226\136\160\226\131\146", -- ∠⃒ nap = "\226\137\137", -- ≉ napE = "\226\169\176\204\184", -- ⩰̸ napid = "\226\137\139\204\184", -- ≋̸ napos = "\197\137", -- ʼn napprox = "\226\137\137", -- ≉ natur = "\226\153\174", -- ♮ natural = "\226\153\174", -- ♮ naturals = "\226\132\149", -- ℕ nbsp = "\194\160", -- [no-break space] nbump = "\226\137\142\204\184", -- ≎̸ nbumpe = "\226\137\143\204\184", -- ≏̸ ncap = "\226\169\131", -- ⩃ ncaron = "\197\136", -- ň Ncaron = "\197\135", -- Ň ncedil = "\197\134", -- ņ Ncedil = "\197\133", -- Ņ ncong = "\226\137\135", -- ≇ ncongdot = "\226\169\173\204\184", -- ⩭̸ ncup = "\226\169\130", -- ⩂ ncy = "\208\189", -- н Ncy = "\208\157", -- Н ndash = "\226\128\147", -- – ne = "\226\137\160", -- ≠ nearhk = "\226\164\164", -- ⤤ nearr = "\226\134\151", -- ↗ neArr = "\226\135\151", -- ⇗ nearrow = "\226\134\151", -- ↗ nedot = "\226\137\144\204\184", -- ≐̸ NegativeMediumSpace = "\226\128\139", -- [zero width space] NegativeThickSpace = "\226\128\139", -- [zero width space] NegativeThinSpace = "\226\128\139", -- [zero width space] NegativeVeryThinSpace = "\226\128\139", -- [zero width space] nequiv = "\226\137\162", -- ≢ nesear = "\226\164\168", -- ⤨ nesim = "\226\137\130\204\184", -- ≂̸ NestedGreaterGreater = "\226\137\171", -- ≫ NestedLessLess = "\226\137\170", -- ≪ NewLine = "\n", -- [new line] nexist = "\226\136\132", -- ∄ nexists = "\226\136\132", -- ∄ nfr = "\240\157\148\171", -- 𝔫 Nfr = "\240\157\148\145", -- 𝔑 nge = "\226\137\177", -- ≱ ngE = "\226\137\167\204\184", -- ≧̸ ngeq = "\226\137\177", -- ≱ ngeqq = "\226\137\167\204\184", -- ≧̸ ngeqslant = "\226\169\190\204\184", -- ⩾̸ nges = "\226\169\190\204\184", -- ⩾̸ nGg = "\226\139\153\204\184", -- ⋙̸ ngsim = "\226\137\181", -- ≵ ngt = "\226\137\175", -- ≯ nGt = "\226\137\171\226\131\146", -- ≫⃒ ngtr = "\226\137\175", -- ≯ nGtv = "\226\137\171\204\184", -- ≫̸ nharr = "\226\134\174", -- ↮ nhArr = "\226\135\142", -- ⇎ nhpar = "\226\171\178", -- ⫲ ni = "\226\136\139", -- ∋ nis = "\226\139\188", -- ⋼ nisd = "\226\139\186", -- ⋺ niv = "\226\136\139", -- ∋ njcy = "\209\154", -- њ NJcy = "\208\138", -- Њ nlarr = "\226\134\154", -- ↚ nlArr = "\226\135\141", -- ⇍ nldr = "\226\128\165", -- ‥ nle = "\226\137\176", -- ≰ nlE = "\226\137\166\204\184", -- ≦̸ nleftarrow = "\226\134\154", -- ↚ nLeftarrow = "\226\135\141", -- ⇍ nleftrightarrow = "\226\134\174", -- ↮ nLeftrightarrow = "\226\135\142", -- ⇎ nleq = "\226\137\176", -- ≰ nleqq = "\226\137\166\204\184", -- ≦̸ nleqslant = "\226\169\189\204\184", -- ⩽̸ nles = "\226\169\189\204\184", -- ⩽̸ nless = "\226\137\174", -- ≮ nLl = "\226\139\152\204\184", -- ⋘̸ nlsim = "\226\137\180", -- ≴ nlt = "\226\137\174", -- ≮ nLt = "\226\137\170\226\131\146", -- ≪⃒ nltri = "\226\139\170", -- ⋪ nltrie = "\226\139\172", -- ⋬ nLtv = "\226\137\170\204\184", -- ≪̸ nmid = "\226\136\164", -- ∤ NoBreak = "\226\129\160", -- [word joiner] NonBreakingSpace = "\194\160", -- [no-break space] nopf = "\240\157\149\159", -- 𝕟 Nopf = "\226\132\149", -- ℕ ["not"] = "\194\172", -- ¬ Not = "\226\171\172", -- ⫬ NotCongruent = "\226\137\162", -- ≢ NotCupCap = "\226\137\173", -- ≭ NotDoubleVerticalBar = "\226\136\166", -- ∦ NotElement = "\226\136\137", -- ∉ NotEqual = "\226\137\160", -- ≠ NotEqualTilde = "\226\137\130\204\184", -- ≂̸ NotExists = "\226\136\132", -- ∄ NotGreater = "\226\137\175", -- ≯ NotGreaterEqual = "\226\137\177", -- ≱ NotGreaterFullEqual = "\226\137\167\204\184", -- ≧̸ NotGreaterGreater = "\226\137\171\204\184", -- ≫̸ NotGreaterLess = "\226\137\185", -- ≹ NotGreaterSlantEqual = "\226\169\190\204\184", -- ⩾̸ NotGreaterTilde = "\226\137\181", -- ≵ NotHumpDownHump = "\226\137\142\204\184", -- ≎̸ NotHumpEqual = "\226\137\143\204\184", -- ≏̸ notin = "\226\136\137", -- ∉ notindot = "\226\139\181\204\184", -- ⋵̸ notinE = "\226\139\185\204\184", -- ⋹̸ notinva = "\226\136\137", -- ∉ notinvb = "\226\139\183", -- ⋷ notinvc = "\226\139\182", -- ⋶ NotLeftTriangle = "\226\139\170", -- ⋪ NotLeftTriangleBar = "\226\167\143\204\184", -- ⧏̸ NotLeftTriangleEqual = "\226\139\172", -- ⋬ NotLess = "\226\137\174", -- ≮ NotLessEqual = "\226\137\176", -- ≰ NotLessGreater = "\226\137\184", -- ≸ NotLessLess = "\226\137\170\204\184", -- ≪̸ NotLessSlantEqual = "\226\169\189\204\184", -- ⩽̸ NotLessTilde = "\226\137\180", -- ≴ NotNestedGreaterGreater = "\226\170\162\204\184", -- ⪢̸ NotNestedLessLess = "\226\170\161\204\184", -- ⪡̸ notni = "\226\136\140", -- ∌ notniva = "\226\136\140", -- ∌ notnivb = "\226\139\190", -- ⋾ notnivc = "\226\139\189", -- ⋽ NotPrecedes = "\226\138\128", -- ⊀ NotPrecedesEqual = "\226\170\175\204\184", -- ⪯̸ NotPrecedesSlantEqual = "\226\139\160", -- ⋠ NotReverseElement = "\226\136\140", -- ∌ NotRightTriangle = "\226\139\171", -- ⋫ NotRightTriangleBar = "\226\167\144\204\184", -- ⧐̸ NotRightTriangleEqual = "\226\139\173", -- ⋭ NotSquareSubset = "\226\138\143\204\184", -- ⊏̸ NotSquareSubsetEqual = "\226\139\162", -- ⋢ NotSquareSuperset = "\226\138\144\204\184", -- ⊐̸ NotSquareSupersetEqual = "\226\139\163", -- ⋣ NotSubset = "\226\138\130\226\131\146", -- ⊂⃒ NotSubsetEqual = "\226\138\136", -- ⊈ NotSucceeds = "\226\138\129", -- ⊁ NotSucceedsEqual = "\226\170\176\204\184", -- ⪰̸ NotSucceedsSlantEqual = "\226\139\161", -- ⋡ NotSucceedsTilde = "\226\137\191\204\184", -- ≿̸ NotSuperset = "\226\138\131\226\131\146", -- ⊃⃒ NotSupersetEqual = "\226\138\137", -- ⊉ NotTilde = "\226\137\129", -- ≁ NotTildeEqual = "\226\137\132", -- ≄ NotTildeFullEqual = "\226\137\135", -- ≇ NotTildeTilde = "\226\137\137", -- ≉ NotVerticalBar = "\226\136\164", -- ∤ npar = "\226\136\166", -- ∦ nparallel = "\226\136\166", -- ∦ nparsl = "\226\171\189\226\131\165", -- ⫽⃥ npart = "\226\136\130\204\184", -- ∂̸ npolint = "\226\168\148", -- ⨔ npr = "\226\138\128", -- ⊀ nprcue = "\226\139\160", -- ⋠ npre = "\226\170\175\204\184", -- ⪯̸ nprec = "\226\138\128", -- ⊀ npreceq = "\226\170\175\204\184", -- ⪯̸ nrarr = "\226\134\155", -- ↛ nrArr = "\226\135\143", -- ⇏ nrarrc = "\226\164\179\204\184", -- ⤳̸ nrarrw = "\226\134\157\204\184", -- ↝̸ nrightarrow = "\226\134\155", -- ↛ nRightarrow = "\226\135\143", -- ⇏ nrtri = "\226\139\171", -- ⋫ nrtrie = "\226\139\173", -- ⋭ nsc = "\226\138\129", -- ⊁ nsccue = "\226\139\161", -- ⋡ nsce = "\226\170\176\204\184", -- ⪰̸ nscr = "\240\157\147\131", -- 𝓃 Nscr = "\240\157\146\169", -- 𝒩 nshortmid = "\226\136\164", -- ∤ nshortparallel = "\226\136\166", -- ∦ nsim = "\226\137\129", -- ≁ nsime = "\226\137\132", -- ≄ nsimeq = "\226\137\132", -- ≄ nsmid = "\226\136\164", -- ∤ nspar = "\226\136\166", -- ∦ nsqsube = "\226\139\162", -- ⋢ nsqsupe = "\226\139\163", -- ⋣ nsub = "\226\138\132", -- ⊄ nsube = "\226\138\136", -- ⊈ nsubE = "\226\171\133\204\184", -- ⫅̸ nsubset = "\226\138\130\226\131\146", -- ⊂⃒ nsubseteq = "\226\138\136", -- ⊈ nsubseteqq = "\226\171\133\204\184", -- ⫅̸ nsucc = "\226\138\129", -- ⊁ nsucceq = "\226\170\176\204\184", -- ⪰̸ nsup = "\226\138\133", -- ⊅ nsupe = "\226\138\137", -- ⊉ nsupE = "\226\171\134\204\184", -- ⫆̸ nsupset = "\226\138\131\226\131\146", -- ⊃⃒ nsupseteq = "\226\138\137", -- ⊉ nsupseteqq = "\226\171\134\204\184", -- ⫆̸ ntgl = "\226\137\185", -- ≹ ntilde = "\195\177", -- ñ Ntilde = "\195\145", -- Ñ ntlg = "\226\137\184", -- ≸ ntriangleleft = "\226\139\170", -- ⋪ ntrianglelefteq = "\226\139\172", -- ⋬ ntriangleright = "\226\139\171", -- ⋫ ntrianglerighteq = "\226\139\173", -- ⋭ nu = "\206\189", -- ν Nu = "\206\157", -- Ν num = "\35", -- # numero = "\226\132\150", -- № numsp = "\226\128\135", -- [figure space] nvap = "\226\137\141\226\131\146", -- ≍⃒ nvdash = "\226\138\172", -- ⊬ nvDash = "\226\138\173", -- ⊭ nVdash = "\226\138\174", -- ⊮ nVDash = "\226\138\175", -- ⊯ nvge = "\226\137\165\226\131\146", -- ≥⃒ nvgt = "\62\226\131\146", -- >⃒ nvHarr = "\226\164\132", -- ⤄ nvinfin = "\226\167\158", -- ⧞ nvlArr = "\226\164\130", -- ⤂ nvle = "\226\137\164\226\131\146", -- ≤⃒ nvlt = "\60\226\131\146", -- <⃒ nvltrie = "\226\138\180\226\131\146", -- ⊴⃒ nvrArr = "\226\164\131", -- ⤃ nvrtrie = "\226\138\181\226\131\146", -- ⊵⃒ nvsim = "\226\136\188\226\131\146", -- ∼⃒ nwarhk = "\226\164\163", -- ⤣ nwarr = "\226\134\150", -- ↖ nwArr = "\226\135\150", -- ⇖ nwarrow = "\226\134\150", -- ↖ nwnear = "\226\164\167", -- ⤧ oacute = "\195\179", -- ó Oacute = "\195\147", -- Ó oast = "\226\138\155", -- ⊛ ocir = "\226\138\154", -- ⊚ ocirc = "\195\180", -- ô Ocirc = "\195\148", -- Ô ocy = "\208\190", -- о Ocy = "\208\158", -- О odash = "\226\138\157", -- ⊝ odblac = "\197\145", -- ő Odblac = "\197\144", -- Ő odiv = "\226\168\184", -- ⨸ odot = "\226\138\153", -- ⊙ odsold = "\226\166\188", -- ⦼ oelig = "\197\147", -- œ OElig = "\197\146", -- Œ ofcir = "\226\166\191", -- ⦿ ofr = "\240\157\148\172", -- 𝔬 Ofr = "\240\157\148\146", -- 𝔒 ogon = "\203\155", -- ˛ ograve = "\195\178", -- ò Ograve = "\195\146", -- Ò ogt = "\226\167\129", -- ⧁ ohbar = "\226\166\181", -- ⦵ ohm = "\206\169", -- Ω oint = "\226\136\174", -- ∮ olarr = "\226\134\186", -- ↺ olcir = "\226\166\190", -- ⦾ olcross = "\226\166\187", -- ⦻ oline = "\226\128\190", -- ‾ olt = "\226\167\128", -- ⧀ omacr = "\197\141", -- ō Omacr = "\197\140", -- Ō omega = "\207\137", -- ω Omega = "\206\169", -- Ω omicron = "\206\191", -- ο Omicron = "\206\159", -- Ο omid = "\226\166\182", -- ⦶ ominus = "\226\138\150", -- ⊖ oopf = "\240\157\149\160", -- 𝕠 Oopf = "\240\157\149\134", -- 𝕆 opar = "\226\166\183", -- ⦷ OpenCurlyDoubleQuote = "\226\128\156", -- “ OpenCurlyQuote = "\226\128\152", -- ‘ operp = "\226\166\185", -- ⦹ oplus = "\226\138\149", -- ⊕ ["or"] = "\226\136\168", -- ∨ Or = "\226\169\148", -- ⩔ orarr = "\226\134\187", -- ↻ ord = "\226\169\157", -- ⩝ order = "\226\132\180", -- ℴ orderof = "\226\132\180", -- ℴ ordf = "\194\170", -- ª ordm = "\194\186", -- º origof = "\226\138\182", -- ⊶ oror = "\226\169\150", -- ⩖ orslope = "\226\169\151", -- ⩗ orv = "\226\169\155", -- ⩛ oS = "\226\147\136", -- Ⓢ oscr = "\226\132\180", -- ℴ Oscr = "\240\157\146\170", -- 𝒪 oslash = "\195\184", -- ø Oslash = "\195\152", -- Ø osol = "\226\138\152", -- ⊘ otilde = "\195\181", -- õ Otilde = "\195\149", -- Õ otimes = "\226\138\151", -- ⊗ Otimes = "\226\168\183", -- ⨷ otimesas = "\226\168\182", -- ⨶ ouml = "\195\182", -- ö Ouml = "\195\150", -- Ö ovbar = "\226\140\189", -- ⌽ OverBar = "\226\128\190", -- ‾ OverBrace = "\226\143\158", -- ⏞ OverBracket = "\226\142\180", -- ⎴ OverParenthesis = "\226\143\156", -- ⏜ par = "\226\136\165", -- ∥ para = "\194\182", -- ¶ parallel = "\226\136\165", -- ∥ parsim = "\226\171\179", -- ⫳ parsl = "\226\171\189", -- ⫽ part = "\226\136\130", -- ∂ PartialD = "\226\136\130", -- ∂ pcy = "\208\191", -- п Pcy = "\208\159", -- П percnt = "\37", -- % period = "\46", -- . permil = "\226\128\176", -- ‰ perp = "\226\138\165", -- ⊥ pertenk = "\226\128\177", -- ‱ pfr = "\240\157\148\173", -- 𝔭 Pfr = "\240\157\148\147", -- 𝔓 phi = "\207\134", -- φ Phi = "\206\166", -- Φ phiv = "\207\149", -- ϕ phmmat = "\226\132\179", -- ℳ phone = "\226\152\142", -- ☎ pi = "\207\128", -- π Pi = "\206\160", -- Π pitchfork = "\226\139\148", -- ⋔ piv = "\207\150", -- ϖ planck = "\226\132\143", -- ℏ planckh = "\226\132\142", -- ℎ plankv = "\226\132\143", -- ℏ plus = "\43", -- + plusacir = "\226\168\163", -- ⨣ plusb = "\226\138\158", -- ⊞ pluscir = "\226\168\162", -- ⨢ plusdo = "\226\136\148", -- ∔ plusdu = "\226\168\165", -- ⨥ pluse = "\226\169\178", -- ⩲ PlusMinus = "\194\177", -- ± plusmn = "\194\177", -- ± plussim = "\226\168\166", -- ⨦ plustwo = "\226\168\167", -- ⨧ pm = "\194\177", -- ± Poincareplane = "\226\132\140", -- ℌ pointint = "\226\168\149", -- ⨕ popf = "\240\157\149\161", -- 𝕡 Popf = "\226\132\153", -- ℙ pound = "\194\163", -- £ pr = "\226\137\186", -- ≺ Pr = "\226\170\187", -- ⪻ prap = "\226\170\183", -- ⪷ prcue = "\226\137\188", -- ≼ pre = "\226\170\175", -- ⪯ prE = "\226\170\179", -- ⪳ prec = "\226\137\186", -- ≺ precapprox = "\226\170\183", -- ⪷ preccurlyeq = "\226\137\188", -- ≼ Precedes = "\226\137\186", -- ≺ PrecedesEqual = "\226\170\175", -- ⪯ PrecedesSlantEqual = "\226\137\188", -- ≼ PrecedesTilde = "\226\137\190", -- ≾ preceq = "\226\170\175", -- ⪯ precnapprox = "\226\170\185", -- ⪹ precneqq = "\226\170\181", -- ⪵ precnsim = "\226\139\168", -- ⋨ precsim = "\226\137\190", -- ≾ prime = "\226\128\178", -- ′ Prime = "\226\128\179", -- ″ primes = "\226\132\153", -- ℙ prnap = "\226\170\185", -- ⪹ prnE = "\226\170\181", -- ⪵ prnsim = "\226\139\168", -- ⋨ prod = "\226\136\143", -- ∏ Product = "\226\136\143", -- ∏ profalar = "\226\140\174", -- ⌮ profline = "\226\140\146", -- ⌒ profsurf = "\226\140\147", -- ⌓ prop = "\226\136\157", -- ∝ Proportion = "\226\136\183", -- ∷ Proportional = "\226\136\157", -- ∝ propto = "\226\136\157", -- ∝ prsim = "\226\137\190", -- ≾ prurel = "\226\138\176", -- ⊰ pscr = "\240\157\147\133", -- 𝓅 Pscr = "\240\157\146\171", -- 𝒫 psi = "\207\136", -- ψ Psi = "\206\168", -- Ψ puncsp = "\226\128\136", -- [punctuation space] qfr = "\240\157\148\174", -- 𝔮 Qfr = "\240\157\148\148", -- 𝔔 qint = "\226\168\140", -- ⨌ qopf = "\240\157\149\162", -- 𝕢 Qopf = "\226\132\154", -- ℚ qprime = "\226\129\151", -- ⁗ qscr = "\240\157\147\134", -- 𝓆 Qscr = "\240\157\146\172", -- 𝒬 quaternions = "\226\132\141", -- ℍ quatint = "\226\168\150", -- ⨖ quest = "\63", -- ? questeq = "\226\137\159", -- ≟ quot = "\34", -- " QUOT = "\34", -- " rAarr = "\226\135\155", -- ⇛ race = "\226\136\189\204\177", -- ∽̱ racute = "\197\149", -- ŕ Racute = "\197\148", -- Ŕ radic = "\226\136\154", -- √ raemptyv = "\226\166\179", -- ⦳ rang = "\226\159\169", -- ⟩ Rang = "\226\159\171", -- ⟫ rangd = "\226\166\146", -- ⦒ range = "\226\166\165", -- ⦥ rangle = "\226\159\169", -- ⟩ raquo = "\194\187", -- » rarr = "\226\134\146", -- → rArr = "\226\135\146", -- ⇒ Rarr = "\226\134\160", -- ↠ rarrap = "\226\165\181", -- ⥵ rarrb = "\226\135\165", -- ⇥ rarrbfs = "\226\164\160", -- ⤠ rarrc = "\226\164\179", -- ⤳ rarrfs = "\226\164\158", -- ⤞ rarrhk = "\226\134\170", -- ↪ rarrlp = "\226\134\172", -- ↬ rarrpl = "\226\165\133", -- ⥅ rarrsim = "\226\165\180", -- ⥴ rarrtl = "\226\134\163", -- ↣ Rarrtl = "\226\164\150", -- ⤖ rarrw = "\226\134\157", -- ↝ ratail = "\226\164\154", -- ⤚ rAtail = "\226\164\156", -- ⤜ ratio = "\226\136\182", -- ∶ rationals = "\226\132\154", -- ℚ rbarr = "\226\164\141", -- ⤍ rBarr = "\226\164\143", -- ⤏ RBarr = "\226\164\144", -- ⤐ rbbrk = "\226\157\179", -- ❳ rbrace = "\125", -- } rbrack = "\93", -- ] rbrke = "\226\166\140", -- ⦌ rbrksld = "\226\166\142", -- ⦎ rbrkslu = "\226\166\144", -- ⦐ rcaron = "\197\153", -- ř Rcaron = "\197\152", -- Ř rcedil = "\197\151", -- ŗ Rcedil = "\197\150", -- Ŗ rceil = "\226\140\137", -- ⌉ rcub = "\125", -- } rcy = "\209\128", -- р Rcy = "\208\160", -- Р rdca = "\226\164\183", -- ⤷ rdldhar = "\226\165\169", -- ⥩ rdquo = "\226\128\157", -- ” rdquor = "\226\128\157", -- ” rdsh = "\226\134\179", -- ↳ Re = "\226\132\156", -- ℜ real = "\226\132\156", -- ℜ realine = "\226\132\155", -- ℛ realpart = "\226\132\156", -- ℜ reals = "\226\132\157", -- ℝ rect = "\226\150\173", -- ▭ reg = "\194\174", -- ® REG = "\194\174", -- ® ReverseElement = "\226\136\139", -- ∋ ReverseEquilibrium = "\226\135\139", -- ⇋ ReverseUpEquilibrium = "\226\165\175", -- ⥯ rfisht = "\226\165\189", -- ⥽ rfloor = "\226\140\139", -- ⌋ rfr = "\240\157\148\175", -- 𝔯 Rfr = "\226\132\156", -- ℜ rHar = "\226\165\164", -- ⥤ rhard = "\226\135\129", -- ⇁ rharu = "\226\135\128", -- ⇀ rharul = "\226\165\172", -- ⥬ rho = "\207\129", -- ρ Rho = "\206\161", -- Ρ rhov = "\207\177", -- ϱ RightAngleBracket = "\226\159\169", -- ⟩ rightarrow = "\226\134\146", -- → Rightarrow = "\226\135\146", -- ⇒ RightArrow = "\226\134\146", -- → RightArrowBar = "\226\135\165", -- ⇥ RightArrowLeftArrow = "\226\135\132", -- ⇄ rightarrowtail = "\226\134\163", -- ↣ RightCeiling = "\226\140\137", -- ⌉ RightDoubleBracket = "\226\159\167", -- ⟧ RightDownTeeVector = "\226\165\157", -- ⥝ RightDownVector = "\226\135\130", -- ⇂ RightDownVectorBar = "\226\165\149", -- ⥕ RightFloor = "\226\140\139", -- ⌋ rightharpoondown = "\226\135\129", -- ⇁ rightharpoonup = "\226\135\128", -- ⇀ rightleftarrows = "\226\135\132", -- ⇄ rightleftharpoons = "\226\135\140", -- ⇌ rightrightarrows = "\226\135\137", -- ⇉ rightsquigarrow = "\226\134\157", -- ↝ RightTee = "\226\138\162", -- ⊢ RightTeeArrow = "\226\134\166", -- ↦ RightTeeVector = "\226\165\155", -- ⥛ rightthreetimes = "\226\139\140", -- ⋌ RightTriangle = "\226\138\179", -- ⊳ RightTriangleBar = "\226\167\144", -- ⧐ RightTriangleEqual = "\226\138\181", -- ⊵ RightUpDownVector = "\226\165\143", -- ⥏ RightUpTeeVector = "\226\165\156", -- ⥜ RightUpVector = "\226\134\190", -- ↾ RightUpVectorBar = "\226\165\148", -- ⥔ RightVector = "\226\135\128", -- ⇀ RightVectorBar = "\226\165\147", -- ⥓ ring = "\203\154", -- ˚ risingdotseq = "\226\137\147", -- ≓ rlarr = "\226\135\132", -- ⇄ rlhar = "\226\135\140", -- ⇌ rlm = "\226\128\143", -- [right-to-left mark] rmoust = "\226\142\177", -- ⎱ rmoustache = "\226\142\177", -- ⎱ rnmid = "\226\171\174", -- ⫮ roang = "\226\159\173", -- ⟭ roarr = "\226\135\190", -- ⇾ robrk = "\226\159\167", -- ⟧ ropar = "\226\166\134", -- ⦆ ropf = "\240\157\149\163", -- 𝕣 Ropf = "\226\132\157", -- ℝ roplus = "\226\168\174", -- ⨮ rotimes = "\226\168\181", -- ⨵ RoundImplies = "\226\165\176", -- ⥰ rpar = "\41", -- ) rpargt = "\226\166\148", -- ⦔ rppolint = "\226\168\146", -- ⨒ rrarr = "\226\135\137", -- ⇉ Rrightarrow = "\226\135\155", -- ⇛ rsaquo = "\226\128\186", -- › rscr = "\240\157\147\135", -- 𝓇 Rscr = "\226\132\155", -- ℛ rsh = "\226\134\177", -- ↱ Rsh = "\226\134\177", -- ↱ rsqb = "\93", -- ] rsquo = "\226\128\153", -- ’ rsquor = "\226\128\153", -- ’ rthree = "\226\139\140", -- ⋌ rtimes = "\226\139\138", -- ⋊ rtri = "\226\150\185", -- ▹ rtrie = "\226\138\181", -- ⊵ rtrif = "\226\150\184", -- ▸ rtriltri = "\226\167\142", -- ⧎ RuleDelayed = "\226\167\180", -- ⧴ ruluhar = "\226\165\168", -- ⥨ rx = "\226\132\158", -- ℞ sacute = "\197\155", -- ś Sacute = "\197\154", -- Ś sbquo = "\226\128\154", -- ‚ sc = "\226\137\187", -- ≻ Sc = "\226\170\188", -- ⪼ scap = "\226\170\184", -- ⪸ scaron = "\197\161", -- š Scaron = "\197\160", -- Š sccue = "\226\137\189", -- ≽ sce = "\226\170\176", -- ⪰ scE = "\226\170\180", -- ⪴ scedil = "\197\159", -- ş Scedil = "\197\158", -- Ş scirc = "\197\157", -- ŝ Scirc = "\197\156", -- Ŝ scnap = "\226\170\186", -- ⪺ scnE = "\226\170\182", -- ⪶ scnsim = "\226\139\169", -- ⋩ scpolint = "\226\168\147", -- ⨓ scsim = "\226\137\191", -- ≿ scy = "\209\129", -- с Scy = "\208\161", -- С sdot = "\226\139\133", -- ⋅ sdotb = "\226\138\161", -- ⊡ sdote = "\226\169\166", -- ⩦ searhk = "\226\164\165", -- ⤥ searr = "\226\134\152", -- ↘ seArr = "\226\135\152", -- ⇘ searrow = "\226\134\152", -- ↘ sect = "\194\167", -- § semi = "\59", -- ; seswar = "\226\164\169", -- ⤩ setminus = "\226\136\150", -- ∖ setmn = "\226\136\150", -- ∖ sext = "\226\156\182", -- ✶ sfr = "\240\157\148\176", -- 𝔰 Sfr = "\240\157\148\150", -- 𝔖 sfrown = "\226\140\162", -- ⌢ sharp = "\226\153\175", -- ♯ shchcy = "\209\137", -- щ SHCHcy = "\208\169", -- Щ shcy = "\209\136", -- ш SHcy = "\208\168", -- Ш ShortDownArrow = "\226\134\147", -- ↓ ShortLeftArrow = "\226\134\144", -- ← shortmid = "\226\136\163", -- ∣ shortparallel = "\226\136\165", -- ∥ ShortRightArrow = "\226\134\146", -- → ShortUpArrow = "\226\134\145", -- ↑ shy = "\194\173", -- [soft hyphen] sigma = "\207\131", -- σ Sigma = "\206\163", -- Σ sigmaf = "\207\130", -- ς sigmav = "\207\130", -- ς sim = "\226\136\188", -- ∼ simdot = "\226\169\170", -- ⩪ sime = "\226\137\131", -- ≃ simeq = "\226\137\131", -- ≃ simg = "\226\170\158", -- ⪞ simgE = "\226\170\160", -- ⪠ siml = "\226\170\157", -- ⪝ simlE = "\226\170\159", -- ⪟ simne = "\226\137\134", -- ≆ simplus = "\226\168\164", -- ⨤ simrarr = "\226\165\178", -- ⥲ slarr = "\226\134\144", -- ← SmallCircle = "\226\136\152", -- ∘ smallsetminus = "\226\136\150", -- ∖ smashp = "\226\168\179", -- ⨳ smeparsl = "\226\167\164", -- ⧤ smid = "\226\136\163", -- ∣ smile = "\226\140\163", -- ⌣ smt = "\226\170\170", -- ⪪ smte = "\226\170\172", -- ⪬ smtes = "\226\170\172\239\184\128", -- ⪬︀ softcy = "\209\140", -- ь SOFTcy = "\208\172", -- Ь sol = "\47", -- / solb = "\226\167\132", -- ⧄ solbar = "\226\140\191", -- ⌿ sopf = "\240\157\149\164", -- 𝕤 Sopf = "\240\157\149\138", -- 𝕊 spades = "\226\153\160", -- ♠ spadesuit = "\226\153\160", -- ♠ spar = "\226\136\165", -- ∥ sqcap = "\226\138\147", -- ⊓ sqcaps = "\226\138\147\239\184\128", -- ⊓︀ sqcup = "\226\138\148", -- ⊔ sqcups = "\226\138\148\239\184\128", -- ⊔︀ Sqrt = "\226\136\154", -- √ sqsub = "\226\138\143", -- ⊏ sqsube = "\226\138\145", -- ⊑ sqsubset = "\226\138\143", -- ⊏ sqsubseteq = "\226\138\145", -- ⊑ sqsup = "\226\138\144", -- ⊐ sqsupe = "\226\138\146", -- ⊒ sqsupset = "\226\138\144", -- ⊐ sqsupseteq = "\226\138\146", -- ⊒ squ = "\226\150\161", -- □ square = "\226\150\161", -- □ Square = "\226\150\161", -- □ SquareIntersection = "\226\138\147", -- ⊓ SquareSubset = "\226\138\143", -- ⊏ SquareSubsetEqual = "\226\138\145", -- ⊑ SquareSuperset = "\226\138\144", -- ⊐ SquareSupersetEqual = "\226\138\146", -- ⊒ SquareUnion = "\226\138\148", -- ⊔ squarf = "\226\150\170", -- ▪ squf = "\226\150\170", -- ▪ srarr = "\226\134\146", -- → sscr = "\240\157\147\136", -- 𝓈 Sscr = "\240\157\146\174", -- 𝒮 ssetmn = "\226\136\150", -- ∖ ssmile = "\226\140\163", -- ⌣ sstarf = "\226\139\134", -- ⋆ star = "\226\152\134", -- ☆ Star = "\226\139\134", -- ⋆ starf = "\226\152\133", -- ★ straightepsilon = "\207\181", -- ϵ straightphi = "\207\149", -- ϕ strns = "\194\175", -- ¯ sub = "\226\138\130", -- ⊂ Sub = "\226\139\144", -- ⋐ subdot = "\226\170\189", -- ⪽ sube = "\226\138\134", -- ⊆ subE = "\226\171\133", -- ⫅ subedot = "\226\171\131", -- ⫃ submult = "\226\171\129", -- ⫁ subne = "\226\138\138", -- ⊊ subnE = "\226\171\139", -- ⫋ subplus = "\226\170\191", -- ⪿ subrarr = "\226\165\185", -- ⥹ subset = "\226\138\130", -- ⊂ Subset = "\226\139\144", -- ⋐ subseteq = "\226\138\134", -- ⊆ subseteqq = "\226\171\133", -- ⫅ SubsetEqual = "\226\138\134", -- ⊆ subsetneq = "\226\138\138", -- ⊊ subsetneqq = "\226\171\139", -- ⫋ subsim = "\226\171\135", -- ⫇ subsub = "\226\171\149", -- ⫕ subsup = "\226\171\147", -- ⫓ succ = "\226\137\187", -- ≻ succapprox = "\226\170\184", -- ⪸ succcurlyeq = "\226\137\189", -- ≽ Succeeds = "\226\137\187", -- ≻ SucceedsEqual = "\226\170\176", -- ⪰ SucceedsSlantEqual = "\226\137\189", -- ≽ SucceedsTilde = "\226\137\191", -- ≿ succeq = "\226\170\176", -- ⪰ succnapprox = "\226\170\186", -- ⪺ succneqq = "\226\170\182", -- ⪶ succnsim = "\226\139\169", -- ⋩ succsim = "\226\137\191", -- ≿ SuchThat = "\226\136\139", -- ∋ sum = "\226\136\145", -- ∑ Sum = "\226\136\145", -- ∑ sung = "\226\153\170", -- ♪ sup = "\226\138\131", -- ⊃ Sup = "\226\139\145", -- ⋑ sup1 = "\194\185", -- ¹ sup2 = "\194\178", -- ² sup3 = "\194\179", -- ³ supdot = "\226\170\190", -- ⪾ supdsub = "\226\171\152", -- ⫘ supe = "\226\138\135", -- ⊇ supE = "\226\171\134", -- ⫆ supedot = "\226\171\132", -- ⫄ Superset = "\226\138\131", -- ⊃ SupersetEqual = "\226\138\135", -- ⊇ suphsol = "\226\159\137", -- ⟉ suphsub = "\226\171\151", -- ⫗ suplarr = "\226\165\187", -- ⥻ supmult = "\226\171\130", -- ⫂ supne = "\226\138\139", -- ⊋ supnE = "\226\171\140", -- ⫌ supplus = "\226\171\128", -- ⫀ supset = "\226\138\131", -- ⊃ Supset = "\226\139\145", -- ⋑ supseteq = "\226\138\135", -- ⊇ supseteqq = "\226\171\134", -- ⫆ supsetneq = "\226\138\139", -- ⊋ supsetneqq = "\226\171\140", -- ⫌ supsim = "\226\171\136", -- ⫈ supsub = "\226\171\148", -- ⫔ supsup = "\226\171\150", -- ⫖ swarhk = "\226\164\166", -- ⤦ swarr = "\226\134\153", -- ↙ swArr = "\226\135\153", -- ⇙ swarrow = "\226\134\153", -- ↙ swnwar = "\226\164\170", -- ⤪ szlig = "\195\159", -- ß Tab = "\t", -- [tab] target = "\226\140\150", -- ⌖ tau = "\207\132", -- τ Tau = "\206\164", -- Τ tbrk = "\226\142\180", -- ⎴ tcaron = "\197\165", -- ť Tcaron = "\197\164", -- Ť tcedil = "\197\163", -- ţ Tcedil = "\197\162", -- Ţ tcy = "\209\130", -- т Tcy = "\208\162", -- Т tdot = "\226\131\155", -- ⃛ telrec = "\226\140\149", -- ⌕ tfr = "\240\157\148\177", -- 𝔱 Tfr = "\240\157\148\151", -- 𝔗 there4 = "\226\136\180", -- ∴ therefore = "\226\136\180", -- ∴ Therefore = "\226\136\180", -- ∴ theta = "\206\184", -- θ Theta = "\206\152", -- Θ thetasym = "\207\145", -- ϑ thetav = "\207\145", -- ϑ thickapprox = "\226\137\136", -- ≈ thicksim = "\226\136\188", -- ∼ ThickSpace = "\226\129\159\226\128\138", -- [medium mathematical space] + [hair space] thinsp = "\226\128\137", -- [thin space] ThinSpace = "\226\128\137", -- [thin space] thkap = "\226\137\136", -- ≈ thksim = "\226\136\188", -- ∼ thorn = "\195\190", -- þ THORN = "\195\158", -- Þ tilde = "\203\156", -- ˜ Tilde = "\226\136\188", -- ∼ TildeEqual = "\226\137\131", -- ≃ TildeFullEqual = "\226\137\133", -- ≅ TildeTilde = "\226\137\136", -- ≈ times = "\195\151", -- × timesb = "\226\138\160", -- ⊠ timesbar = "\226\168\177", -- ⨱ timesd = "\226\168\176", -- ⨰ tint = "\226\136\173", -- ∭ toea = "\226\164\168", -- ⤨ top = "\226\138\164", -- ⊤ topbot = "\226\140\182", -- ⌶ topcir = "\226\171\177", -- ⫱ topf = "\240\157\149\165", -- 𝕥 Topf = "\240\157\149\139", -- 𝕋 topfork = "\226\171\154", -- ⫚ tosa = "\226\164\169", -- ⤩ tprime = "\226\128\180", -- ‴ trade = "\226\132\162", -- ™ TRADE = "\226\132\162", -- ™ triangle = "\226\150\181", -- ▵ triangledown = "\226\150\191", -- ▿ triangleleft = "\226\151\131", -- ◃ trianglelefteq = "\226\138\180", -- ⊴ triangleq = "\226\137\156", -- ≜ triangleright = "\226\150\185", -- ▹ trianglerighteq = "\226\138\181", -- ⊵ tridot = "\226\151\172", -- ◬ trie = "\226\137\156", -- ≜ triminus = "\226\168\186", -- ⨺ TripleDot = "\226\131\155", -- ⃛ triplus = "\226\168\185", -- ⨹ trisb = "\226\167\141", -- ⧍ tritime = "\226\168\187", -- ⨻ trpezium = "\226\143\162", -- ⏢ tscr = "\240\157\147\137", -- 𝓉 Tscr = "\240\157\146\175", -- 𝒯 tscy = "\209\134", -- ц TScy = "\208\166", -- Ц tshcy = "\209\155", -- ћ TSHcy = "\208\139", -- Ћ tstrok = "\197\167", -- ŧ Tstrok = "\197\166", -- Ŧ twixt = "\226\137\172", -- ≬ twoheadleftarrow = "\226\134\158", -- ↞ twoheadrightarrow = "\226\134\160", -- ↠ uacute = "\195\186", -- ú Uacute = "\195\154", -- Ú uarr = "\226\134\145", -- ↑ uArr = "\226\135\145", -- ⇑ Uarr = "\226\134\159", -- ↟ Uarrocir = "\226\165\137", -- ⥉ ubrcy = "\209\158", -- ў Ubrcy = "\208\142", -- Ў ubreve = "\197\173", -- ŭ Ubreve = "\197\172", -- Ŭ ucirc = "\195\187", -- û Ucirc = "\195\155", -- Û ucy = "\209\131", -- у Ucy = "\208\163", -- У udarr = "\226\135\133", -- ⇅ udblac = "\197\177", -- ű Udblac = "\197\176", -- Ű udhar = "\226\165\174", -- ⥮ ufisht = "\226\165\190", -- ⥾ ufr = "\240\157\148\178", -- 𝔲 Ufr = "\240\157\148\152", -- 𝔘 ugrave = "\195\185", -- ù Ugrave = "\195\153", -- Ù uHar = "\226\165\163", -- ⥣ uharl = "\226\134\191", -- ↿ uharr = "\226\134\190", -- ↾ uhblk = "\226\150\128", -- ▀ ulcorn = "\226\140\156", -- ⌜ ulcorner = "\226\140\156", -- ⌜ ulcrop = "\226\140\143", -- ⌏ ultri = "\226\151\184", -- ◸ umacr = "\197\171", -- ū Umacr = "\197\170", -- Ū uml = "\194\168", -- ¨ UnderBar = "\95", -- _ UnderBrace = "\226\143\159", -- ⏟ UnderBracket = "\226\142\181", -- ⎵ UnderParenthesis = "\226\143\157", -- ⏝ Union = "\226\139\131", -- ⋃ UnionPlus = "\226\138\142", -- ⊎ uogon = "\197\179", -- ų Uogon = "\197\178", -- Ų uopf = "\240\157\149\166", -- 𝕦 Uopf = "\240\157\149\140", -- 𝕌 uparrow = "\226\134\145", -- ↑ Uparrow = "\226\135\145", -- ⇑ UpArrow = "\226\134\145", -- ↑ UpArrowBar = "\226\164\146", -- ⤒ UpArrowDownArrow = "\226\135\133", -- ⇅ updownarrow = "\226\134\149", -- ↕ Updownarrow = "\226\135\149", -- ⇕ UpDownArrow = "\226\134\149", -- ↕ UpEquilibrium = "\226\165\174", -- ⥮ upharpoonleft = "\226\134\191", -- ↿ upharpoonright = "\226\134\190", -- ↾ uplus = "\226\138\142", -- ⊎ UpperLeftArrow = "\226\134\150", -- ↖ UpperRightArrow = "\226\134\151", -- ↗ upsi = "\207\133", -- υ Upsi = "\207\146", -- ϒ upsih = "\207\146", -- ϒ upsilon = "\207\133", -- υ Upsilon = "\206\165", -- Υ UpTee = "\226\138\165", -- ⊥ UpTeeArrow = "\226\134\165", -- ↥ upuparrows = "\226\135\136", -- ⇈ urcorn = "\226\140\157", -- ⌝ urcorner = "\226\140\157", -- ⌝ urcrop = "\226\140\142", -- ⌎ uring = "\197\175", -- ů Uring = "\197\174", -- Ů urtri = "\226\151\185", -- ◹ uscr = "\240\157\147\138", -- 𝓊 Uscr = "\240\157\146\176", -- 𝒰 utdot = "\226\139\176", -- ⋰ utilde = "\197\169", -- ũ Utilde = "\197\168", -- Ũ utri = "\226\150\181", -- ▵ utrif = "\226\150\180", -- ▴ uuarr = "\226\135\136", -- ⇈ uuml = "\195\188", -- ü Uuml = "\195\156", -- Ü uwangle = "\226\166\167", -- ⦧ vangrt = "\226\166\156", -- ⦜ varepsilon = "\207\181", -- ϵ varkappa = "\207\176", -- ϰ varnothing = "\226\136\133", -- ∅ varphi = "\207\149", -- ϕ varpi = "\207\150", -- ϖ varpropto = "\226\136\157", -- ∝ varr = "\226\134\149", -- ↕ vArr = "\226\135\149", -- ⇕ varrho = "\207\177", -- ϱ varsigma = "\207\130", -- ς varsubsetneq = "\226\138\138\239\184\128", -- ⊊︀ varsubsetneqq = "\226\171\139\239\184\128", -- ⫋︀ varsupsetneq = "\226\138\139\239\184\128", -- ⊋︀ varsupsetneqq = "\226\171\140\239\184\128", -- ⫌︀ vartheta = "\207\145", -- ϑ vartriangleleft = "\226\138\178", -- ⊲ vartriangleright = "\226\138\179", -- ⊳ vBar = "\226\171\168", -- ⫨ Vbar = "\226\171\171", -- ⫫ vBarv = "\226\171\169", -- ⫩ vcy = "\208\178", -- в Vcy = "\208\146", -- В vdash = "\226\138\162", -- ⊢ vDash = "\226\138\168", -- ⊨ Vdash = "\226\138\169", -- ⊩ VDash = "\226\138\171", -- ⊫ Vdashl = "\226\171\166", -- ⫦ vee = "\226\136\168", -- ∨ Vee = "\226\139\129", -- ⋁ veebar = "\226\138\187", -- ⊻ veeeq = "\226\137\154", -- ≚ vellip = "\226\139\174", -- ⋮ verbar = "\124", -- | Verbar = "\226\128\150", -- ‖ vert = "\124", -- | Vert = "\226\128\150", -- ‖ VerticalBar = "\226\136\163", -- ∣ VerticalLine = "\124", -- | VerticalSeparator = "\226\157\152", -- ❘ VerticalTilde = "\226\137\128", -- ≀ VeryThinSpace = "\226\128\138", -- [hair space] vfr = "\240\157\148\179", -- 𝔳 Vfr = "\240\157\148\153", -- 𝔙 vltri = "\226\138\178", -- ⊲ vnsub = "\226\138\130\226\131\146", -- ⊂⃒ vnsup = "\226\138\131\226\131\146", -- ⊃⃒ vopf = "\240\157\149\167", -- 𝕧 Vopf = "\240\157\149\141", -- 𝕍 vprop = "\226\136\157", -- ∝ vrtri = "\226\138\179", -- ⊳ vscr = "\240\157\147\139", -- 𝓋 Vscr = "\240\157\146\177", -- 𝒱 vsubne = "\226\138\138\239\184\128", -- ⊊︀ vsubnE = "\226\171\139\239\184\128", -- ⫋︀ vsupne = "\226\138\139\239\184\128", -- ⊋︀ vsupnE = "\226\171\140\239\184\128", -- ⫌︀ Vvdash = "\226\138\170", -- ⊪ vzigzag = "\226\166\154", -- ⦚ wcirc = "\197\181", -- ŵ Wcirc = "\197\180", -- Ŵ wedbar = "\226\169\159", -- ⩟ wedge = "\226\136\167", -- ∧ Wedge = "\226\139\128", -- ⋀ wedgeq = "\226\137\153", -- ≙ weierp = "\226\132\152", -- ℘ wfr = "\240\157\148\180", -- 𝔴 Wfr = "\240\157\148\154", -- 𝔚 wopf = "\240\157\149\168", -- 𝕨 Wopf = "\240\157\149\142", -- 𝕎 wp = "\226\132\152", -- ℘ wr = "\226\137\128", -- ≀ wreath = "\226\137\128", -- ≀ wscr = "\240\157\147\140", -- 𝓌 Wscr = "\240\157\146\178", -- 𝒲 xcap = "\226\139\130", -- ⋂ xcirc = "\226\151\175", -- ◯ xcup = "\226\139\131", -- ⋃ xdtri = "\226\150\189", -- ▽ xfr = "\240\157\148\181", -- 𝔵 Xfr = "\240\157\148\155", -- 𝔛 xharr = "\226\159\183", -- ⟷ xhArr = "\226\159\186", -- ⟺ xi = "\206\190", -- ξ Xi = "\206\158", -- Ξ xlarr = "\226\159\181", -- ⟵ xlArr = "\226\159\184", -- ⟸ xmap = "\226\159\188", -- ⟼ xnis = "\226\139\187", -- ⋻ xodot = "\226\168\128", -- ⨀ xopf = "\240\157\149\169", -- 𝕩 Xopf = "\240\157\149\143", -- 𝕏 xoplus = "\226\168\129", -- ⨁ xotime = "\226\168\130", -- ⨂ xrarr = "\226\159\182", -- ⟶ xrArr = "\226\159\185", -- ⟹ xscr = "\240\157\147\141", -- 𝓍 Xscr = "\240\157\146\179", -- 𝒳 xsqcup = "\226\168\134", -- ⨆ xuplus = "\226\168\132", -- ⨄ xutri = "\226\150\179", -- △ xvee = "\226\139\129", -- ⋁ xwedge = "\226\139\128", -- ⋀ yacute = "\195\189", -- ý Yacute = "\195\157", -- Ý yacy = "\209\143", -- я YAcy = "\208\175", -- Я ycirc = "\197\183", -- ŷ Ycirc = "\197\182", -- Ŷ ycy = "\209\139", -- ы Ycy = "\208\171", -- Ы yen = "\194\165", -- ¥ yfr = "\240\157\148\182", -- 𝔶 Yfr = "\240\157\148\156", -- 𝔜 yicy = "\209\151", -- ї YIcy = "\208\135", -- Ї yopf = "\240\157\149\170", -- 𝕪 Yopf = "\240\157\149\144", -- 𝕐 yscr = "\240\157\147\142", -- 𝓎 Yscr = "\240\157\146\180", -- 𝒴 yucy = "\209\142", -- ю YUcy = "\208\174", -- Ю yuml = "\195\191", -- ÿ Yuml = "\197\184", -- Ÿ zacute = "\197\186", -- ź Zacute = "\197\185", -- Ź zcaron = "\197\190", -- ž Zcaron = "\197\189", -- Ž zcy = "\208\183", -- з Zcy = "\208\151", -- З zdot = "\197\188", -- ż Zdot = "\197\187", -- Ż zeetrf = "\226\132\168", -- ℨ ZeroWidthSpace = "\226\128\139", -- [zero width space] zeta = "\206\182", -- ζ Zeta = "\206\150", -- Ζ zfr = "\240\157\148\183", -- 𝔷 Zfr = "\226\132\168", -- ℨ zhcy = "\208\182", -- ж ZHcy = "\208\150", -- Ж zigrarr = "\226\135\157", -- ⇝ zopf = "\240\157\149\171", -- 𝕫 Zopf = "\226\132\164", -- ℤ zscr = "\240\157\147\143", -- 𝓏 Zscr = "\240\157\146\181", -- 𝒵 zwj = "\226\128\141", -- [zero width joiner] zwnj = "\226\128\140", -- [zero width non-joiner] -- Nonstandard, but accepted by MediaWiki. ["רלמ"] = "\226\128\143", -- [right-to-left mark] ["رلم"] = "\226\128\143", -- [right-to-left mark] } 8o4sqdodbkfwk9xmp2f1xlrb7zei3p7 Modul:parser 828 41868 218845 187742 2025-06-20T00:28:03Z Sponge2490 8927 Mengemaskini berdasarkan Module:parser pada 14 Mei 2025 (84802573) 218845 Scribunto text/plain local export = {} local scribunto_metamethods_module = "Module:Scribunto/metamethods" local table_deep_copy_module = "Module:table/deepCopy" local table_get_nested_module = "Module:table/getNested" local table_set_nested_module = "Module:table/setNested" local concat = table.concat local find = string.find local getmetatable = getmetatable local insert = table.insert local next = next local rawget = rawget local rawset = rawset local remove = table.remove local require = require local select = select local setmetatable = setmetatable local sub = string.sub local type = type local unpack = unpack or table.unpack -- Lua 5.2 compatibility local node_classes = {} local function deep_copy(...) deep_copy = require(table_deep_copy_module) return deep_copy(...) end local function get_nested(...) get_nested = require(table_get_nested_module) return get_nested(...) end local function set_nested(...) set_nested = require(table_set_nested_module) return set_nested(...) end --[==[ Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==] local metamethods local function get_metamethods() -- Use require, since lookup times are much slower with mw.loadData. metamethods, get_metamethods = require(scribunto_metamethods_module), nil return metamethods end ------------------------------------------------------------------------------------ -- -- Helper functions -- ------------------------------------------------------------------------------------ local function inherit_metamethods(child, parent) if parent then for method, value in next, parent do if child[method] == nil and (metamethods or get_metamethods())[method] ~= nil then child[method] = value end end end return child end local function signed_index(t, n) return n and n <= 0 and #t + 1 + n or n end local function is_node(value) if value == nil then return false end local mt = getmetatable(value) return not (mt == nil or node_classes[mt] == nil) end local function node_class(value) if value == nil then return nil end local mt = getmetatable(value) if mt == nil then return nil end return mt ~= nil and node_classes[mt] or nil end local function class_else_type(value) if value == nil then return type(value) end local mt = getmetatable(value) if mt == nil then return type(value) end local class = node_classes[mt] return class == nil and type(value) or class end -- Recursively calling tostring() adds to the C stack (limit: 200), whereas -- calling __tostring metamethods directly does not. Occasionally relevant when -- dealing with very deep nesting. local tostring do local _tostring = _G.tostring function tostring(value) if is_node(value) then return value:__tostring(value) end return _tostring(value) end end ------------------------------------------------------------------------------------ -- -- Nodes -- ------------------------------------------------------------------------------------ local Node = {} Node.__index = Node function Node:next(i) i = i + 1 return self[i], self, i end --[==[ Implements recursive iteration over a node tree. By default, when a node is encountered (which may contain other nodes), it is returned on the first iteration, and then any child nodes are returned on each subsequent iteration; the same process is then followed if any of those children contain nodes themselves. Once a particular node has been fully traversed, the iterator then continues with any sibling nodes. The iterator will use the `next` method of each node to traverse it, which may differ depending on the node class. Each iteration returns three values: `value`, `node` and `key`. Together, these can be used to manipulate the node tree at any given point without needing to know the full structure. Note that when the input node is returned on the first iteration, `node` and `key` will be nil. The optional argument `test` can be used to limit the return values. This should be a function that returns a boolean value, where a return value of true means that the child will be returned by the iterator. If a node is not returned by the iterator, it will still be traversed, as it may contain children that should be returned. The method `iterate_nodes` is provided as a special instance of iterate which uses `is_node` as the test.]==] function Node:iterate(test) local node, k, n, nodes, keys, returned_self = self, 0, 0 -- Special case if `test` is `is_node`. local is_node_is_test = test == is_node return function() if not returned_self then returned_self = true if test == nil or test(self) then return self end end -- Get `v`, which is the value at the last-returned key of the current node; if `v` is a node, it will be iterated over (i.e. recursive iteration). By default, `v` will be the last-returned value, but looking it up here means that any modifications made to the node during the loop will be taken into account. This makes it possible to swap one node out for something else (e.g. another node), or to remove it entirely, without being locked into recursively iterating over the old node; instead, the new node (if any) will be iterated over. This means node trees can be modified on-the-fly during the course of a single loop. local v, node_check = node[k], true while true do -- If `v` is a node, memoize the current node and key, then iterate over it. if node_check and is_node(v) then -- `n` is the current memo level. n = n + 1 if nodes then nodes[n], keys[n] = node, k else nodes, keys = {node}, {k} end node, k = v, 0 end v, node, k = node:next(k) -- If `v` is nil, move down one level, then continue iterating the node on that level (if any), or otherwise terminate the loop. if v == nil then if n == 0 then return nil end node, k, n = nodes[n], keys[n], n - 1 elseif test == nil or test(v) then return v, node, k -- If `test` is `is_node`, there's no point checking it again on the next loop. elseif node_check and is_node_is_test then node_check = false end end end end function Node:iterate_nodes(...) local args_n = select("#", ...) if args_n == 0 then return self:iterate(is_node) elseif args_n == 1 then local class = ... return self:iterate(function(value) return node_class(value) == class end) end local classes = {} for i = 1, args_n do classes[select(i, ...)] = true end return self:iterate(function(value) return classes[node_class(value)] end) end function Node:__tostring() local output = {} for i = 1, #self do insert(output, tostring(self[i])) end return concat(output) end function Node:clone() return deep_copy(self, "keep", true) end function Node:new_class(class) local t = {type = class} t.__index = t t = inherit_metamethods(t, self) node_classes[t] = class return setmetatable(t, self) end function Node:new(t) rawset(t, "_parse_data", nil) return setmetatable(t, self) end do local Proxy = {} function Proxy:__index(k) local v = Proxy[k] if v ~= nil then return v end return self.__chars[k] end function Proxy:__newindex(k, v) local key = self.__keys[k] if key then self.__chars[k] = v self.__parents[key] = v elseif key == false then error("Character is immutable.") else error("Invalid key.") end end function Proxy:build(a, b, c) local len = self.__len + 1 self.__chars[len] = a self.__parents[len] = b self.__keys[len] = c self.__len = len end function Proxy:iter(i) i = i + 1 local char = self.__chars[i] if char ~= nil then return i, self[i], self, self.__parents[i], self.__keys[i] end end function Node:new_proxy() return setmetatable({ __node = self, __chars = {}, __parents = {}, __keys = {}, __len = 0 }, Proxy) end end function export.node() return Node:new_class("node") end ------------------------------------------------------------------------------------ -- -- Parser -- ------------------------------------------------------------------------------------ local Parser = {} Parser.__index = Parser function Parser:get_layer(n) if n ~= nil then return rawget(self, #self + n) end return self.current_layer end function Parser:emit(a, b) local layer = self.current_layer if b ~= nil then insert(layer, signed_index(layer, a), b) else rawset(layer, #layer + 1, a) end end function Parser:emit_tokens(a, b) local layer = self.current_layer if b ~= nil then a = signed_index(layer, a) for i = 1, #b do insert(layer, a + i - 1, b[i]) end else local len = #layer for i = 1, #a do len = len + 1 rawset(layer, len, a[i]) end end end function Parser:remove(n) local layer = self.current_layer if n ~= nil then return remove(layer, signed_index(layer, n)) end local len = #layer local token = layer[len] layer[len] = nil return token end function Parser:replace(a, b) local layer = self.current_layer layer[signed_index(layer, a)] = b end -- Unlike default table.concat, this respects __tostring metamethods. function Parser:concat(a, b, c) if a == nil or a > 0 then return self:concat(0, a, b) end local layer, ret, n = self:get_layer(a), {}, 0 for i = b and signed_index(layer, b) or 1, c and signed_index(layer, c) or #layer do n = n + 1 ret[n] = tostring(layer[i]) end return concat(ret) end function Parser:emitted(delta) if delta == nil then delta = -1 end local get_layer, i = self.get_layer, 0 while true do local layer = get_layer(self, i) if layer == nil then return nil end local layer_len = #layer if -delta <= layer_len then return rawget(layer, layer_len + delta + 1) end delta = delta + layer_len i = i - 1 end end function Parser:push(route) local layer = {_parse_data = { head = self.head, route = route, }} self[#self + 1] = layer self.current_layer = layer end function Parser:push_sublayer(handler, inherit) local pdata = { handler = handler, sublayer = true, } local sublayer = { _parse_data = pdata, } if inherit then local layer_parse_data = self.current_layer._parse_data setmetatable(pdata, inherit_metamethods({ __index = layer_parse_data, __newindex = layer_parse_data }, getmetatable(layer_parse_data))) end self[#self + 1] = sublayer self.current_layer = sublayer end function Parser:pop() local len, layer = #self while true do layer = self[len] self[len] = nil len = len - 1 if len == 0 then self.current_layer = self break elseif layer._parse_data.sublayer == nil then self.current_layer = self[len] break end self:emit_tokens(layer) end return setmetatable(layer, nil) end function Parser:pop_sublayer() local len, layer = #self, self.current_layer self[len] = nil self.current_layer = len == 1 and self or self[len - 1] return setmetatable(layer, nil) end function Parser:get(route, ...) self:push(route) local layer = route(self, ...) if layer == nil then layer = self:traverse() end return layer end function Parser:try(route, ...) local failed_routes = self.failed_routes if failed_routes ~= nil then local failed_layer = get_nested(failed_routes, route, self.head) if failed_layer ~= nil then return false, failed_layer end end local layer = self:get(route, ...) return not layer._parse_data.fail, layer end function Parser:fail_route() local layer = self:pop() local pdata = layer._parse_data pdata.fail = true local layer_head = pdata.head set_nested(self, layer, "failed_routes", pdata.route, layer_head) self.head = layer_head return layer end function Parser:traverse() local consume, advance = self.consume, self.advance while true do local layer = consume(self) if layer ~= nil then return layer end advance(self) end end -- Converts a handler into a switch table the first time it's called, which avoids creating unnecessary objects, and prevents any scoping issues caused by parser methods being assigned to table keys before they've been declared. -- false is used as the default key. do local Switch = {} function Switch:__call(parser, this) return (self[this] or self[false])(parser, this) end function Parser:switch(func, t) local pdata = self.current_layer._parse_data -- Point handler to the new switch table if the calling function is the current handler. if pdata.handler == func then pdata.handler = t end return setmetatable(t, Switch) end end -- Generate a new parser class object, which is used as the template for any parser objects. These should be customized with additional/modified methods as needed. function Parser:new_class() local t = {} t.__index = t return setmetatable(inherit_metamethods(t, self), self) end -- Generate a new parser object, which is used for a specific parse. function Parser:new(text) return setmetatable({ text = text, head = 1 }, self) end function Parser:parse(data) local parser = self:new(data.text) local success, tokens = parser:try(unpack(data.route)) if #parser > 0 then -- This shouldn't happen. error("Parser exited with non-empty stack.") elseif success then local node = data.node return true, node[1]:new(tokens, unpack(node, 2)), parser elseif data.allow_fail then return false, nil, parser end error("Parser exited with failed route.") end export.class_else_type = class_else_type export.is_node = is_node export.tostring = tostring local ArrayParser = Parser:new_class() function ArrayParser:read(delta) local v = self.text[self.head + (delta or 0)] return v == nil and "" or v end function ArrayParser:advance(n) self.head = self.head + (n == nil and 1 or n) end function ArrayParser:jump(head) self.head = head end function ArrayParser:consume(this, ...) if this == nil then this = self:read() end local pdata = self.current_layer._parse_data return pdata.handler(self, this, ...) end function export.array_parser() return ArrayParser:new_class() end local StringParser = Parser:new_class() function StringParser:read(i, j) local head, i = self.head, i or 0 return sub(self.text, head + i, head + (j or i)) end function StringParser:advance(n) self.head = self.head + (n or self.current_layer._parse_data.step or 1) end function StringParser:jump(head) local pdata = self.current_layer._parse_data self.head, pdata.next, pdata.next_len = head, nil, nil end -- If `ignore_nonmatch` is set, any non-match segment before the match will be ignored. function StringParser:set_pattern(pattern, ignore_nonmatch) local pdata = self.current_layer._parse_data pdata.pattern, pdata.next, pdata.next_len = "(" .. pattern .. ")", nil, nil if ignore_nonmatch then pdata.ignore_nonmatch = true end end function StringParser:consume() local pdata = self.current_layer._parse_data local this = pdata.next -- Use `next` and `next_len` from the previous iteration, if available. if this then pdata.step, pdata.next, pdata.next_len = pdata.next_len, nil, nil return pdata.handler(self, this) end local text, head, loc1, loc2 = self.text, self.head loc1, loc2, this = find(text, pdata.pattern, head) -- If there was no match, default to find(text, "$", head), with `this` as -- the empty string. if not loc1 then this, loc1 = "", #text + 1 loc2 = loc1 - 1 -- zero-length matches cause loc2 to be less than loc1 end -- If `this` is at `head`, consume it. if loc1 == head then pdata.step = loc2 - loc1 + 1 -- If `ignore_nonmatch` is set, ignore everything before `this`, then -- consume it. elseif pdata.ignore_nonmatch then self.head, pdata.step = loc1, loc2 - loc1 + 1 -- Otherwise, consume everything before `this`, and memoize the match and -- match length; the length is dealt with separately, as it could be 0 if -- `next` is an index (e.g. if the pattern is the empty string). else this, pdata.step, pdata.next, pdata.next_len = sub(text, head, loc1 - 1), loc1 - head, this, loc2 - loc1 + 1 end return pdata.handler(self, this) end function export.string_parser() return StringParser:new_class() end return export itvslgsv46c1ywldkt63xzu5krykaov 218846 218845 2025-06-20T00:30:14Z Sponge2490 8927 Membatalkan semakan [[Special:Diff/218845|218845]] oleh [[Special:Contributions/Sponge2490|Sponge2490]] ([[User talk:Sponge2490|perbincangan]]) Ralat 218846 Scribunto text/plain local export = {} local concat = table.concat local deepcopy -- Assigned when needed. local getmetatable = getmetatable local insert = table.insert local next = next local rawget = rawget local rawset = rawset local remove = table.remove local select = select local setmetatable = setmetatable local type = type local unpack = unpack local classes = {} local metamethods = mw.loadData("Module:data/metamethods") ------------------------------------------------------------------------------------ -- -- Helper functions -- ------------------------------------------------------------------------------------ local function get_nested(a, b, ...) if not a then return nil elseif ... then return get_nested(a[b], ...) end return a[b] end local function set_nested(a, b, c, ...) if not (a and b) then return elseif c and ... then a[b] = a[b] or {} return set_nested(a[b], c, ...) end a[b] = c end local function inherit_metamethods(child, parent) if parent then for method, value in next, parent do if child[method] == nil and metamethods[method] then child[method] = value end end end return child end local function signed_index(t, n) return n and n <= 0 and #t + 1 + n or n end local function is_node(value) return classes[getmetatable(value)] and true or false end -- Recursively calling tostring() adds to the C stack (limit: 200), whereas -- calling __tostring metamethods directly does not. Occasionally relevant when -- dealing with very deep nesting. local tostring do local _tostring = _G.tostring function tostring(value) if is_node(value) then return value:__tostring(value) end return _tostring(value) end end local function class_else_type(value) return classes[getmetatable(value)] or type(value) end ------------------------------------------------------------------------------------ -- -- Nodes -- ------------------------------------------------------------------------------------ local Node = {} Node.__index = Node function Node:next(i) i = i + 1 return self[i], i end function Node:next_node(i) local v repeat v, i = self:next(i) until v == nil or is_node(v) return v, i end -- Implements recursive iteration over a node tree, using functors to maintain state (which uses a lot less memory than closures). Iterator1 exists only to return the calling node on the first iteration, while Iterator2 uses a stack to store the state of each layer in the tree. -- When a node is encountered (which may contain other nodes), it is returned on the first iteration, and then any child nodes are returned on each subsequent iteration; the same process is followed if any of those children contain nodes themselves. Once a particular node has been fully traversed, the iterator moves back up one layer and continues with any sibling nodes. -- Each iteration returns three values: `value`, `node` and `key`. Together, these can be used to manipulate the node tree at any given point without needing to know the full structure. Note that when the input node is returned on the first iteration, `node` and `key` will be nil. -- By default, the iterator will use the `next` method of each node, but this can be changed with the `next_func` parameter, which accepts a string argument with the name of a next method. This is because trees might consist of several different classes of node, and each might have different next methods that are tailored to their particular structures. In addition, each class of node might have multiple different next methods, which can be named according to their purposes. `next_func` ensures that the iterator uses equivalent next methods between different types of node. -- Currently, two next methods are available: `next`, which simply iterates over the node conventionally, and `next_node`, which only returns children that are themselves nodes. Custom next methods can be declared by any calling module. do local Iterator1, Iterator2 = {}, {} Iterator1.__index = Iterator2 -- Not a typo. Iterator2.__index = Iterator2 function Iterator1:__call() setmetatable(self, Iterator2) return self[1].node end function Iterator2:push(node) local layer = { k = 0, node = node } self[#self + 1] = layer self[-1] = layer return self end function Iterator2:pop() local len = #self self[len] = nil self[-1] = self[len - 1] end function Iterator2:catch_values(node, ...) local v, k = ... if v == nil then self:pop() if self[-1] then return self:__call() end return end self[-1].k = k if is_node(v) then self:push(v) end return v, node, select(2, ...) end function Iterator2:__call() local layer = self[-1] local node = layer.node return self:catch_values(node, node[self.next_func](node, layer.k)) end function Node:__pairs(next_func) return setmetatable({ next_func = next_func or "next" }, Iterator1):push(self) end end function Node:rawpairs() return next, self end function Node:__tostring() local output = {} for i = 1, #self do insert(output, tostring(self[i])) end return concat(output) end function Node:clone() if not deepcopy then deepcopy = require("Module:table").deepcopy end return deepcopy(self, "keep", true) end function Node:new_class(class) local t = {type = class} t.__index = t t = inherit_metamethods(t, self) classes[t] = class return setmetatable(t, self) end Node.keys_to_remove = {"fail", "handler", "head", "override", "route"} function Node:new(t) setmetatable(t, nil) local keys_to_remove = self.keys_to_remove for i = 1, #keys_to_remove do t[keys_to_remove[i]] = nil end return setmetatable(t, self) end do local Proxy = {} function Proxy:__index(k) return Proxy[k] or self.__chars[k] end function Proxy:__newindex(k, v) local key = self.__keys[k] if key then self.__chars[k] = v self.__parents[key] = v elseif key == false then error("Character is immutable.") else error("Invalid key.") end end function Proxy:build(a, b, c) local len = self.__len + 1 self.__chars[len] = a self.__parents[len] = b self.__keys[len] = c self.__len = len end function Proxy:iter(i) i = i + 1 local char = self.__chars[i] if char then return i, self[i], self, self.__parents[i], self.__keys[i] end end function Node:new_proxy() return setmetatable({ __node = self, __chars = {}, __parents = {}, __keys = {}, __len = 0 }, Proxy) end end ------------------------------------------------------------------------------------ -- -- Parser -- ------------------------------------------------------------------------------------ local Parser = {} Parser.__index = Parser function Parser:read(delta) return self.text[self.head + (delta or 0)] or "" end function Parser:advance(n) self.head = self.head + (n or 1) end function Parser:layer(n) if n then return rawget(self, #self + n) end return self[-1] end function Parser:emit(a, b) local layer = self[-1] if b then insert(layer, signed_index(layer, a), b) else rawset(layer, #layer + 1, a) end end function Parser:emit_tokens(a, b) local layer = self[-1] if b then a = signed_index(layer, a) for i = 1, #b do insert(layer, a + i - 1, b[i]) end else local len = #layer for i = 1, #a do len = len + 1 rawset(layer, len, a[i]) end end end function Parser:remove(n) local layer = self[-1] if n then return remove(layer, signed_index(layer, n)) end local len = #layer local token = layer[len] layer[len] = nil return token end function Parser:replace(a, b) local layer = self[-1] layer[signed_index(layer, a)] = b end -- Unlike default table.concat, this respects __tostring metamethods. function Parser:concat(a, b, c) if not a or a > 0 then return self:concat(0, a, b) end local layer = self:layer(a) local ret = {} for i = signed_index(layer, b) or 1, signed_index(layer, c) or #layer do insert(ret, tostring(layer[i])) end return concat(ret) end function Parser:emitted(delta) delta = delta or -1 local i = 0 while true do local layer = self:layer(i) if not layer then return nil end local layer_len = #layer if -delta <= layer_len then return rawget(layer, layer_len + delta + 1) end delta = delta + layer_len i = i - 1 end end function Parser:push(route) local layer = { head = self.head, route = route } self[#self + 1] = layer self[-1] = layer end function Parser:push_sublayer(handler, inherit) local sublayer = { handler = handler, sublayer = true } if inherit then local layer = self[-1] setmetatable(sublayer, inherit_metamethods({ __index = layer, __newindex = layer }, getmetatable(layer))) end self[#self + 1] = sublayer self[-1] = sublayer end function Parser:pop() local len, layer = #self while true do layer = self[len] self[len] = nil len = len - 1 self[-1] = self[len] or self if not layer.sublayer then break end self:emit_tokens(layer) end return layer end function Parser:pop_sublayer() local len, layer = #self, self[-1] self[len] = nil self[-1] = self[len - 1] or self setmetatable(layer, nil) layer.sublayer = nil return layer end function Parser:get(route, ...) local failed_route = get_nested(self.failed_routes, self.head, route) if failed_route then return false, failed_route end self:push(route) local layer = self[route](self, ...) if layer == nil then layer = self:traverse() end if layer.fail then return false, layer end return true, layer end function Parser:consume(this, ...) local layer = self[-1] return (layer.override or layer.handler)(self, this or self:read(), ...) end function Parser:fail_route() local layer = self:pop() layer.fail = true set_nested(self, "failed_routes", layer.head, layer.route, layer) self.head = layer.head return layer end function Parser:traverse() while true do local layer = self:consume() if layer then return layer end self:advance() end end -- Converts a handler into a switch table the first time it's called, which avoids creating unnecessary objects, and prevents any scoping issues caused by parser methods being assigned to table keys before they've been declared. -- false is used as the default key. do local Switch = {} function Switch:__call(parser, this) return (self[this] or self[false])(parser, this) end function Parser:switch(func, t) local layer = self[-1] -- Point handler to the new switch table if the calling function is the current handler. if layer.handler == func then layer.handler = t end return setmetatable(t, Switch) end end -- Generate a new parser class object, which is used as the template for any parser objects. These should be customized with additional/modified methods as needed. function Parser:new_class() local t = {} t.__index = t return setmetatable(inherit_metamethods(t, self), self) end -- Generate a new parser object, which is used for a specific parse. function Parser:new(text) return setmetatable({ text = text, head = 1 }, self) end function Parser:parse(data) local parser = self:new(data.text) local success, tokens = parser:get(unpack(data.route)) if #parser > 0 then -- This shouldn't happen. error("Parser exited with non-empty stack.") elseif success then local node = data.node return true, node[1]:new(tokens, unpack(node, 2)), parser elseif data.allow_fail then return false, nil, parser end error("Parser exited with bad route.") end export.class_else_type = class_else_type export.is_node = is_node export.tostring = tostring function export.new() return Parser:new_class(), Node:new_class("node") end return export m8ca5vsf65kudx5ne22s4knpb1xrwj6 Modul:data/magic words 828 51770 218844 184805 2025-06-20T00:01:48Z Sponge2490 8927 Mengemaskini berdasarkan Module:data/magic words pada 20 Febuari 2025 (83987375) 218844 Scribunto text/plain local next = next local date_and_time = "mw:Help:Magic words#Date and time" local escaped_characters = "mw:Help:Magic words#Escaped characters" local formatting = "mw:Help:Magic words#Formatting" local labeled_section_transclusion = "mw:Extension:Labeled Section Transclusion" local liquidthreads = "mw:Extension:LiquidThreads" local localization_functions = "mw:Help:Magic words#Localization functions" local localization_variables = "mw:Help:Magic words#Localization variables" local miscellaneous = "mw:Help:Magic words#Miscellaneous" local namespaces = "mw:Help:Magic words#Namespaces" local namespaces_2 = "mw:Help:Magic words#Namespaces 2" local noexternallanglinks = "mw:Wikibase/Installation/Advanced configuration#noexternallanglinks" local page_names = "mw:Help:Magic words#Page names" local parser_functions_ext = "mw:Help:Extension:ParserFunctions##" -- ## is not a typo local statistics = "mw:Help:Magic words#Statistics" local substitution = "mw:Manual:Substitution" local technical_metadata = "mw:Help:Magic words#Technical metadata" local technical_metadata_of_another_page = "mw:Help:Magic words#Technical metadata of another page" local transclusion_modifiers = "mw:Help:Magic words#Transclusion modifiers" local url_data = "mw:Help:Magic words#URL data" local data = {} for k, v in next, { ["!"] = { parser_variable = escaped_characters, case_sensitive = false }, ["#BABEL"] = { parser_function = "mw:Extension:Babel#Usage", case_sensitive = false }, ["#bcp47"] = { -- Case-sensitive lowercase. parser_function = localization_functions, parser_variable = localization_functions, -- Not a typo. case_sensitive = true }, ["#CATEGORYTREE"] = { parser_function = "mw:Extension:CategoryTree#The {{#categorytree}} parser function", case_sensitive = false }, ["#COMMASEPARATEDLIST"] = { parser_function = formatting, case_sensitive = false }, ["#dir"] = { -- Case-sensitive lowercase. parser_function = localization_functions, parser_variable = localization_functions, -- Not a typo. case_sensitive = true }, ["#EXPR"] = { parser_function = parser_functions_ext .. "expr", case_sensitive = false }, ["#FORMAL"] = { parser_function = localization_functions, case_sensitive = true }, ["#FORMATDATE"] = { aliases = {"#DATEFORMAT"}, parser_function = formatting, case_sensitive = false }, ["#IF"] = { parser_function = parser_functions_ext .. "if", case_sensitive = false }, ["#IFEQ"] = { parser_function = parser_functions_ext .. "ifeq", case_sensitive = false }, ["#IFERROR"] = { parser_function = parser_functions_ext .. "iferror", case_sensitive = false }, ["#IFEXIST"] = { parser_function = parser_functions_ext .. "ifexist", case_sensitive = false }, ["#IFEXPR"] = { parser_function = parser_functions_ext .. "ifexpr", case_sensitive = false }, ["#interlanguagelink"] = { -- Case-sensitive lowercase. parser_function = miscellaneous, case_sensitive = true }, ["#interwikilink"] = { -- Case-sensitive lowercase. parser_function = miscellaneous, case_sensitive = true }, ["#INVOKE"] = { parser_function = "mw:Extension:Scribunto#Usage", case_sensitive = false }, ["#LANGUAGE"] = { parser_function = localization_functions, parser_variable = localization_functions, -- Not a typo. case_sensitive = false }, ["#LQTPAGELIMIT"] = { parser_function = liquidthreads, case_sensitive = false }, ["#LST"] = { aliases = {"#SECTION"}, parser_function = labeled_section_transclusion, case_sensitive = false }, ["#LSTH"] = { aliases = {"#SECTION-H"}, parser_function = labeled_section_transclusion, case_sensitive = false }, ["#LSTX"] = { aliases = {"#SECTION-X"}, parser_function = labeled_section_transclusion, case_sensitive = false }, ["#PROPERTY"] = { parser_function = "m:Wikidata/Notes/Inclusion syntax", case_sensitive = false }, ["#REL2ABS"] = { parser_function = parser_functions_ext .. "rel2abs", case_sensitive = false }, ["#SPECIAL"] = { parser_function = miscellaneous, case_sensitive = false }, ["#SPECIALE"] = { parser_function = miscellaneous, case_sensitive = false }, ["#STATEMENTS"] = { parser_function = "d:WD:How to use data on Wikimedia projects#Parser function", case_sensitive = false }, ["#SWITCH"] = { parser_function = parser_functions_ext .. "switch", case_sensitive = false }, ["#TAG"] = { parser_function = miscellaneous, case_sensitive = false }, ["#TARGET"] = { parser_function = "mw:Extension:MassMessage#Parser function delivery lists", case_sensitive = false }, ["#TIME"] = { parser_function = parser_functions_ext .. "time", case_sensitive = false }, ["#timef"] = { -- Case-sensitive lowercase. parser_function = parser_functions_ext, case_sensitive = true }, ["#timefl"] = { -- Case-sensitive lowercase. parser_function = parser_functions_ext, case_sensitive = true }, ["#TIMEL"] = { parser_function = parser_functions_ext .. "timel", case_sensitive = false }, ["#TITLEPARTS"] = { parser_function = parser_functions_ext .. "titleparts", case_sensitive = false }, ["#USELIQUIDTHREADS"] = { parser_function = liquidthreads, case_sensitive = false }, ["="] = { parser_variable = escaped_characters, case_sensitive = false }, ["ANCHORENCODE"] = { parser_function = url_data, case_sensitive = false }, ["ARTICLEPATH"] = { parser_variable = technical_metadata, case_sensitive = false }, ["BASEPAGENAME"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["BASEPAGENAMEE"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["BIDI"] = { parser_function = formatting, case_sensitive = false }, ["CANONICALURL"] = { parser_function = url_data, case_sensitive = false }, ["CANONICALURLE"] = { parser_function = url_data, case_sensitive = false }, ["CASCADINGSOURCES"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["CONTENTLANGUAGE"] = { aliases = {"CONTENTLANG"}, parser_variable = technical_metadata, case_sensitive = true }, ["CURRENTDAY"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTDAY2"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTDAYNAME"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTDOW"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTHOUR"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTMONTH"] = { aliases = {"CURRENTMONTH2"}, parser_variable = date_and_time, case_sensitive = true }, ["CURRENTMONTH1"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTMONTHABBREV"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTMONTHNAME"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTMONTHNAMEGEN"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTTIME"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTTIMESTAMP"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTVERSION"] = { parser_variable = technical_metadata, case_sensitive = true }, ["CURRENTWEEK"] = { parser_variable = date_and_time, case_sensitive = true }, ["CURRENTYEAR"] = { parser_variable = date_and_time, case_sensitive = true }, ["DEFAULTSORT"] = { aliases = {"DEFAULTCATEGORYSORT", "DEFAULTSORTKEY"}, parser_function = technical_metadata, case_sensitive = true }, ["DIRECTIONMARK"] = { aliases = {"DIRMARK"}, parser_variable = technical_metadata, case_sensitive = true }, ["DISPLAYTITLE"] = { parser_function = technical_metadata, case_sensitive = true }, ["FILEPATH"] = { parser_function = url_data, case_sensitive = false }, ["FORMATNUM"] = { parser_function = formatting, case_sensitive = false }, ["FULLPAGENAME"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["FULLPAGENAMEE"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["FULLURL"] = { parser_function = url_data, case_sensitive = false }, ["FULLURLE"] = { parser_function = url_data, case_sensitive = false }, ["GENDER"] = { parser_function = localization_functions, case_sensitive = false }, ["GRAMMAR"] = { parser_function = localization_functions, case_sensitive = false }, ["INT"] = { parser_function = localization_functions, case_sensitive = false }, ["LC"] = { parser_function = formatting, case_sensitive = false }, ["LCFIRST"] = { parser_function = formatting, case_sensitive = false }, ["LOCALDAY"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALDAY2"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALDAYNAME"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALDOW"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALHOUR"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALMONTH"] = { aliases = {"LOCALMONTH2"}, parser_variable = date_and_time, case_sensitive = true }, ["LOCALMONTH1"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALMONTHABBREV"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALMONTHNAME"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALMONTHNAMEGEN"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALTIME"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALTIMESTAMP"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALURL"] = { parser_function = url_data, case_sensitive = false }, ["LOCALURLE"] = { parser_function = url_data, case_sensitive = false }, ["LOCALWEEK"] = { parser_variable = date_and_time, case_sensitive = true }, ["LOCALYEAR"] = { parser_variable = date_and_time, case_sensitive = true }, ["MSG"] = { transclusion_modifier = transclusion_modifiers, priority = 2, case_sensitive = false }, ["MSGNW"] = { transclusion_modifier = transclusion_modifiers, priority = 2, case_sensitive = false }, ["NAMESPACE"] = { parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["NAMESPACEE"] = { parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["NAMESPACENUMBER"] = { parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["NOEXTERNALLANGLINKS"] = { parser_function = noexternallanglinks, parser_variable = noexternallanglinks, case_sensitive = false }, ["NS"] = { parser_function = namespaces_2, case_sensitive = false }, ["NSE"] = { parser_function = namespaces_2, case_sensitive = false }, ["NUMBERINGROUP"] = { aliases = {"NUMINGROUP"}, parser_function = statistics, case_sensitive = true }, ["NUMBEROFACTIVEUSERS"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["NUMBEROFADMINS"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["NUMBEROFARTICLES"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["NUMBEROFEDITS"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["NUMBEROFFILES"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["NUMBEROFPAGES"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["NUMBEROFUSERS"] = { parser_function = statistics, parser_variable = statistics, case_sensitive = true }, ["PADLEFT"] = { parser_function = formatting, case_sensitive = false }, ["PADRIGHT"] = { parser_function = formatting, case_sensitive = false }, ["PAGEID"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = false }, ["PAGELANGUAGE"] = { parser_variable = technical_metadata, case_sensitive = true }, ["PAGENAME"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["PAGENAMEE"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["PAGESINCATEGORY"] = { aliases = {"PAGESINCAT"}, parser_function = statistics, case_sensitive = true }, ["PAGESIZE"] = { parser_function = technical_metadata_of_another_page, case_sensitive = true }, ["PLURAL"] = { parser_function = localization_functions, case_sensitive = false }, ["PROTECTIONEXPIRY"] = { parser_function = { technical_metadata, technical_metadata_of_another_page }, case_sensitive = true }, ["PROTECTIONLEVEL"] = { parser_function = { technical_metadata, technical_metadata_of_another_page }, case_sensitive = true }, ["RAW"] = { transclusion_modifier = transclusion_modifiers, priority = 3, case_sensitive = false }, ["REVISIONDAY"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONDAY2"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONID"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONMONTH"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONMONTH1"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONSIZE"] = { parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONTIMESTAMP"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONUSER"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["REVISIONYEAR"] = { parser_function = technical_metadata_of_another_page, parser_variable = technical_metadata, case_sensitive = true }, ["ROOTPAGENAME"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["ROOTPAGENAMEE"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["SAFESUBST"] = { transclusion_modifier = substitution, priority = 1, case_sensitive = false }, ["SCRIPTPATH"] = { parser_variable = technical_metadata, case_sensitive = false }, ["SERVER"] = { parser_variable = technical_metadata, case_sensitive = false }, ["SERVERNAME"] = { parser_variable = technical_metadata, case_sensitive = false }, ["SITENAME"] = { parser_variable = technical_metadata, case_sensitive = true }, ["STYLEPATH"] = { parser_variable = technical_metadata, case_sensitive = false }, ["SUBJECTPAGENAME"] = { aliases = {"ARTICLEPAGENAME"}, parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["SUBJECTPAGENAMEE"] = { aliases = {"ARTICLEPAGENAMEE"}, parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["SUBJECTSPACE"] = { aliases = {"ARTICLESPACE"}, parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["SUBJECTSPACEE"] = { aliases = {"ARTICLESPACEE"}, parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["SUBPAGENAME"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["SUBPAGENAMEE"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["SUBST"] = { transclusion_modifier = substitution, priority = 1, case_sensitive = false }, ["TALKPAGENAME"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["TALKPAGENAMEE"] = { parser_function = page_names, parser_variable = page_names, case_sensitive = true }, ["TALKSPACE"] = { parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["TALKSPACEE"] = { parser_function = namespaces, parser_variable = namespaces, case_sensitive = true }, ["UC"] = { parser_function = formatting, case_sensitive = false }, ["UCFIRST"] = { parser_function = formatting, case_sensitive = false }, ["URLENCODE"] = { parser_function = url_data, case_sensitive = false }, ["USERLANGUAGE"] = { parser_variable = localization_variables, case_sensitive = true }, } do data[k] = v if not v.name then v.name = k end local aliases = v.aliases if aliases then for i = 1, #aliases do data[aliases[i]] = v end v.aliases = nil end end return data jkwpl1ihlf560owi79olg91zvhvb1xy Modul:require when needed 828 57635 218840 186131 2025-06-19T23:41:33Z Sponge2490 8927 Mengemaskini berdasarkan Module:require when needed pada 24 April 2025 (84628829) 218840 Scribunto text/plain local getmetatable = getmetatable local ipairs = ipairs local loaded = package.loaded local pairs = pairs local require = require local select = select local setmetatable = setmetatable local tostring = tostring local unpack = unpack or table.unpack -- Lua 5.2 compatibility local function get_nested(obj, ...) local n = select("#", ...) if n == 0 then return obj end obj = obj[...] for i = 2, n do obj = obj[select(i, ...)] end return obj end local function get_obj(mt) local obj = require(mt[1]) if #mt > 1 then obj = get_nested(obj, unpack(mt, 2)) end mt[0] = obj return obj end local function __call(self, ...) local mt = getmetatable(self) local obj = mt[0] if obj == nil then obj = get_obj(mt) end return obj(...) end local function __index(self, k) local mt = getmetatable(self) local obj = mt[0] if obj == nil then obj = get_obj(mt) end return obj[k] end local function __ipairs(self) local mt = getmetatable(self) local obj = mt[0] if obj == nil then obj = get_obj(mt) end return ipairs(obj) end local function __newindex(self, k, v) local mt = getmetatable(self) local obj = mt[0] if obj == nil then obj = get_obj(mt) end obj[k] = v end local function __pairs(self) local mt = getmetatable(self) local obj = mt[0] if obj == nil then obj = get_obj(mt) end return pairs(obj) end local function __tostring(self) local mt = getmetatable(self) local obj = mt[0] if obj == nil then obj = get_obj(mt) end return tostring(obj) end return function(modname, ...) local mod = loaded[modname] if mod ~= nil then return get_nested(mod, ...) end return setmetatable({}, { modname, __call = __call, __index = __index, __ipairs = __ipairs, __newindex = __newindex, __pairs = __pairs, __tostring = __tostring, -- TODO: other metamethods, if needed. ... }) end 1p8upm5p2cm943t5atixatwvtsenpe2 Modul:pages 828 57817 218847 184808 2025-06-20T00:53:18Z Sponge2490 8927 Mengemaskini berdasarkan Module:pages when needed pada 26 Mei 2025 (84947246) 218847 Scribunto text/plain local export = {} local string_utilities_module = "Module:string utilities" local concat = table.concat local find = string.find local format = string.format local getmetatable = getmetatable local get_current_section -- defined below local get_namespace_shortcut -- defined below local get_pagetype -- defined below local gsub = string.gsub local insert = table.insert local is_internal_title -- defined below local is_title -- defined below local lower = string.lower local match = string.match local new_title = mw.title.new local require = require local sub = string.sub local title_equals = mw.title.equals local tonumber = tonumber local type = type local ufind = mw.ustring.find local unstrip_nowiki = mw.text.unstripNoWiki --[==[ Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==] local function decode_entities(...) decode_entities = require(string_utilities_module).decode_entities return decode_entities(...) end local function ulower(...) ulower = require(string_utilities_module).lower return ulower(...) end local function trim(...) trim = require(string_utilities_module).trim return trim(...) end --[==[ Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==] local current_frame local function get_current_frame() current_frame, get_current_frame = mw.getCurrentFrame(), nil return current_frame end local parent_frame local function get_parent_frame() parent_frame, get_parent_frame = (current_frame or get_current_frame()):getParent(), nil return parent_frame end local namespace_shortcuts local function get_namespace_shortcuts() namespace_shortcuts, get_namespace_shortcuts = { [4] = "WT", [10] = "T", [14] = "CAT", [100] = "AP", [110] = "WS", [118] = "RC", [828] = "MOD", }, nil return namespace_shortcuts end do local transcluded --[==[ Returns {true} if the current {{tl|#invoke:}} is being transcluded, or {false} if not. If the current {{tl|#invoke:}} is part of a template, for instance, this template will therefore return {true}. Note that if a template containing an {{tl|#invoke:}} is used on its own page (e.g. to display a demonstration), this function is still able to detect that this is transclusion. This is an improvement over the other method for detecting transclusion, which is to check the parent frame title against the current page title, which fails to detect transclusion in that instance.]==] function export.is_transcluded() if transcluded == nil then transcluded = (parent_frame or get_parent_frame()) and parent_frame:preprocess("<includeonly>1</includeonly>") == "1" or false end return transcluded end end do local preview --[==[ Returns {true} if the page is currently being viewed in preview, or {false} if not.]==] function export.is_preview() if preview == nil then preview = (current_frame or get_current_frame()):preprocess("{{REVISIONID}}") == "" end return preview end end --[==[ Returns {true} if the input is a title object, or {false} if not. This therefore '''includes''' external title objects (i.e. those for pages on other wikis), such as [[w:Example]], unlike `is_internal_title` below.]==] function export.is_title(val) if not (val and type(val) == "table") then return false end local mt = getmetatable(val) -- There's no foolproof method for checking for a title object, but the -- __eq metamethod should be mw.title.equals unless the object has been -- seriously messed around with. return mt and type(mt) == "table" and getmetatable(mt) == nil and mt.__eq == title_equals and true or false end is_title = export.is_title --[==[ Returns {true} if the input is an internal title object, or {false} if not. An internal title object is a title object for a page on this wiki, such as [[example]]. This therefore '''excludes''' external title objects (i.e. those for pages on other wikis), such as [[w:Example]], unlike `is_title` above.]==] function export.is_internal_title(title) -- Note: Mainspace titles starting with "#" should be invalid, but a bug in mw.title.new and mw.title.makeTitle means a title object is returned that has the empty string for prefixedText, so they need to be filtered out. return is_title(title) and #title.prefixedText > 0 and #title.interwiki == 0 end is_internal_title = export.is_internal_title --[==[ Returns {true} if the input string is a valid link target, or {false} if not. This therefore '''includes''' link targets to other wikis, such as [[w:Example]], unlike `is_valid_page_name` below.]==] function export.is_valid_link_target(target) local target_type = type(target) if target_type == "string" then return is_title(new_title(target)) end error(format("bad argument #1 to 'is_valid_link_target' (string expected, got %s)", target_type), 2) end --[==[ Returns {true} if the input string is a valid page name on this wiki, or {false} if not. This therefore '''excludes''' page names on other wikis, such as [[w:Example]], unlike `is_valid_link_target` above.]==] function export.is_valid_page_name(name) local name_type = type(name) if name_type == "string" then return is_internal_title(new_title(name)) end error(format("bad argument #1 to 'is_valid_page_name' (string expected, got %s)", name_type), 2) end --[==[ Given a title object, returns a full link target which will always unambiguously link to it. For instance, the input {"foo"} (for the page [[foo]]) returns {":foo"}, as a leading colon always refers to mainspace, even when other namespaces might be assumed (e.g. when transcluding using `{{ }}` syntax). If `shortcut` is set, then the returned target will use the namespace shortcut, if any; for example, the title for `Template:foo` would return {"T:foo"} instead of {"Template:foo"}.]==] function export.get_link_target(title, shortcut) if not is_title(title) then error(format("bad argument #1 to 'is_valid_link_target' (title object expected, got %s)", type(title))) elseif title.interwiki ~= "" then return title.fullText elseif shortcut then local fragment = title.fragment if fragment == "" then return get_namespace_shortcut(title) .. ":" .. title.text end return get_namespace_shortcut(title) .. ":" .. title.text .. "#" .. fragment elseif title.namespace == 0 then return ":" .. title.fullText end return title.fullText end do local function find_sandbox(text) return find(text, "^User:.") or find(lower(text), "sandbox", 1, true) end local function get_transclusion_subtypes(title, main_type, documentation, page_suffix) local text, subtypes = title.text, {main_type} -- Any template/module with "sandbox" in the title. These are impossible -- to screen for more accurately, as there's no consistent pattern. Also -- any user sandboxes in the form (e.g.) "Template:User:...". local sandbox = find_sandbox(text) if sandbox then insert(subtypes, "sandbox") end -- Any template/module testcases (which can be labelled and/or followed -- by further subpages). local testcase = find(text, "./[Tt]estcases?%f[%L]") if testcase then -- Order "testcase" and "sandbox" based on where the patterns occur -- in the title. local n = sandbox and sandbox < testcase and 3 or 2 insert(subtypes, n, "testcase") end -- Any template/module documentation pages. if documentation then insert(subtypes, "documentation") end local final = subtypes[#subtypes] if not (final == main_type and not page_suffix or final == "sandbox") then insert(subtypes, "page") end return concat(subtypes, " ") end local function get_snippet_subtypes(title, main_type, documentation) local ns = title.namespace return get_transclusion_subtypes(title, ( ns == 2 and "user " or ns == 8 and match(title.text, "^Gadget-.") and "gadget " or "" ) .. main_type, documentation) end --[==[ Returns the page type of the input title object in a format which can be used in running text.]==] function export.get_pagetype(title) if not is_internal_title(title) then error(mw.dumpObject(title.fullText) .. " is not a valid page name.") end -- If possibly a documentation page, get the base title and set the -- `documentation` flag. local content_model, text, documentation = title.contentModel if content_model == "wikitext" then text = title.text if title.isSubpage and title.subpageText == "documentation" then local base_title = title.basePageTitle if base_title then title, content_model, text, documentation = base_title, base_title.contentModel, base_title.text, true end end end -- Content models have overriding priority, as they can appear in -- nonstandard places due to page content model changes. if content_model == "css" or content_model == "sanitized-css" then return get_snippet_subtypes(title, "stylesheet", documentation) elseif content_model == "javascript" then return get_snippet_subtypes(title, "script", documentation) elseif content_model == "json" then return get_snippet_subtypes(title, "JSON data", documentation) elseif content_model == "MassMessageListContent" then return get_snippet_subtypes(title, "mass message delivery list", documentation) -- Modules. elseif content_model == "Scribunto" then return get_transclusion_subtypes(title, "module", documentation, false) elseif content_model == "text" then return "page" -- ??? -- Otherwise, the content model is "wikitext", so check namespaces. elseif title.isTalkPage then return "talk page" end local ns = title.namespace -- Main namespace. if ns == 0 then return "entry" -- Wiktionary: elseif ns == 4 then return find_sandbox(title.text) and "sandbox" or "project page" -- Template: elseif ns == 10 then return get_transclusion_subtypes(title, "template", documentation, false) end -- Convert the namespace to lowercase, unless it contains a capital -- letter after the initial letter (e.g. MediaWiki, TimedText). Also -- normalize any underscores. local ns_text = gsub(title.nsText, "_", " ") if ufind(ns_text, "^%U*$", 2) then ns_text = ulower(ns_text) end -- User: if ns == 2 then return ns_text .. " " .. (title.isSubpage and "subpage" or "page") -- Category: and Appendix: elseif ns == 14 or ns == 100 then return ns_text -- Thesaurus: and Reconstruction: elseif ns == 110 or ns == 118 then return ns_text .. " entry" end return ns_text .. " page" end get_pagetype = export.get_pagetype end --[==[ Returns {true} if the input title object is for a content page, or {false} if not. A content page is a page that is considered part of the dictionary itself, and excludes pages for discussion, administration, maintenance etc.]==] function export.is_content_page(title) if not is_internal_title(title) then error(mw.dumpObject(title.fullText) .. " is not a valid page name.") end local ns = title.namespace -- (main), Appendix, Thesaurus, Citations, Reconstruction. return (ns == 0 or ns == 100 or ns == 110 or ns == 114 or ns == 118) and title.contentModel == "wikitext" end --[==[ Returns {true} if the input title object is for a documentation page, or {false} if not.]==] function export.is_documentation(title) return match(get_pagetype(title), "%f[%w]documentation%f[%W]") and true or false end --[==[ Returns {true} if the input title object is for a sandbox, or {false} if not. By default, sandbox documentation pages are excluded, but this can be overridden with the `include_documentation` parameter.]==] function export.is_sandbox(title, include_documentation) local pagetype = get_pagetype(title) return match(pagetype, "%f[%w]sandbox%f[%W]") and ( include_documentation or not match(pagetype, "%f[%w]documentation%f[%W]") ) and true or false end --[==[ Returns {true} if the input title object is for a testcase page, or {false} if not. By default, testcase documentation pages are excluded, but this can be overridden with the `include_documentation` parameter.]==] function export.is_testcase_page(title, include_documentation) local pagetype = get_pagetype(title) return match(pagetype, "%f[%w]testcase%f[%W]") and ( include_documentation or not match(pagetype, "%f[%w]documentation%f[%W]") ) and true or false end --[==[ Returns the namespace shortcut for the input title object, or else the namespace text. For example, a `Template:` title returns {"T"}, a `Module:` title returns {"MOD"}, and a `User:` title returns {"User"}.]==] function export.get_namespace_shortcut(title) return (namespace_shortcuts or get_namespace_shortcuts())[title.namespace] or title.nsText end get_namespace_shortcut = export.get_namespace_shortcut do local function check_level(lvl) if type(lvl) ~= "number" then error("Heading levels must be numbers.") elseif lvl < 1 or lvl > 6 or lvl % 1 ~= 0 then error("Heading levels must be integers between 1 and 6.") end return lvl end --[==[ A helper function which iterates over the headings in `text`, which should be the content of a page or (main) section. Each iteration returns three values: `sec` (the section title), `lvl` (the section level) and `loc` (the index of the section in the given text, from the first equals sign). The section title will be automatically trimmed, and any HTML entities will be resolved. The optional parameter `a` (which should be an integer between 1 and 6) can be used to ensure that only headings of the specified level are iterated over. If `b` is also given, then they are treated as a range. The optional parameters `a` and `b` can be used to specify a range, so that only headings with levels in that range are returned.]==] local function find_headings(text, a, b) a = a and check_level(a) or nil b = b and check_level(b) or a or nil local start, loc, lvl, sec = 1 return function() repeat loc, lvl, sec, start = match(text, "()%f[^%z\n](==?=?=?=?=?)([^\n]+)%2[\t ]*%f[%z\n]()", start) lvl = lvl and #lvl until not (sec and a) or (lvl >= a and lvl <= b) return sec and trim(decode_entities(sec)) or nil, lvl, loc end end local function _get_section(content, name, level) if not (content and name) then return nil elseif find(name, "\n", 1, true) then error("Heading name cannot contain a newline.") end level = level and check_level(level) or nil name = trim(decode_entities(name)) local start for sec, lvl, loc in find_headings(content, level and 1 or nil, level) do if start and lvl <= level then return sub(content, start, loc - 1) elseif not start and (not level or lvl == level) and sec == name then start, level = loc, lvl end end return start and sub(content, start) end --[==[ A helper function to return the content of a page section. `content` is raw wikitext, `name` is the requested section, and `level` is an optional parameter that specifies the required section heading level. If `level` is not supplied, then the first section called `name` is returned. `name` can either be a string or table of section names. If a table, each name represents a section that has the next as a subsection. For example, { {"Spanish", "Noun"}} will return the first matching section called "Noun" under a section called "Spanish". These do not have to be at adjacent levels ("Noun" might be L4, while "Spanish" is L2). If `level` is given, it refers to the last name in the table (i.e. the name of the section to be returned). The returned section includes all of its subsections. If no matching section is found, return {nil}.]==] function export.get_section(content, names, level) if type(names) ~= "table" then return _get_section(content, names, level) end local i = 1 local name = names[i] if not name then error("Must specify at least 1 section.") end while true do local nxt_i = i + 1 local nxt = names[nxt_i] if nxt == nil then return _get_section(content, name, level) end content = _get_section(content, name) if content == nil then return nil elseif i == 6 then error("Not possible specify more than 6 sections: headings only go up to level 6.") end i = nxt_i name = names[i] end return content end end do local current_section --[==[ A function which returns the number of the page section which contains the current {#invoke}.]==] function export.get_current_section() if current_section ~= nil then return current_section end local extension_tag = (current_frame or get_current_frame()).extensionTag -- We determine the section via the heading strip marker count, since they're numbered sequentially, but the only way to do this is to generate a fake heading via frame:preprocess(). The native parser assigns each heading a unique marker, but frame:preprocess() will return copies of older markers if the heading is identical to one further up the page, so the fake heading has to be unique to the page. The best way to do this is to feed it a heading containing a nowiki marker (which we will need later), since those are always unique. local nowiki_marker = extension_tag(current_frame, "nowiki") -- Note: heading strip markers have a different syntax to the ones used for tags. local h = tonumber(match( current_frame:preprocess("=" .. nowiki_marker .. "="), "\127'\"`UNIQ%-%-h%-(%d+)%-%-QINU`\"'\127" )) -- For some reason, [[Special:ExpandTemplates]] doesn't generate a heading strip marker, so if that happens we simply abort early. if not h then return 0 end -- The only way to get the section number is to increment the heading count, so we store the offset in nowiki strip markers which can be retrieved by procedurally unstripping nowiki markers, counting backwards until we find a match. local n, offset = tonumber(match( nowiki_marker, "\127'\"`UNIQ%-%-nowiki%-([%dA-F]+)%-QINU`\"'\127" ), 16) while not offset and n > 0 do n = n - 1 offset = match( unstrip_nowiki(format("\127'\"`UNIQ--nowiki-%08X-QINU`\"'\127", n)), "^HEADING\1(%d+)" -- Prefix "HEADING\1" prevents collisions. ) end offset = offset and (offset + 1) or 0 extension_tag(current_frame, "nowiki", "HEADING\1" .. offset) current_section = h - offset return current_section end get_current_section = export.get_current_section end do local L2_sections local function get_L2_sections() L2_sections, get_L2_sections = mw.loadData("Module:headword/data").page.L2_sections, nil return L2_sections end --[==[ A function which returns the name of the L2 language section which contains the current {#invoke}.]==] function export.get_current_L2() local section = get_current_section() if section == 0 then return end while section > 0 do local L2 = (L2_sections or get_L2_sections())[section] if L2 then return L2 end section = section - 1 end end end return export fahzb5v4u71j961eqb048ciy8nk4h06 218848 218847 2025-06-20T00:57:25Z Sponge2490 8927 Membatalkan semakan [[Special:Diff/218847|218847]] oleh [[Special:Contributions/Sponge2490|Sponge2490]] ([[User talk:Sponge2490|perbincangan]]) Ralat 218848 Scribunto text/plain local require = require local require_when_needed = require("Module:require when needed") local decode_entities = require_when_needed("Module:string utilities", "decode_entities") local find = string.find local format = string.format local get_current_section -- Defined below. local gsub = string.gsub local is_valid_title -- Defined below. local lower = string.lower local match = string.match local new_title = mw.title.new local sub = string.sub local tonumber = tonumber local trim = require_when_needed("Module:string utilities", "trim") local type = type local unstrip_nowiki = mw.text.unstripNoWiki local export = {} --[==[ Returns true if the title object is a valid title that is not an interwiki link.]==] function export.is_valid_title(title) -- Note: Mainspace titles starting with "#" should be invalid, but a bug in mw.title.new and mw.title.makeTitle means a title object is returned that has the empty string for prefixedText, so they need to be filtered out. return title and #title.prefixedText > 0 and #title.interwiki == 0 end is_valid_title = export.is_valid_title --[==[ Returns true if `pagename` is a valid page title that is not an interwiki link.]==] function export.is_valid_page_name(pagename) return is_valid_title(new_title(pagename)) end do -- Any template/module with "sandbox" in the title. These are impossible -- to screen for more accurately, as there's no consistent pattern. Also -- any user sandboxes in the form (e.g.) "Template:User:...". local function is_sandbox(text) return (find(lower(text), "sandbox", 1, true) or sub(text, 1, 5) == "Pengguna:") and true or false end -- Any template/module documentation pages. local function is_documentation(text) return match(text, "./doc$") and true or false end -- Any template/module testcases (which can be labelled and/or followed by -- further subpages). local function is_testcase_page(text) return match(text, "./[Tt]estcases?%f[%L]") and true or false end --[==[ Returns the page type of `title` in a format which can be used in running text.]==] function export.pagetype(title) if not is_valid_title(title) then error(mw.dumpObject(title.fullText) .. " is not a valid page name.") end -- Content models have overriding priority, as they can appear in -- nonstandard places due to page content model changes. local content_model = title.contentModel if content_model == "css" or content_model == "sanitized-css" then return "stylesheet" elseif content_model == "javascript" then return "script" elseif content_model == "json" then return "JSON data page" elseif content_model == "MassMessageListContent" then return "mass message delivery list" -- Modules. elseif content_model == "Scribunto" then local title_text = title.text if is_sandbox(title_text) then return "module sandbox" elseif is_testcase_page(title_text) then return "module testcase page" end return "module" elseif content_model == "text" then return "page" -- ??? -- Otherwise, the content model is "wikitext", so check namespaces. elseif title.isTalkPage then return "talk page" end local ns = title.namespace -- Main namespace. if ns == 0 then return "entry" -- Wiktionary: elseif ns == 4 then return "project page" -- MediaWiki: and TimedText: elseif ns == 8 or ns == 710 then return title.nsText .. " page" elseif ns == 10 then local title_text = title.text if is_sandbox(title_text) then return "template sandbox" elseif is_documentation(title_text) then return "template documentation page" elseif is_testcase_page(title_text) then return "template testcase page" end return "template" -- Any non-Scribunto pages in the Module: space (which will almost -- always be documentation subpages). Any remaining will get default -- handling as "module pages". elseif ns == 828 then local title_text = title.text if is_sandbox(title_text) then return "module sandbox" elseif is_documentation(title_text) then return "module documentation page" end end local ns_text = lower(title.nsText) -- Category: and Appendix: if ns == 14 or ns == 100 then return ns_text -- Thesaurus: and Reconstruction: elseif ns == 110 or ns == 118 then return ns_text .. " entry" end return gsub(ns_text, "_", " ") .. " page" end end do local function check_level(lvl) if type(lvl) ~= "number" then error("Heading levels must be numbers.") elseif lvl < 1 or lvl > 6 or lvl % 1 ~= 0 then error("Heading levels must be integers between 1 and 6.") end return lvl end --[==[ A helper function which iterates over the headings in `text`, which should be the content of a page or (main) section. Each iteration returns three values: `sec` (the section title), `lvl` (the section level) and `loc` (the index of the section in the given text, from the first equals sign). The section title will be automatically trimmed, and any HTML entities will be resolved. The optional parameter `a` (which should be an integer between 1 and 6) can be used to ensure that only headings of the specified level are iterated over. If `b` is also given, then they are treated as a range. The optional parameters `a` and `b` can be used to specify a range, so that only headings with levels in that range are returned. If only `a` is given ... ]==] local function find_headings(text, a, b) a = a and check_level(a) or nil b = b and check_level(b) or a or nil local start, loc, lvl, sec = 1 return function() repeat loc, lvl, sec, start = match(text, "()%f[^%z\n](==?=?=?=?=?)([^\n]+)%2[\t ]*%f[%z\n]()", start) lvl = lvl and #lvl until not (sec and a) or (lvl >= a and lvl <= b) return sec and trim(decode_entities(sec)) or nil, lvl, loc end end local function _get_section(content, name, level) if not (content and name) then return nil elseif find(name, "\n", 1, true) then error("Heading name cannot contain a newline.") end level = level and check_level(level) or nil name = trim(decode_entities(name)) local start for sec, lvl, loc in find_headings(content, level and 1 or nil, level) do if start and lvl <= level then return sub(content, start, loc - 1) elseif not start and (not level or lvl == level) and sec == name then start, level = loc, lvl end end return start and sub(content, start) end --[==[ A helper function to return the content of a page section. `content` is raw wikitext, `name` is the requested section, and `level` is an optional parameter that specifies the required section heading level. If `level` is not supplied, then the first section called `name` is returned. `name` can either be a string or table of section names. If a table, each name represents a section that has the next as a subsection. For example, { {"Spanish", "Noun"}} will return the first matching section called "Noun" under a section called "Spanish". These do not have to be at adjacent levels ("Noun" might be L4, while "Spanish" is L2). If `level` is given, it refers to the last name in the table (i.e. the name of the section to be returned). The returned section includes all of its subsections. If no matching section is found, return {nil}. ]==] function export.get_section(content, names, level) if type(names) ~= "table" then return _get_section(content, names, level) end local i = 1 local name = names[i] if not name then error("Must specify at least 1 section.") end while true do local nxt_i = i + 1 local nxt = names[nxt_i] if nxt == nil then return _get_section(content, name, level) end content = _get_section(content, name) if content == nil then return nil elseif i == 6 then error("Not possible specify more than 6 sections: headings only go up to level 6.") end i = nxt_i name = names[i] end return content end end do local current_section --[==[ A function which returns the number of the page section which contains the current {#invoke}. ]==] function export.get_current_section() if current_section then return current_section end local frame = mw.getCurrentFrame() local extension_tag = frame.extensionTag -- We determine the section via the heading strip marker count, since they're numbered sequentially, but the only way to do this is to generate a fake heading via frame:preprocess(). The native parser assigns each heading a unique marker, but frame:preprocess() will return copies of older markers if the heading is identical to one further up the page, so the fake heading has to be unique to the page. The best way to do this is to feed it a heading containing a nowiki marker (which we will need later), since those are always unique. local nowiki_marker = extension_tag(frame, "nowiki") -- Note: heading strip markers have a different syntax to the ones used for tags. local h = tonumber(match( frame:preprocess("=" .. nowiki_marker .. "="), "\127'\"`UNIQ%-%-h%-(%d+)%-%-QINU`\"'\127" )) -- For some reason, [[Special:ExpandTemplates]] doesn't generate a heading strip marker, so if that happens we simply abort early. if not h then return 0 end -- The only way to get the section number is to increment the heading count, so we store the offset in nowiki strip markers which can be retrieved by procedurally unstripping nowiki markers, counting backwards until we find a match. local n, offset = tonumber(match( nowiki_marker, "\127'\"`UNIQ%-%-nowiki%-([%dA-F]+)%-QINU`\"'\127" ), 16) while not offset and n > 0 do n = n - 1 offset = match( unstrip_nowiki(format("\127'\"`UNIQ--nowiki-%08X-QINU`\"'\127", n)), "^HEADING\1(%d+)" -- Prefix "HEADING\1" prevents collisions. ) end offset = offset and (offset + 1) or 0 extension_tag(frame, "nowiki", "HEADING\1" .. offset) current_section = h - offset return current_section end get_current_section = export.get_current_section end do local L2_sections --[==[ A function which returns the name of the L2 language section which contains the current {#invoke}. ]==] function export.get_current_L2() local section = get_current_section() if section == 0 then return end L2_sections = L2_sections or mw.loadData("Module:headword/data").page.L2_sections while section > 0 do local L2 = L2_sections[section] if L2 then return L2 end section = section - 1 end end end return export acr7fss28efekbh2ifbr49y2erogs5u Modul:string/patternEscape 828 75062 218838 2025-06-19T23:30:10Z Sponge2490 8927 Mencipta [[Modul:string/patternEscape]] 218838 Scribunto text/plain local gsub = string.gsub local chars local function get_chars() chars, get_chars = { ["\000"] = "%z", ["$"] = "%$", ["%"] = "%%", ["("] = "%(", [")"] = "%)", ["*"] = "%*", ["+"] = "%+", ["-"] = "%-", ["."] = "%.", ["?"] = "%?", ["["] = "%[", ["]"] = "%]", ["^"] = "%^", }, nil return chars end --[==[Escapes the magic characters used in a pattern: {$%()*+-.?[]^}, and converts the null character to {%z}. For example, {"^$()%.[]*+-?\0"} becomes {"%^%$%(%)%%%.%[%]%*%+%-%?%z"}. This is necessary when constructing a pattern involving arbitrary text (e.g. from user input).]==] return function(str) return (gsub(str, "[%z$%%()*+%-.?[%]^]", chars or get_chars())) end kdhwp5dohwvh931huz7m0oufqqh05wl Modul:string/replacementEscape 828 75063 218839 2025-06-19T23:35:02Z Sponge2490 8927 Mencipta [[Modul:string/replacementEscape]] 218839 Scribunto text/plain local gsub = string.gsub --[==[Escapes {%}, which is the only magic character used in replacement strings, which are given as the third argument to {string.gsub} and {mw.ustring.gsub}, as well as format strings given to {string.format} and {mw.ustring.format}.]==] return function(str) return (gsub(str, "%%", "%%%%")) end aid90he3azqkc4qrytnczmfsjczbfe3 Modul:table/deepCopy 828 75064 218841 2025-06-19T23:44:11Z Sponge2490 8927 Mencipta [[Modul:table/deepCopy]] 218841 Scribunto text/plain local debug_track_module = "Module:debug/track" local dump = mw.dumpObject local error = error local getmetatable = getmetatable local next = next local pairs = pairs local rawget = rawget local type = type local setmetatable = setmetatable local function debug_track(...) debug_track = require(debug_track_module) return debug_track(...) end local tracked local function make_copy(orig, seen, mt_flag, keep_loaded_data) local mt, iter, state, init = getmetatable(orig) -- If `mt` is nil, just use `next`, as it's faster. if mt == nil then iter, state, init = next, orig, nil -- `mt` could be a non-table if `__metatable` has been used, but discard it in such cases. elseif type(mt) ~= "table" then mt, iter, state, init = nil, pairs(orig) -- Data loaded via `mw.loadData`, which sets the key "mw_loadData" to true in the metatable. elseif rawget(mt, "mw_loadData") == true then if keep_loaded_data then seen[orig] = orig return orig -- Track instances of such data being copied, which is very inefficient and usually unnecessary. elseif not tracked then debug_track("table/deepCopy/loaded data") tracked = true end -- Discard the metatable and use the `__pairs` metamethod. mt, iter, state, init = nil, pairs(orig) -- If `mt_flag` is "none", discard the metatable and use the `__pairs` metamethod. elseif mt_flag == "none" then mt, iter, state, init = nil, pairs(orig) -- Otherwise, keep `mt` and use `next` to copy the raw contents. else iter, state, init = next, orig, nil end local copy = {} seen[orig] = copy for k, v in iter, state, init do if k and type(k) == "table" then k = seen[k] or make_copy(k, seen, mt_flag, keep_loaded_data) end if v and type(v) == "table" then v = seen[v] or make_copy(v, seen, mt_flag, keep_loaded_data) end copy[k] = v end if mt == nil or mt_flag == "none" then return copy -- Copy the metatable if `mt_flag` is "copy"; otherwise, it will be "keep", so keep it. elseif mt_flag == "copy" then mt = seen[mt] or make_copy(mt, seen, mt_flag, keep_loaded_data) end return setmetatable(copy, mt) end --[==[ Recursive deep copy function. Preserves copied identities of subtables. A more powerful version of {mw.clone}, with customizable options. * `metatableFlag` can be one of three options: *# "none" (the default): `pairs` will be used to copy the table, meaning that any `__pairs` metamethod will be used to copy the table, if available; the resulting table will not have a metatable. *# "copy": a raw copy of the table will be made (i.e. any `__pairs` metamethod will be ignored), and the copy will be given a copy of the original table's metatable; this ensures that nothing from the original is retained, but may cause metamethods to behave unexpectedly, depending on their implementation. *# "keep": a raw copy of the table will be made (i.e. any `__pairs` metamethod will be ignored), and the copy will be given the original table's metatable; this is useful when copying objects that inherit methods from a prototype object (e.g. language objects). * If `keepLoadedData` is true, then any data loaded via {mw.loadData} will not be copied, and the original will be used instead. This is useful in iterative contexts where it is necessary to copy data being destructively modified, because objects loaded via mw.loadData are immutable. * Notes: *# Protected metatables will not be copied (i.e. those hidden behind a `__metatable` metamethod), as they are not accessible by Lua's design. Instead, the output of the `__metatable` method will be used instead. *# Data loaded via {mw.loadData} is always treated as though the "none" flag is set, because the way it has been implemented causes errors to be thrown if "copy" or "keep" are used with it.]==] return function(orig, metatableFlag, keepLoadedData) if metatableFlag == nil then metatableFlag = "none" elseif not (metatableFlag == "keep" or metatableFlag == "copy" or metatableFlag == "none") then error('metatableFlag must be "none", "copy", "keep" or nil; received ' .. dump(metatableFlag)) end if orig and type(orig) == "table" then return make_copy(orig, {}, metatableFlag, keepLoadedData) end return orig end n283xd4cxzrnpyf4zrlt9334gjwqw59 Modul:table/getNested 828 75065 218842 2025-06-19T23:48:51Z Sponge2490 8927 Mencipta [[Modul:table/getNested]] 218842 Scribunto text/plain local error = error local select = select --[==[ Given a table and an arbitrary number of keys, will successively access subtables using each key in turn, returning the value at the final key. For example, if {t} is { {[1] = {[2] = {[3] = "foo"}}}}, {export.getNested(t, 1, 2, 3)} will return {"foo"}. If no subtable exists for a given key value, returns nil, but will throw an error if a non-table is found at an intermediary key.]==] return function(...) local n = select("#", ...) if n < 2 then error("Must provide a table and at least one key.") end local t, k = ... for i = 3, n do local v = t[k] if v == nil then return nil end t, k = v, select(i, ...) end return t[k] end tm1q0pycz7xr0ute9n4h4yhpf1jzo33 Modul:table/setNested 828 75066 218843 2025-06-19T23:50:58Z Sponge2490 8927 Mencipta [[Modul:table/setNested]] 218843 Scribunto text/plain local error = error local select = select --[==[ Given a table, value and an arbitrary number of keys, will successively access subtables using each key in turn, and sets the value at the final key. For example, if {t} is { {} }, {export.setNested(t, "foo", 1, 2, 3)} will modify {t} to { {[1] = {[2] = {[3] = "foo"} } } }. If no subtable exists for a given key value, one will be created, but the function will throw an error if a non-table value is found at an intermediary key. Note: the parameter order (table, value, keys) differs from functions like rawset, because the number of keys can be arbitrary. This is to avoid situations where an additional argument must be appended to arbitrary lists of variables, which can be awkward and error-prone: for example, when handling variable arguments ({...}) or function return values.]==] return function(...) local n = select("#", ...) if n < 3 then error("Must provide a table, value and at least one key.") end local t, v, k = ... for i = 4, n do local next_t = t[k] if next_t == nil then -- If there's no next table while setting nil, there's nothing more -- to do. if v == nil then return end next_t = {} t[k] = next_t end t, k = next_t, select(i, ...) end t[k] = v end 1jxfjipchypy8qfjkmtb9b9sal1bcc1 muddal 0 75067 218849 2025-06-20T03:21:03Z 180.195.212.239 Mencipta laman baru dengan kandungan '==Bahasa Suluk== ===Takrifan=== ====Kata nama==== {{inti|tsg|kata nama}} # [[modal]] #: {{syn|tsg|puun}} ===Etimologi=== {{bor+|tsg|ms|modal}}, daripada {{der|tsg|ta|முதல்}}.' 218849 wikitext text/x-wiki ==Bahasa Suluk== ===Takrifan=== ====Kata nama==== {{inti|tsg|kata nama}} # [[modal]] #: {{syn|tsg|puun}} ===Etimologi=== {{bor+|tsg|ms|modal}}, daripada {{der|tsg|ta|முதல்}}. 888ygqfk02x9tnp5h9s3d5jq9q29aht