{"version":3,"file":"main.js","sources":["theme-9/virtual:init-settings","theme-9/virtual:theme","theme-9/discourse/lib/emoji-diversity.js","theme-9/discourse/components/ucd-warning.gjs","theme-9/discourse/components/modal/ucd-warning.gjs","theme-9/discourse/core/code-energy.js","theme-9/discourse/lib/boundaries.js","theme-9/discourse/core/sensitivity.js","theme-9/discourse/core/strip-ignored-content.js","theme-9/discourse/core/detect-code.js","theme-9/discourse/initializers/init.js","theme-9/discourse/services/ucd-state.js","theme-9/virtual:entrypoint:main"],"sourcesContent":["import { registerSettings } from \"discourse/lib/theme-settings-store\";\n\nregisterSettings(9, {\n  \"emoji_icon\": \"👩🏽‍💻\",\n  \"disable_at_trust_level\": -1,\n  \"sensitivity\": 0.5,\n  \"min_post_length_to_check\": 50,\n  \"max_post_length_to_check\": -1,\n  \"include_html\": true\n});\n","import { getObjectForTheme } from \"discourse/lib/theme-settings-store\";\n\nexport const settings = getObjectForTheme(9);\n\nexport function themePrefix(key) {\n  return `theme_translations.9.${key}`;\n}\n","const genderEmojiData = {\n  masc: {\n    adult: \"👨\",\n    child: \"👦\",\n    modifier: \"\\u200d♂\",\n  },\n  fem: {\n    adult: \"👩\",\n    child: \"👧\",\n    modifier: \"\\u200d♀\",\n  },\n  // no widespread support for most gender-neutral emoji sequences yet :(\n  // neutral: {\n  //   adult: \"🧑\",\n  //   child: \"🧒\",\n  //   modifier: \"\",\n  // },\n};\n\nconst randomGenderEmojiData = () => {\n  const genders = Object.values(genderEmojiData);\n\n  return genders[Math.floor(Math.random() * genders.length)];\n};\n\nconst emojiRegexes = Object.keys(Object.values(genderEmojiData)[0]).reduce(\n  (regexInfo, subStrType) => {\n    regexInfo[subStrType] = new RegExp(\n      Object.values(genderEmojiData)\n        .map((gender) => gender[subStrType])\n        .filter(Boolean)\n        .join(\"|\"),\n      \"g\"\n    );\n\n    return regexInfo;\n  },\n  {}\n);\n\nexport const randomizeEmojiGender = (emojis) =>\n  Object.entries(emojiRegexes).reduce(\n    (emoji, [subStrType, regex]) =>\n      emoji.replace(regex, () => randomGenderEmojiData()[subStrType]),\n    emojis\n  );\n\nconst MIN_SKIN_TONE_CODEPOINT = 0x1f3fb;\nconst MAX_SKIN_TONE_CODEPOINT = 0x1f3ff;\n\nexport const randomizeEmojiSkinTone = (emoji) =>\n  emoji.replace(/[\\u{1f3fb}-\\u{1f3ff}]/gu, () =>\n    String.fromCodePoint(\n      MIN_SKIN_TONE_CODEPOINT +\n        Math.floor(\n          Math.random() *\n            (MAX_SKIN_TONE_CODEPOINT - MIN_SKIN_TONE_CODEPOINT + 1)\n        )\n    )\n  );\n\nexport const randomizeEmojiDiversity = (emoji) =>\n  randomizeEmojiSkinTone(randomizeEmojiGender(emoji));\n","import Component from \"@glimmer/component\";\nimport { Input } from \"@ember/component\";\nimport { inject as controller } from \"@ember/controller\";\nimport { on } from \"@ember/modifier\";\nimport { action } from \"@ember/object\";\nimport { service } from \"@ember/service\";\nimport CookText from \"discourse/components/cook-text\";\nimport DButton from \"discourse/components/d-button\";\nimport { i18n } from \"discourse-i18n\";\n\nexport default class UcdWarning extends Component {\n  @service modal;\n  @service ucdState;\n\n  @controller composer;\n\n  get shouldPermanentlyDismiss() {\n    return this.ucdState.permanentlyDismissed ?? false;\n  }\n\n  @action\n  toggleShouldPermanentlyDismiss() {\n    this.ucdState.toggle();\n  }\n\n  @action\n  goBackAndFix() {\n    this.modal.close();\n  }\n\n  @action\n  ignoreAndProceed() {\n    this.modal.close();\n    this.composer.model.ucd_previousWarningIgnored = true;\n    this.composer.save();\n  }\n\n  <template>\n    <CookText @rawText={{i18n (themePrefix \"warning_modal.content\")}} />\n    <label for=\"ucd_do-not-show-again\" class=\"checkbox-label\">\n      <Input\n        @type=\"checkbox\"\n        id=\"ucd_do-not-show-again\"\n        name=\"ucd_do-not-show-again\"\n        @checked={{readonly this.shouldPermanentlyDismiss}}\n        {{on \"change\" this.toggleShouldPermanentlyDismiss}}\n      />\n      {{i18n (themePrefix \"warning_modal.do_not_show_again\")}}\n    </label>\n    <div class=\"action-buttons\">\n      <DButton\n        @action={{this.goBackAndFix}}\n        @icon=\"pencil\"\n        class=\"btn-primary\"\n        @label={{themePrefix \"warning_modal.fix_post\"}}\n      />\n      <DButton\n        @action={{this.ignoreAndProceed}}\n        @label={{themePrefix \"warning_modal.ignore_and_post_anyway\"}}\n      />\n    </div>\n  </template>\n}\n","import Component from \"@glimmer/component\";\nimport { action } from \"@ember/object\";\nimport { service } from \"@ember/service\";\nimport { htmlSafe } from \"@ember/template\";\nimport { escape } from \"pretty-text/sanitizer\";\nimport DModal from \"discourse/components/d-modal\";\nimport { emojiUnescape } from \"discourse/lib/text\";\nimport { i18n } from \"discourse-i18n\";\nimport { randomizeEmojiDiversity } from \"../../lib/emoji-diversity\";\nimport UcdWarning from \"../ucd-warning\";\n\nexport default class ModalUcdWarning extends Component {\n  @service ucdState;\n\n  get title() {\n    return htmlSafe(\n      [\n        emojiUnescape(escape(randomizeEmojiDiversity(settings.emoji_icon))),\n        escape(i18n(themePrefix(\"warning_modal.title\"))),\n      ].join(\" \")\n    );\n  }\n\n  @action\n  closeModal() {\n    if (this.args.model.ucd_shouldPermanentlyDismiss) {\n      this.ucdState.permanentlyDismiss();\n    }\n\n    this.args.closeModal();\n  }\n\n  <template>\n    <DModal\n      @closeModal={{this.closeModal}}\n      class=\"modal-ucd-warning\"\n      @title={{this.title}}\n      @inline={{@inline}}\n    >\n      <UcdWarning @onClose={{this.closeModal}} />\n    </DModal>\n  </template>\n}\n","const varNameStart = \"[$_a-zA-Z]\";\nconst varNameEnd = \"[$_a-zA-Z0-9]*\";\nconst varName = `${varNameStart}${varNameEnd}`;\nconst varFragment = `[$a-zA-Z]${varNameEnd}`; // no underscore at start\nconst xmlLikeName = \"[a-zA-Z-]+\";\nconst string = `(?:\"(?:[^\\\\n\"\\\\\\\\]|\\\\\\\\[^\\\\n])*\"|'(?:[^\\\\n'\\\\\\\\]|\\\\\\\\[^\\\\n])*')`;\n// adapted from http://wordaligned.org/articles/string-literals-and-regular-expressions\nconst numeric = \"-?(?:0|[1-9]\\\\d*)(?:\\\\.\\\\d+)?(?:[eE][+-]?\\\\d+)?\";\n// adapted from https://www.json.org/\nconst argument = `(?:${varName}|${string}|${numeric})`;\n// ignoring complex values due to complexity;\n// bools, `null`s, and `undefined`s are already matched based on varName\nconst argList = `(?:\\\\s*${argument}\\\\s*(?:,\\\\s*${argument}\\\\s*)*|\\\\s*)`;\n// matches 0 or more args; don't use on its own due to risk of infinite matches\n\n// enum\nexport const CodeEnergyLevels = {\n  Complex: \"Complex\",\n  High: \"High\",\n  Medium: \"Medium\",\n  Low: \"Low\",\n};\n\nexport const codeEnergyValues = {\n  [CodeEnergyLevels.Complex]: 1,\n  [CodeEnergyLevels.High]: 0.7,\n  [CodeEnergyLevels.Medium]: 0.3,\n  [CodeEnergyLevels.Low]: 0.1,\n};\n\nconst nonHtmlIndicators = [\n  `\\\\$${varName}`, // almost certain to be var name\n  `^\\\\s*\\\\.${xmlLikeName}`, // CSS class selectors\n  `:${varName}`, // Ruby symbol\n  // omitted: _varName starting with underscore (conflict with italics)\n  `${varFragment}(?:_${varFragment})+`, // snake_case\n  // ommitted: camelCase and spinal-case (too many false positives)\n  \"(?:^|\\\\s+)(?:\\\\/\\\\/|;)\", // single-line comment\n  // omitted: python-style `#` single-line comments and CSS ID selectors (conflict with md headings)\n  `\\\\/\\\\*[\\\\s\\\\S]+?\\\\*\\\\/`, // C-like multiline comment\n  `('''|\"\"\")[\\\\s\\\\S]+?\\\\1`, // Python-like multiline string/comment\n  \";\\\\s*$\", // trailing semicolon\n  `(?:${varName})?[$_a-z]\\\\(${argList}\\\\)`, // function call\n  // var name cannot end with uppercase to avoid `O(n)` false positive etc.\n  `${varName}\\\\[\\\\s*${argument}?\\\\s*\\\\]`, // array index\n  // omitted: object property (conflict with domain names, e.g. \"google.com\")\n  \"^\\\\s*[{}]\\\\s*$\", // curly brace and nothing else on a line\n  \"\\\\{\\\\{.+\\\\}\\\\}\", // templating languages e.g. Handlebars\n  \"[\\\\$#]\\\\{.+\\\\}\", // template string\n  \"&&|!=|>>|<<|::|\\\\+=|-=|\\\\*=|\\\\/=|\\\\|\\\\|=|\\\\?=|\\\\.\\\\?\", // various operators\n  // omitted: ++ (conflict with C++, Notepad++, etc.)\n  // omitted: || (conflict with empty table header row)\n  \"\\\\\\\\['\\\"ntr0\\\\\\\\]\", // common escape sequences\n  `<\\\\?[^>]*\\\\?>`, // PHP\n  `<%[^>]*%>`, // ERB (Rails)\n  \"0000-00-00T00:00:00\".split(\"0\").join(\"\\\\d\"), // ISO 8601 timestamps in logs\n  \"^\\\\s*at .+(.+)\", // common stack trace format\n  '^\\\\s*{\\\\s*\"[^\"]*\"\\\\s*:', // single-line JSON property\n];\n\nconst htmlIndicators = [\n  \"<!--[\\\\s\\\\S]*?-->\", // XML-like comment\n  `<${xmlLikeName}[^>]*\\\\/?>`, // XML-like start/empty tag\n  `</${xmlLikeName}>`, // XML-like end tag\n  \"&[0-9a-zA-Z]+;\", // HTML entity - human-readable\n  \"&#[0-9]{1,7};\", // HTML entity - decimal\n  \"&#x[0-9a-fA-F]{1,6};\", // HTML entity - hex\n];\n\nconst _codeEnergyIndicators = {\n  // multiple-character matches\n  [CodeEnergyLevels.Complex]: {\n    get indicators() {\n      return [nonHtmlIndicators, settings.include_html && htmlIndicators]\n        .filter(Boolean)\n        .flat();\n    },\n  },\n  // High code energy(almost always seen only in code and never in regular text, such as [)\n  [CodeEnergyLevels.High]: {\n    // TODO\n    indicators: [\n      // \"\\\\[\"\n    ],\n  },\n  // Medium code energy(usually seen in code but rarely in regular text, such as ;)\n  [CodeEnergyLevels.Medium]: {\n    // TODO\n    indicators: [\n      // \";\"\n    ],\n  },\n  // Low code energy(sometimes seen in code, but also seen with fair frequency in regular text, such as .)\n  [CodeEnergyLevels.Low]: {\n    // TODO\n    value: 0.1,\n    indicators: [\n      // \".\"\n    ],\n  },\n};\n\nexport const getCodeEnergyIndicators = () => {\n  return Object.entries(_codeEnergyIndicators)\n    .map(([key, { indicators }]) => {\n      return indicators.map((source) => ({\n        value: codeEnergyValues[key],\n        matcher: new RegExp(source, \"gm\"),\n      }));\n    })\n    .flat();\n};\n","export const getLineBoundaries = (str) => {\n  const lineBoundaries = [];\n\n  let cursor = -1;\n\n  do {\n    lineBoundaries.push({ start: cursor + 1 });\n\n    cursor = str.indexOf(\"\\n\", cursor + 1);\n\n    lineBoundaries[lineBoundaries.length - 1].end =\n      cursor === -1 ? str.length : cursor;\n\n    lineBoundaries[lineBoundaries.length - 1].content = str.slice(\n      lineBoundaries[lineBoundaries.length - 1].start,\n      lineBoundaries[lineBoundaries.length - 1].end\n    );\n  } while (cursor > -1);\n\n  return lineBoundaries;\n};\n\nexport const isBetween = (start, end) => (point) => {\n  return point >= start && point <= end;\n};\n","export const applySensitivity =\n  (sensitivity) => (leastSensitive, mostSensitive) =>\n    leastSensitive + sensitivity * (mostSensitive - leastSensitive);\n\nexport const sensitivityConfig = {\n  get complexMatchesToIgnore() {\n    return Math.round(applySensitivity(settings.sensitivity)(4, 0));\n  },\n\n  get minSequentialLinesToMatch() {\n    return Math.round(applySensitivity(settings.sensitivity)(5, 1));\n  },\n\n  get minTotalCodeEnergy() {\n    return Math.round(applySensitivity(settings.sensitivity)(5, 1));\n  },\n};\n","const ignoredContents = [\n  // properly formatted code\n  /(^([`~])\\2{2,})[^`~\\n]*\\n[\\s\\S]*?\\n\\1\\2*\\s*(?:\\n|$)/gm, // backtick-/tilde-fenced block\n  /(?:^|(?:\\n{2,}))\\s*(?:(?: {4}|\\t).*(?:\\n|$))/g, // indented block\n  // lack of `m` flag is intentional (`^` must match beginning of input, not line)\n\n  /`[^`\\n]+`/g, // inline backticks (must come after fenced code blocks)\n\n  /\\[([a-z]+).*?\\][\\s\\S]*?\\[\\/\\1\\]/gim, // BBCode tags\n\n  // URLs\n  /https?:\\/\\/(_\\([^() \\n\\t]+\\)|[^() \\n\\t])+/g, // parens/underscores\n  // for Wikipedia-style URLs\n\n  // emojis\n  /:[a-z_+-][a-z_0-9+-]*:/g, // descriptive style, e.g. :wink:, :stuck_out_tongue:\n  /:D|:-D|:\\)|:-\\)|;\\)|;-\\)|:\\(|:-\\(|:o|:-o|:\\?|:-\\?|:\\?\\?\\?:|8\\)|8-\\)|:x|:-x|:P|:-P|:!:|:\\?:|:\\||:-\\||^_^|^__^|:'\\(|:'-\\(|:-'\\(|:p|:O|:-O|:\\/|;P|;-P|:\\$|:-\\$/g, // emoticon style, e.g. ;), :-P\n  // per https://github.com/discourse/discourse/blob/dc6b547ed89f652b5406489d76140b76cf8e0d1d/script/import_scripts/phpbb3/support/smiley_processor.rb#L36-L63 and https://github.com/discourse/discourse/blob/0eeedf307a8f2a8e1ccd5b24dafbf5a7fd20e51e/lib/emoji/db.json#L7015-L7042\n\n  // misc\n  /\\((?:c|tm|r)\\)/gi, // copy/trademark/registered\n\n  // markdown links and images\n  /!?\\[[^\\]]+\\]\\([[^\\)]+\\)/g,\n\n  // mentions (Prefixed by non-word and terminated at word boundary)\n  /\\B@[\\w][\\w.-]{0,58}\\b/g,\n];\n\nexport const stripIgnoredContent = (content) => {\n  const strippedContent = ignoredContents.reduce((str, ignoredContent) => {\n    return str.replace(ignoredContent, \"\");\n  }, content);\n\n  return strippedContent;\n};\n","import { getLineBoundaries, isBetween } from \"../lib/boundaries\";\nimport {\n  CodeEnergyLevels,\n  codeEnergyValues,\n  getCodeEnergyIndicators,\n} from \"./code-energy\";\nimport { sensitivityConfig } from \"./sensitivity\";\nimport { stripIgnoredContent } from \"./strip-ignored-content\";\n\nexport const getCodeEnergy = (content) => {\n  let totalCodeEnergy = 0;\n  let totalComplexMatches = 0;\n\n  const lines = getLineBoundaries(content);\n\n  lines.forEach((x) => {\n    x.matches = 0;\n    x.matched_patterns = [];\n  });\n\n  for (const { matcher, value } of getCodeEnergyIndicators()) {\n    const matches = [...content.matchAll(matcher)];\n\n    totalCodeEnergy += matches.length * value;\n\n    if (value === codeEnergyValues[CodeEnergyLevels.Complex]) {\n      totalComplexMatches += matches.length;\n    }\n\n    for (const match of matches) {\n      const startIndex = match.index;\n      const endIndex = startIndex + match[0].length;\n\n      for (const line of lines) {\n        const isThisLine = isBetween(line.start, line.end);\n\n        if (\n          isThisLine(startIndex) ||\n          isThisLine(endIndex) ||\n          (line.start >= startIndex && line.end <= endIndex)\n        ) {\n          ++line.matches;\n          line.matched_patterns.push({ matcher, value });\n        }\n      }\n    }\n  }\n\n  return { totalCodeEnergy, totalComplexMatches, lines };\n};\n\nexport const numSequentialLinesWithThresholdCodeEnergy =\n  (threshold) => (lines) => {\n    let maxContiguous = 0;\n    let curContiguous = 0;\n\n    for (const line of lines) {\n      // empty/whitespace-only lines don't affect contiguity\n      if (!line.content.trim().length) {\n        continue;\n      }\n\n      if (line.matches >= threshold) {\n        ++curContiguous;\n      } else {\n        maxContiguous = Math.max(maxContiguous, curContiguous);\n        curContiguous = 0;\n      }\n    }\n\n    return Math.max(maxContiguous, curContiguous);\n  };\n\nexport const printDebugInfo = (content) => {\n  content = stripIgnoredContent(content);\n\n  const {\n    complexMatchesToIgnore,\n    minSequentialLinesToMatch,\n    minTotalCodeEnergy,\n  } = sensitivityConfig;\n\n  const { totalCodeEnergy, totalComplexMatches, lines } =\n    getCodeEnergy(content);\n\n  const debugTable = [];\n\n  let consecutive = 0;\n  lines.forEach((l) => {\n    if (!l.content.trim()) {\n      return;\n    }\n    if (l.matches) {\n      consecutive++;\n    } else {\n      consecutive = 0;\n    }\n    debugTable.push([\n      l.matches ? String(l.matches) : \"\",\n      consecutive ? String(consecutive) : \"\",\n      l.matched_patterns.length\n        ? `\\`${l.matched_patterns.map((p) => p.matcher).join(\"`, `\")}\\``\n        : \"\",\n      l.content,\n    ]);\n  });\n\n  const columns = [\"matches\", \"cumulative\", \"matched patterns\", \"content\"];\n  const dividers = columns.map(() => \"\");\n\n  columns.forEach((c, i) => {\n    const longest = Math.max(\n      c.length,\n      ...debugTable.map((row) => row[i].length)\n    );\n    debugTable.forEach((row) => (row[i] = row[i].padEnd(longest)));\n    columns[i] = c.padEnd(longest);\n    dividers[i] = dividers[i].padEnd(longest, \"-\");\n  });\n\n  debugTable.unshift(columns, dividers);\n\n  // eslint-disable-next-line no-console\n  console.log(debugTable.map((l) => `| ${l.join(\" | \")} |`).join(\"\\n\"));\n\n  // eslint-disable-next-line no-console\n  console.log(\"Result is \", { totalCodeEnergy, totalComplexMatches, lines });\n  // eslint-disable-next-line no-console\n  console.log(\"Sensitivity Config is \", {\n    complexMatchesToIgnore,\n    minSequentialLinesToMatch,\n    minTotalCodeEnergy,\n  });\n};\n\nconst detectCode = (content) => {\n  const {\n    complexMatchesToIgnore,\n    minSequentialLinesToMatch,\n    minTotalCodeEnergy,\n  } = sensitivityConfig;\n\n  const { totalCodeEnergy, totalComplexMatches, lines } =\n    getCodeEnergy(content);\n\n  if (totalComplexMatches <= complexMatchesToIgnore) {\n    return false;\n  }\n\n  if (totalCodeEnergy < minTotalCodeEnergy) {\n    return false;\n  }\n\n  if (\n    numSequentialLinesWithThresholdCodeEnergy(\n      codeEnergyValues[CodeEnergyLevels.Complex]\n    )(lines) < minSequentialLinesToMatch\n  ) {\n    return false;\n  }\n\n  return true;\n};\n\nexport const detectUnformattedCode = (content) => {\n  const strippedContent = stripIgnoredContent(content);\n\n  return isBetween(\n    settings.min_post_length_to_check,\n    settings.max_post_length_to_check === -1\n      ? Infinity\n      : settings.max_post_length_to_check\n  )(content.length)\n    ? detectCode(strippedContent)\n    : false;\n};\n","import { service } from \"@ember/service\";\nimport { withPluginApi } from \"discourse/lib/plugin-api\";\nimport ModalUcdWarning from \"../components/modal/ucd-warning\";\nimport { detectUnformattedCode, printDebugInfo } from \"../core/detect-code\";\n\nconst getDisableAtTrustLevel = () =>\n  settings.disable_at_trust_level === -1\n    ? Infinity\n    : settings.disable_at_trust_level;\n\nexport default {\n  name: \"unformatted-code-detector\",\n  initialize() {\n    withPluginApi((api) => {\n      window.debugUnformattedCodeDetector = () => {\n        const content = document.querySelector(\n          \"#reply-control textarea.d-editor-input\"\n        )?.value;\n        if (!content) {\n          // eslint-disable-next-line no-console\n          console.log(\"No content found\");\n        } else {\n          printDebugInfo(content);\n        }\n      };\n\n      api.modifyClass(\n        \"model:composer\",\n        (Superclass) =>\n          class extends Superclass {\n            @service ucdState;\n\n            ucd_previousWarningIgnored = false;\n\n            ucd_checkShouldIgnoreWarning() {\n              return (\n                this.ucd_previousWarningIgnored ||\n                this.ucdState.permanentlyDismissed ||\n                api.getCurrentUser()?.trust_level >= getDisableAtTrustLevel()\n              );\n            }\n\n            ucd_checkUnformattedCodeDetected() {\n              return detectUnformattedCode(this.reply);\n            }\n          }\n      );\n\n      api.modifyClass(\n        \"service:composer\",\n        (Superclass) =>\n          class extends Superclass {\n            save(...args) {\n              if (\n                this.model.ucd_checkUnformattedCodeDetected() &&\n                !this.model.ucd_checkShouldIgnoreWarning()\n              ) {\n                this.modal.show(ModalUcdWarning, {\n                  model: this.model,\n                });\n              } else {\n                super.save(...args);\n              }\n            }\n          }\n      );\n    });\n  },\n};\n","import Service from \"@ember/service\";\nimport KeyValueStore from \"discourse/lib/key-value-store\";\n\nconst DISMISSED = \"permanently_dismissed\";\nconst NAMESPACE = \"ucd_\";\n\nexport default class extends Service {\n  store = new KeyValueStore(NAMESPACE);\n\n  get permanentlyDismissed() {\n    return this.store.getObject(DISMISSED) || false;\n  }\n\n  toggle() {\n    this.store.setObject({ key: DISMISSED, value: !this.permanentlyDismissed });\n  }\n}\n","const compatModules = {};import \"virtual:init-settings\";\nimport * as Mod1 from \"./discourse/components/modal/ucd-warning\";\ncompatModules[\"discourse/components/modal/ucd-warning\"] = Mod1;\n\nexport * as discourse$components$modal$ucd__warning$$__module from \"./discourse/components/modal/ucd-warning\";\nexport {\ndefault as discourse$components$modal$ucd__warning$$default\n} from \"./discourse/components/modal/ucd-warning\";\nimport * as Mod2 from \"./discourse/components/ucd-warning\";\ncompatModules[\"discourse/components/ucd-warning\"] = Mod2;\n\nexport * as discourse$components$ucd__warning$$__module from \"./discourse/components/ucd-warning\";\nexport {\ndefault as discourse$components$ucd__warning$$default\n} from \"./discourse/components/ucd-warning\";\nimport * as Mod3 from \"./discourse/core/code-energy\";\ncompatModules[\"discourse/core/code-energy\"] = Mod3;\n\nexport * as discourse$core$code__energy$$__module from \"./discourse/core/code-energy\";\nexport {\nCodeEnergyLevels as discourse$core$code__energy$$CodeEnergyLevels,\ncodeEnergyValues as discourse$core$code__energy$$codeEnergyValues,\ngetCodeEnergyIndicators as discourse$core$code__energy$$getCodeEnergyIndicators\n} from \"./discourse/core/code-energy\";\nimport * as Mod4 from \"./discourse/core/detect-code\";\ncompatModules[\"discourse/core/detect-code\"] = Mod4;\n\nexport * as discourse$core$detect__code$$__module from \"./discourse/core/detect-code\";\nexport {\ngetCodeEnergy as discourse$core$detect__code$$getCodeEnergy,\nnumSequentialLinesWithThresholdCodeEnergy as discourse$core$detect__code$$numSequentialLinesWithThresholdCodeEnergy,\nprintDebugInfo as discourse$core$detect__code$$printDebugInfo,\ndetectUnformattedCode as discourse$core$detect__code$$detectUnformattedCode\n} from \"./discourse/core/detect-code\";\nimport * as Mod5 from \"./discourse/core/sensitivity\";\ncompatModules[\"discourse/core/sensitivity\"] = Mod5;\n\nexport * as discourse$core$sensitivity$$__module from \"./discourse/core/sensitivity\";\nexport {\napplySensitivity as discourse$core$sensitivity$$applySensitivity,\nsensitivityConfig as discourse$core$sensitivity$$sensitivityConfig\n} from \"./discourse/core/sensitivity\";\nimport * as Mod6 from \"./discourse/core/strip-ignored-content\";\ncompatModules[\"discourse/core/strip-ignored-content\"] = Mod6;\n\nexport * as discourse$core$strip__ignored__content$$__module from \"./discourse/core/strip-ignored-content\";\nexport {\nstripIgnoredContent as discourse$core$strip__ignored__content$$stripIgnoredContent\n} from \"./discourse/core/strip-ignored-content\";\nimport * as Mod7 from \"./discourse/initializers/init\";\ncompatModules[\"discourse/initializers/init\"] = Mod7;\n\nexport * as discourse$initializers$init$$__module from \"./discourse/initializers/init\";\nexport {\ndefault as discourse$initializers$init$$default\n} from \"./discourse/initializers/init\";\nimport * as Mod8 from \"./discourse/lib/boundaries\";\ncompatModules[\"discourse/lib/boundaries\"] = Mod8;\n\nexport * as discourse$lib$boundaries$$__module from \"./discourse/lib/boundaries\";\nexport {\ngetLineBoundaries as discourse$lib$boundaries$$getLineBoundaries,\nisBetween as discourse$lib$boundaries$$isBetween\n} from \"./discourse/lib/boundaries\";\nimport * as Mod9 from \"./discourse/lib/emoji-diversity\";\ncompatModules[\"discourse/lib/emoji-diversity\"] = Mod9;\n\nexport * as discourse$lib$emoji__diversity$$__module from \"./discourse/lib/emoji-diversity\";\nexport {\nrandomizeEmojiGender as discourse$lib$emoji__diversity$$randomizeEmojiGender,\nrandomizeEmojiSkinTone as discourse$lib$emoji__diversity$$randomizeEmojiSkinTone,\nrandomizeEmojiDiversity as discourse$lib$emoji__diversity$$randomizeEmojiDiversity\n} from \"./discourse/lib/emoji-diversity\";\nimport * as Mod10 from \"./discourse/services/ucd-state\";\ncompatModules[\"discourse/services/ucd-state\"] = Mod10;\n\nexport * as discourse$services$ucd__state$$__module from \"./discourse/services/ucd-state\";\nexport {\ndefault as discourse$services$ucd__state$$default\n} from \"./discourse/services/ucd-state\";\nexport default compatModules;\n"],"names":["registerSettings","emoji_icon","disable_at_trust_level","sensitivity","min_post_length_to_check","max_post_length_to_check","include_html","settings","getObjectForTheme","themePrefix","key","genderEmojiData","masc","adult","child","modifier","fem","emojiRegexes","Object","keys","values","reduce","regexInfo","subStrType","RegExp","map","gender","filter","Boolean","join","randomizeEmojiGender","emojis","entries","emoji","regex","replace","randomGenderEmojiData","genders","Math","floor","random","length","MIN_SKIN_TONE_CODEPOINT","randomizeEmojiSkinTone","String","fromCodePoint","randomizeEmojiDiversity","UcdWarning","Component","dt7948","g","this","prototype","service","modal","i","ucdState","controller","composer","shouldPermanentlyDismiss","permanentlyDismissed","toggleShouldPermanentlyDismiss","toggle","n","action","goBackAndFix","close","ignoreAndProceed","model","ucd_previousWarningIgnored","save","setComponentTemplate","createTemplateFactory","id","block","moduleName","scope","CookText","i18n","Input","on","DButton","isStrictMode","ModalUcdWarning","title","htmlSafe","emojiUnescape","escape","closeModal","args","ucd_shouldPermanentlyDismiss","permanentlyDismiss","DModal","varNameEnd","varName","varFragment","xmlLikeName","argument","argList","CodeEnergyLevels","Complex","High","Medium","Low","codeEnergyValues","nonHtmlIndicators","split","htmlIndicators","_codeEnergyIndicators","indicators","flat","value","getCodeEnergyIndicators","source","matcher","getLineBoundaries","str","lineBoundaries","cursor","push","start","indexOf","end","content","slice","isBetween","point","applySensitivity","leastSensitive","mostSensitive","sensitivityConfig","complexMatchesToIgnore","round","minSequentialLinesToMatch","minTotalCodeEnergy","ignoredContents","stripIgnoredContent","ignoredContent","getCodeEnergy","totalCodeEnergy","totalComplexMatches","lines","forEach","x","matches","matched_patterns","matchAll","match","startIndex","index","endIndex","line","isThisLine","numSequentialLinesWithThresholdCodeEnergy","threshold","maxContiguous","curContiguous","trim","max","printDebugInfo","debugTable","consecutive","l","p","columns","dividers","c","longest","row","padEnd","unshift","console","log","detectUnformattedCode","strippedContent","Infinity","detectCode","init","name","initialize","withPluginApi","api","window","debugUnformattedCodeDetector","document","querySelector","modifyClass","Superclass","ucd_checkShouldIgnoreWarning","getCurrentUser","trust_level","ucd_checkUnformattedCodeDetected","reply","show","super","DISMISSED","Service","store","KeyValueStore","getObject","setObject","compatModules","Mod1","Mod2","Mod3","Mod4","Mod5","Mod6","Mod7","Mod8","Mod9","Mod10"],"mappings":"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"}