Module:Citation/CS1/Configuration: Difference between revisions
From Vigyanwiki
(bump s2cid;) |
m (1 revision imported) |
||
| (3 intermediate revisions by 3 users not shown) | |||
| Line 1: | Line 1: | ||
local lang_obj = mw.language.getContentLanguage(); -- make a language object for the local language; used here for languages and dates | local lang_obj = mw.language.getContentLanguage(); -- make a language object for the local language; used here for languages and dates | ||
--[[--------------------------< S E T T I N G S >-------------------------------------------------------------- | |||
boolean settings used to control various things. these setting located here to make them easy to find | |||
]] | |||
-- these settings local to this module only | |||
local local_digits_from_mediawiki = false; -- for i18n; when true, module fills date_names['local_digits'] from MediaWiki; manual fill required else; always false at en.wiki | |||
local local_date_names_from_mediawiki = false; -- for i18n; when true, module fills date_names['local']['long'] and date_names['local']['short'] from MediaWiki; | |||
-- manual translation required else; ; always false at en.wiki | |||
-- these settings exported to other modules | |||
local use_identifier_redirects = true; -- when true use redirect name for identifier label links; always true at en.wiki | |||
local local_lang_cat_enable = false; -- when true categorizes pages where |language=<local wiki's language>; always false at en.wiki | |||
local date_name_auto_xlate_enable = false; -- when true translates English month-names to the local-wiki's language month names; always false at en.wiki | |||
local date_digit_auto_xlate_enable = false; -- when true translates Western date digit to the local-wiki's language digits (date_names['local_digits']); always false at en.wiki | |||
--[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------ | --[[--------------------------< U N C A T E G O R I Z E D _ N A M E S P A C E S >------------------------------ | ||
| Line 34: | Line 52: | ||
['archived-dead'] = 'Archived from $1 on $2', | ['archived-dead'] = 'Archived from $1 on $2', | ||
['archived-live'] = '$1 from the original on $2', | ['archived-live'] = '$1 from the original on $2', | ||
['archived-unfit'] = 'Archived from the original on ', | ['archived-unfit'] = 'Archived from the original on ', | ||
['archived'] = 'Archived', | ['archived'] = 'Archived', | ||
| Line 48: | Line 65: | ||
['inset'] = '$1 inset', | ['inset'] = '$1 inset', | ||
['interview'] = 'Interviewed by $1', | ['interview'] = 'Interviewed by $1', | ||
['mismatch'] = '<code class="cs1-code">|$1=</code> / <code class="cs1-code">|$2=</code> mismatch', -- $1 is year param name; $2 is date param name | ['mismatch'] = '<code class="cs1-code">|$1=</code> / <code class="cs1-code">|$2=</code> mismatch', -- $1 is year param name; $2 is date param name | ||
['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]: $1', | ['newsgroup'] = '[[Usenet newsgroup|Newsgroup]]: $1', | ||
| Line 125: | Line 141: | ||
local citation_class_map_t = { -- TODO: if kept, these and all other config.CitationClass 'names' require some sort of i18n | local citation_class_map_t = { -- TODO: if kept, these and all other config.CitationClass 'names' require some sort of i18n | ||
['arxiv'] = 'arXiv', | |||
['audio-visual'] = 'AV media', | ['audio-visual'] = 'AV media', | ||
['AV-media-notes'] = 'AV media notes', | ['AV-media-notes'] = 'AV media notes', | ||
['biorxiv'] = 'bioRxiv', | |||
['citeseerx'] = 'CiteSeerX', | |||
['encyclopaedia'] = 'encyclopedia', | ['encyclopaedia'] = 'encyclopedia', | ||
['mailinglist'] = 'mailing list', | ['mailinglist'] = 'mailing list', | ||
['pressrelease'] = 'press release' | ['medrxiv'] = 'medRxiv', | ||
['pressrelease'] = 'press release', | |||
['ssrn'] = 'SSRN', | |||
['techreport'] = 'tech report', | |||
} | } | ||
| Line 275: | Line 297: | ||
['Issue'] = {'issue', 'number'}, | ['Issue'] = {'issue', 'number'}, | ||
['Language'] = {'language', 'lang'}, | ['Language'] = {'language', 'lang'}, | ||
['MailingList'] = {'mailing-list', 'mailinglist'}, -- cite mailing list only | ['MailingList'] = {'mailing-list', 'mailinglist'}, -- cite mailing list only | ||
['Map'] = 'map', -- cite map only | ['Map'] = 'map', -- cite map only | ||
| Line 326: | Line 344: | ||
['Title'] = 'title', -- Used by InternetArchiveBot | ['Title'] = 'title', -- Used by InternetArchiveBot | ||
['TitleLink'] = {'title-link', 'episode-link', 'episodelink'}, -- Used by InternetArchiveBot | ['TitleLink'] = {'title-link', 'episode-link', 'episodelink'}, -- Used by InternetArchiveBot | ||
['TitleNote'] = 'department', | ['TitleNote'] = {'title-note', 'department'}, | ||
['TitleType'] = {'type', 'medium'}, | ['TitleType'] = {'type', 'medium'}, | ||
['TransChapter'] = {'trans-article', 'trans-chapter', 'trans-contribution', | ['TransChapter'] = {'trans-article', 'trans-chapter', 'trans-contribution', | ||
| Line 332: | Line 350: | ||
['Transcript'] = 'transcript', | ['Transcript'] = 'transcript', | ||
['TranscriptFormat'] = 'transcript-format', | ['TranscriptFormat'] = 'transcript-format', | ||
['TranscriptURL'] = | ['TranscriptURL'] = 'transcript-url', -- Used by InternetArchiveBot | ||
['TransMap'] = 'trans-map', -- cite map only | ['TransMap'] = 'trans-map', -- cite map only | ||
['TransPeriodical'] = {'trans-journal', 'trans-magazine', 'trans-newspaper', | ['TransPeriodical'] = {'trans-journal', 'trans-magazine', 'trans-newspaper', | ||
| Line 347: | Line 365: | ||
['Year'] = 'year', | ['Year'] = 'year', | ||
['AuthorList-First'] = {"first#", "author-first#", "author#-first", "given#", | ['AuthorList-First'] = {"first#", "author-first#", "author#-first", "author-given#", "author#-given", | ||
" | "subject-first#", "subject#-first", "subject-given#", "subject#-given", | ||
['AuthorList-Last'] = {"last#", "author-last#", "author#-last", "surname#", | "given#"}, | ||
" | ['AuthorList-Last'] = {"last#", "author-last#", "author#-last", "author-surname#", "author#-surname", | ||
"subject-last#", "subject#-last", "subject-surname#", "subject#-surname", | |||
"author#", 'host#', "subject#", "surname#"}, | |||
['AuthorList-Link'] = {"author-link#", "author#-link", "subject-link#", | ['AuthorList-Link'] = {"author-link#", "author#-link", "subject-link#", | ||
"subject#-link", "authorlink#", "author#link"}, | "subject#-link", "authorlink#", "author#link"}, | ||
| Line 394: | Line 414: | ||
'AuthorList-Mask', 'ContributorList-Mask', 'EditorList-Mask', 'InterviewerList-Mask', 'TranslatorList-Mask', -- name-list mask may have name separators | 'AuthorList-Mask', 'ContributorList-Mask', 'EditorList-Mask', 'InterviewerList-Mask', 'TranslatorList-Mask', -- name-list mask may have name separators | ||
'PostScript', 'Quote', 'ScriptQuote', 'TransQuote', 'Ref', -- miscellaneous | 'PostScript', 'Quote', 'ScriptQuote', 'TransQuote', 'Ref', -- miscellaneous | ||
'ArchiveURL', 'ChapterURL', 'ConferenceURL | 'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'MapURL', 'TranscriptURL', 'URL', -- URL-holding parameters | ||
} | } | ||
local url_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value | local url_meta_params = { -- table of aliases[] keys (meta parameters); each key has a table of parameter names for a value | ||
'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'ID | 'ArchiveURL', 'ChapterURL', 'ConferenceURL', 'ID', 'MapURL', 'TranscriptURL', 'URL', -- parameters allowed to hold urls | ||
'Page', 'Pages', 'At', 'QuotePage', 'QuotePages', -- insource locators allowed to hold urls | 'Page', 'Pages', 'At', 'QuotePage', 'QuotePages', -- insource locators allowed to hold urls | ||
} | } | ||
| Line 617: | Line 637: | ||
date_names[invert_t[2]][i] = name; -- invert to get [i] = 'name' for conversions from ymd | date_names[invert_t[2]][i] = name; -- invert to get [i] = 'name' for conversions from ymd | ||
end | end | ||
end | |||
if local_digits_from_mediawiki then -- if fetching local digits from MediaWiki is enabled | |||
local digits_t = {}; | |||
for i=0, 9 do -- loop 10x and | |||
digits_t [lang_obj:formatNum (i)] = tostring (i); -- format the loop indexer as local lang table index and assign loop indexer (a string) as the value | |||
end | |||
date_names['local_digits'] = digits_t; | |||
end | end | ||
| Line 638: | Line 666: | ||
'{{ *([Mm]DY) *[|}]', -- 0 | '{{ *([Mm]DY) *[|}]', -- 0 | ||
} | } | ||
local title_object = mw.title.getCurrentTitle(); | |||
local content; -- done this way so that unused templates appear in unused-template-reports; self-transcluded makes them look like they are used | |||
if 10 ~= title_object.namespace then -- all namespaces except Template | |||
content = title_object:getContent() or ''; -- get the content of the article or ''; new pages edited w/ve do not have 'content' until saved; ve does not preview; phab:T221625 | |||
end | |||
local function get_date_format () | local function get_date_format () | ||
-- if title_object.namespace == 10 then -- not in template space so that unused templates appear in unused-template-reports; | |||
if not content then -- nil content when we're in template | |||
return nil; -- auto-formatting does not work in Template space so don't set global_df | return nil; -- auto-formatting does not work in Template space so don't set global_df | ||
end | end | ||
for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects | for _, pattern in ipairs (df_template_patterns) do -- loop through the patterns looking for {{Use dmy dates}} or {{Use mdy dates}} or any of their redirects | ||
local start, _, match = content:find(pattern); -- match is the three letters indicating desired date format | local start, _, match = content:find(pattern); -- match is the three letters indicating desired date format | ||
if match then | if match then | ||
local use_dates_template = content:match ('%b{}', start); -- get the whole template | |||
if | if use_dates_template:match ('| *cs1%-dates *= *[lsy][sy]?') then -- look for |cs1-dates=publication date length access-/archive-date length | ||
return match:lower() .. '-' .. | return match:lower() .. '-' .. use_dates_template:match ('| *cs1%-dates *= *([lsy][sy]?)'); | ||
else | else | ||
return match:lower() .. '-all'; -- no |cs1-dates= k/v pair; return value appropriate for use in |df= | return match:lower() .. '-all'; -- no |cs1-dates= k/v pair; return value appropriate for use in |df= | ||
| Line 658: | Line 691: | ||
end | end | ||
local global_df; | local global_df; -- TODO: add this to <global_cs1_config_t>? | ||
| Line 850: | Line 883: | ||
--[[---------------------< S | --[[--------------------------< C S 1 _ C O N F I G _ G E T >-------------------------------------------------- | ||
fetch and validate values from {{cs1 config}} template to fill <global_cs1_config_t> | |||
no error messages; when errors are detected, the parameter value from {{cs1 config}} is blanked. | |||
Supports all parameters and aliases associated with the metaparameters: DisplayAuthors, DisplayContributors, | |||
DisplayEditors, DisplayInterviewers, DisplayTranslators, NameListStyle, and Mode. The DisplayWhatever metaparameters | |||
accept numeric values only (|display-authors=etal and the like is not supported). | |||
]] | ]] | ||
local | local global_cs1_config_t = {}; -- TODO: add value returned from get_date_format() to this table? | ||
local function get_cs1_config () | |||
-- if title_object.namespace == 10 then -- not in template space so that unused templates appear in unused-template-reports; | |||
if not content then -- nil content when we're in template | |||
return nil; -- auto-formatting does not work in Template space so don't set global_df | |||
end | |||
local start = content:find('{{ *[Cc][Ss]1 config *[|}]'); -- <start> is offset into <content> when {{cs1 config}} found; nil else | |||
if start then | |||
local cs1_config_template = content:match ('%b{}', start); -- get the whole template | |||
if not cs1_config_template then | |||
return nil; | |||
end | |||
Also here is a pattern that recognizes stripmarkers that begin and end with the | local params_t = mw.text.split (cs1_config_template:gsub ('^{{%s*', ''):gsub ('%s*}}$', ''), '%s*|%s*'); -- remove '{{' and '}}'; make a sequence of parameter/value pairs (split on the pipe) | ||
delete characters. The nowiki stripmarker is not an error but some others are | table.remove (params_t, 1); -- remove the template name because it isn't a parameter/value pair | ||
because the parameter values that include them become part of the template's | |||
metadata before stripmarker replacement. | local config_meta_params_t = {'DisplayAuthors', 'DisplayContributors', 'DisplayEditors', 'DisplayInterviewers', 'DisplayTranslators', 'NameListStyle', 'Mode'}; | ||
local meta_param_map_t = {}; -- list of accepted parameter names usable in {{cs1 config}} goes here | |||
]] | |||
for _, meta_param in ipairs (config_meta_params_t) do -- for i18n using <config_meta_params_t>, map template parameter names to their metaparameter equivalents | |||
local invisible_defs = { | if 'table' == type (aliases[meta_param]) then -- if <meta_param> is a sequence, | ||
del = '\127', -- used to distinguish between stripmarker and del char | for _, param in ipairs (aliases[meta_param]) do -- extract its contents | ||
zwj = '\226\128\141', -- used with capture because zwj may be allowed | meta_param_map_t[param] = meta_param; -- and add to <meta_param_map_t> | ||
} | end | ||
else | |||
local invisible_chars = { | meta_param_map_t[aliases[meta_param]] = meta_param; -- not a sequence so just add the parameter to <meta_param_map_t> | ||
{'replacement', '\239\191\189'}, -- U+FFFD, EF BF BD | end | ||
{'zero width joiner', '('.. invisible_defs.zwj .. ')'}, -- U+200D, E2 80 8D; capture because zwj may be allowed | end | ||
{'zero width space', '\226\128\139'}, -- U+200B, E2 80 8B | |||
{'hair space', '\226\128\138'}, -- U+200A, E2 80 8A | local keywords_t = {}; -- map valid keywords to their associate metaparameter; reverse form of <keyword_lists[key] for these metaparameters | ||
{'soft hyphen', '\194\173'}, -- U+00AD, C2 AD | for _, metaparam_t in ipairs ({{'NameListStyle', 'name-list-style'}, {'Mode', 'mode'}}) do -- only these metaparameter / keywords_lists key pairs | ||
{'horizontal tab', '\009'}, -- U+0009 (HT), 09 | for _, keyword in ipairs (keywords_lists[metaparam_t[2]]) do -- spin through the list of keywords | ||
{'line feed', '\010'}, -- U+000A (LF), 0A | keywords_t[keyword] = metaparam_t[1]; -- add [keyword] = metaparameter to the map | ||
{'no-break space', '\194\160'}, -- U+00A0 (NBSP), C2 A0 | end | ||
{'carriage return', '\013'}, -- U+000D (CR), 0D | end | ||
{'stripmarker', stripmarkers.any}, -- stripmarker; may or may not be an error; capture returns the stripmaker type | |||
{'delete', '('.. invisible_defs.del .. ')'}, -- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker | for _, param in ipairs (params_t) do -- spin through the {{cs1 config}} parameters and fill <global_cs1_config_t> | ||
{'C0 control', '[\000-\008\011\012\014-\031]'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D)) | local k, v = param:match ('([^=]-)%s*=%s*(.+)'); -- <k> is the parameter name; <v> is parameter's assigned value | ||
{'C1 control', '[\194\128-\194\159]'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F | if k then | ||
-- {'Specials', '[\239\191\185-\239\191\191]'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF | if k:find ('^display') then -- if <k> is one of the |display-<namelist>= parameters | ||
-- {'Private use area', '[\238\128\128-\239\163\191]'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF | if v:match ('%d+') then -- the assigned value must be digits; doesn't accept 'etal' | ||
-- {'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD | global_cs1_config_t[meta_param_map_t[k]]=v; -- add the display param and its value to globals table | ||
-- {'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD | end | ||
else | |||
if keywords_t[v] == meta_param_map_t[k] then -- keywords_t[v] returns nil or the metaparam name; these must be the same | |||
global_cs1_config_t[meta_param_map_t[k]]=v; -- add the parameter and its value to globals table | |||
end | |||
end | |||
end | |||
end | |||
end | |||
end | |||
get_cs1_config (); -- fill <global_cs1_config_t> | |||
--[[---------------------< S T R I P M A R K E R S >---------------------------- | |||
Common pattern definition location for stripmarkers so that we don't have to go | |||
hunting for them if (when) MediaWiki changes their form. | |||
]] | |||
local stripmarkers = { | |||
['any'] = '\127[^\127]*UNIQ%-%-(%a+)%-[%a%d]+%-QINU[^\127]*\127', -- capture returns name of stripmarker | |||
['math'] = '\127[^\127]*UNIQ%-%-math%-[%a%d]+%-QINU[^\127]*\127' -- math stripmarkers used in coins_cleanup() and coins_replace_math_stripmarker() | |||
} | |||
--[[------------< I N V I S I B L E _ C H A R A C T E R S >--------------------- | |||
This table holds non-printing or invisible characters indexed either by name or | |||
by Unicode group. Values are decimal representations of UTF-8 codes. The table | |||
is organized as a table of tables because the Lua pairs keyword returns table | |||
data in an arbitrary order. Here, we want to process the table from top to bottom | |||
because the entries at the top of the table are also found in the ranges specified | |||
by the entries at the bottom of the table. | |||
Also here is a pattern that recognizes stripmarkers that begin and end with the | |||
delete characters. The nowiki stripmarker is not an error but some others are | |||
because the parameter values that include them become part of the template's | |||
metadata before stripmarker replacement. | |||
]] | |||
local invisible_defs = { | |||
del = '\127', -- used to distinguish between stripmarker and del char | |||
zwj = '\226\128\141', -- used with capture because zwj may be allowed | |||
} | |||
local invisible_chars = { | |||
{'replacement', '\239\191\189'}, -- U+FFFD, EF BF BD | |||
{'zero width joiner', '('.. invisible_defs.zwj .. ')'}, -- U+200D, E2 80 8D; capture because zwj may be allowed | |||
{'zero width space', '\226\128\139'}, -- U+200B, E2 80 8B | |||
{'hair space', '\226\128\138'}, -- U+200A, E2 80 8A | |||
{'soft hyphen', '\194\173'}, -- U+00AD, C2 AD | |||
{'horizontal tab', '\009'}, -- U+0009 (HT), 09 | |||
{'line feed', '\010'}, -- U+000A (LF), 0A | |||
{'no-break space', '\194\160'}, -- U+00A0 (NBSP), C2 A0 | |||
{'carriage return', '\013'}, -- U+000D (CR), 0D | |||
{'stripmarker', stripmarkers.any}, -- stripmarker; may or may not be an error; capture returns the stripmaker type | |||
{'delete', '('.. invisible_defs.del .. ')'}, -- U+007F (DEL), 7F; must be done after stripmarker test; capture to distinguish isolated del chars not part of stripmarker | |||
{'C0 control', '[\000-\008\011\012\014-\031]'}, -- U+0000–U+001F (NULL–US), 00–1F (except HT, LF, CR (09, 0A, 0D)) | |||
{'C1 control', '[\194\128-\194\159]'}, -- U+0080–U+009F (XXX–APC), C2 80 – C2 9F | |||
-- {'Specials', '[\239\191\185-\239\191\191]'}, -- U+FFF9-U+FFFF, EF BF B9 – EF BF BF | |||
-- {'Private use area', '[\238\128\128-\239\163\191]'}, -- U+E000–U+F8FF, EE 80 80 – EF A3 BF | |||
-- {'Supplementary Private Use Area-A', '[\243\176\128\128-\243\191\191\189]'}, -- U+F0000–U+FFFFD, F3 B0 80 80 – F3 BF BF BD | |||
-- {'Supplementary Private Use Area-B', '[\244\128\128\128-\244\143\191\189]'}, -- U+100000–U+10FFFD, F4 80 80 80 – F4 8F BF BD | |||
} | |||
--[[ | |||
Indic script makes use of zero width joiner as a character modifier so zwj | |||
characters must be left in. This pattern covers all of the unicode characters | |||
for these languages: | |||
Devanagari 0900–097F – https://unicode.org/charts/PDF/U0900.pdf | |||
Devanagari extended A8E0–A8FF – https://unicode.org/charts/PDF/UA8E0.pdf | |||
Bengali 0980–09FF – https://unicode.org/charts/PDF/U0980.pdf | |||
Gurmukhi 0A00–0A7F – https://unicode.org/charts/PDF/U0A00.pdf | |||
Gujarati 0A80–0AFF – https://unicode.org/charts/PDF/U0A80.pdf | |||
Oriya 0B00–0B7F – https://unicode.org/charts/PDF/U0B00.pdf | |||
Tamil 0B80–0BFF – https://unicode.org/charts/PDF/U0B80.pdf | |||
Telugu 0C00–0C7F – https://unicode.org/charts/PDF/U0C00.pdf | |||
Kannada 0C80–0CFF – https://unicode.org/charts/PDF/U0C80.pdf | |||
Malayalam 0D00–0D7F – https://unicode.org/charts/PDF/U0D00.pdf | |||
plus the not-necessarily Indic scripts for Sinhala and Burmese: | |||
Sinhala 0D80-0DFF - https://unicode.org/charts/PDF/U0D80.pdf | |||
Myanmar 1000-109F - https://unicode.org/charts/PDF/U1000.pdf | |||
Myanmar extended A AA60-AA7F - https://unicode.org/charts/PDF/UAA60.pdf | |||
Myanmar extended B A9E0-A9FF - https://unicode.org/charts/PDF/UA9E0.pdf | |||
the pattern is used by has_invisible_chars() and coins_cleanup() | |||
]] | |||
local indic_script = '[\224\164\128-\224\181\191\224\163\160-\224\183\191\225\128\128-\225\130\159\234\167\160-\234\167\191\234\169\160-\234\169\191]'; | |||
-- list of emoji that use a zwj character (U+200D) to combine with another emoji | |||
-- from: https://unicode.org/Public/emoji/15.0/emoji-zwj-sequences.txt; version: 15.0; 2022-05-06 | |||
-- table created by: [[:en:Module:Make emoji zwj table]] | |||
local emoji_t = { -- indexes are decimal forms of the hex values in U+xxxx | |||
[9760] = true, -- U+2620 ☠ skull and crossbones | |||
[9792] = true, -- U+2640 ♀ female sign | |||
[9794] = true, -- U+2642 ♂ male sign | |||
[9877] = true, -- U+2695 ⚕ staff of aesculapius | |||
[9878] = true, -- U+2696 ⚖ scales | |||
[9895] = true, -- U+26A7 ⚧ male with stroke and male and female sign | |||
[9992] = true, -- U+2708 ✈ airplane | |||
[10052] = true, -- U+2744 ❄ snowflake | |||
[10084] = true, -- U+2764 ❤ heavy black heart | |||
[11035] = true, -- U+2B1B ⬛ black large square | |||
[127752] = true, -- U+1F308 🌈 rainbow | |||
[127787] = true, -- U+1F32B 🌫 fog | |||
[127806] = true, -- U+1F33E 🌾 ear of rice | |||
[127859] = true, -- U+1F373 🍳 cooking | |||
[127868] = true, -- U+1F37C 🍼 baby bottle | |||
[127876] = true, -- U+1F384 🎄 christmas tree | |||
[127891] = true, -- U+1F393 🎓 graduation cap | |||
[127908] = true, -- U+1F3A4 🎤 microphone | |||
[127912] = true, -- U+1F3A8 🎨 artist palette | |||
[127979] = true, -- U+1F3EB 🏫 school | |||
[127981] = true, -- U+1F3ED 🏭 factory | |||
[128102] = true, -- U+1F466 👦 boy | |||
[128103] = true, -- U+1F467 👧 girl | |||
[128104] = true, -- U+1F468 👨 man | |||
[128105] = true, -- U+1F469 👩 woman | |||
[128139] = true, -- U+1F48B 💋 kiss mark | |||
[128168] = true, -- U+1F4A8 💨 dash symbol | |||
[128171] = true, -- U+1F4AB 💫 dizzy symbol | |||
[128187] = true, -- U+1F4BB 💻 personal computer | |||
[128188] = true, -- U+1F4BC 💼 brief case | |||
[128293] = true, -- U+1F525 🔥 fire | |||
[128295] = true, -- U+1F527 🔧 wrench | |||
[128300] = true, -- U+1F52C 🔬 microscope | |||
[128488] = true, -- U+1F5E8 🗨 left speech bubble | |||
[128640] = true, -- U+1F680 🚀 rocket | |||
[128658] = true, -- U+1F692 🚒 fire engine | |||
[129309] = true, -- U+1F91D 🤝 handshake | |||
[129455] = true, -- U+1F9AF 🦯 probing cane | |||
[129456] = true, -- U+1F9B0 🦰 emoji component red hair | |||
[129457] = true, -- U+1F9B1 🦱 emoji component curly hair | |||
[129458] = true, -- U+1F9B2 🦲 emoji component bald | |||
[129459] = true, -- U+1F9B3 🦳 emoji component white hair | |||
[ | |||