<commit_before>import SearchAndReplace from './SearchAndReplace'
import Protect from './Protect'
import Style from './Style'
import Hide from './Hide'
import Group from './Group'
import ReplaceImage from './ReplaceImage'
import RecolorImage from './RecolorImage'
import ReplaceLink from './ReplaceLink'
import ReplaceNeighbor from './ReplaceNeighbor'
import InsertHTML from './InsertHTML'
import OverwriteHTML from './OverwriteHTML'
import ReplaceFlowmapIcon from './appdynamics/ReplaceFlowmapIcon'
import ReplaceFlowmapConnection from './appdynamics/ReplaceFlowmapConnection'
import RecolorDashboard from './appdynamics/RecolorDashboard'
import SetDashboardBackground from './appdynamics/SetDashboardBackground'
import DelayLink from './appdynamics/DelayLink'
import BlockUrl from './BlockUrl'
import DelayUrl from './DelayUrl'
import ReplaceUrl from './ReplaceUrl'
import Limit from './Limit'
import Eval from './Eval'
import Command from './Command'
import UndoElement from './UndoElement'

class CommandBuilder {
  constructor(namespaces = [], includeRules, excludeRules, withEvalCommand = false) {
    this.namespaces = namespaces
    this.includeRules = includeRules
    this.excludeRules = excludeRules
    this.withEvalCommand = withEvalCommand
  }

  _buildRegex(search, modifiers, replace) {
    // If the provided regular expression is invalid, an exception is thrown
    // We capture that exception and return an dummy command
    try {
      modifiers = typeof modifiers === 'string' ? modifiers : 'g'
      if (modifiers.includes('p')) {
        return new SearchAndReplace(
          new RegExp(search, modifiers.replace('p', '')),
          function (match) {
            if (match.toUpperCase() === match) {
              replace = replace.toUpperCase()
            }
            if (match.toLowerCase() === match) {
              replace = replace.toLowerCase()
            }
            return match.replace(new RegExp(search, modifiers.replace('p', '')), replace)
          })
      }
      return new SearchAndReplace(new RegExp(search, modifiers), replace)
    } catch (e) {
      return new Command()
    }
  }

  _buildCustomCommand(namespace, command, parameters, value) {
    var location = typeof window === 'undefined' ? '' : window.location

    if (namespace === 'appdynamics' || this.namespaces.includes('appdynamics')) {
      if (command === 'replaceFlowmapIcon') {
        return new ReplaceFlowmapIcon(parameters[0], value)
      }

      if (command === 'replaceApplication') {
        return value === '' || value === true
          ? this._buildCustomCommand(namespace, 'hideApplication', parameters, value)
          : new SearchAndReplace(parameters[0], value)
      }
      if (command === 'hideApplication') {
        return new Group([
          new Hide(parameters[0], 4, 'ads-application-card', '', 'APPS_ALL_DASHBOARD', location),
          new Hide(parameters[0], 3, 'x-grid-row', '', 'APPS_ALL_DASHBOARD', location),
          new Hide(parameters[0], 3, 'ads-home-list-action-item', '', 'AD_HOME_OVERVIEW', location, function (node, parentNode) {
            return node.parentElement.hasAttribute('ad-test-id') && node.parentElement.getAttribute('ad-test-id').includes('home-screen-application-card-application-name')
          })
        ])
      }
      if (command === 'hideBrowserApplication') {
        return new Group([
          new Hide(parameters[0], 4, 'x-grid-row', '', 'EUM_WEB_ALL_APPS', location),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewEumWebApplication')
          })
        ])
      }
      if (command === 'hideMobileApplication') {
        return new Group([
          new Hide(parameters[0], 4, 'ads-mobile-app-card', '', 'EUM_MOBILE_ALL_APPS', location),
          new Hide(parameters[0], 4, 'x-grid-row', '', 'EUM_MOBILE_ALL_APPS', location),
          new Hide(parameters[0], 5, 'x-grid-row', '', 'EUM_MOBILE_ALL_APPS', location),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewEumMobileApplication')
          })
        ])
      }
      if (command === 'hideDB' || command === 'hideDatabase') {
        return new Group([
          new Hide(parameters[0], 9, 'ads-database-card', '', 'DB_MONITORING_SERVER_LIST', location),
          new Hide(parameters[0], 4, 'x-grid-row', '', 'DB_MONITORING_SERVER_LIST', location),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewDbServer')
          })
        ])
      }
      if (command === 'hideBT' || command === 'hideBusinessTransaction') {
        return new Hide(parameters[0], 3, 'x-grid-row', '', 'APP_BT_LIST', location)
      }
      if (command === 'hideDashboard') {
        return new Group([
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'DASHBOARDS_REPORTS_HOME', location),
          new Hide(parameters[0], 3, 'x-grid-row', '', 'DASHBOARD_LIST', location, function (node, parentNode) {
            // Make sure that replacements with !not work on the dashboard list, so filter for the first cell
            return node.parentElement.parentElement.className.includes('x-grid-cell-first')
          }),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewCustomDashboard')
          })
        ])
      }
      if (command === 'hideBusinessJourney') {
        return new Hide(parameters[0], 9, 'ads-analytics-business-outcomes-card-size', '', 'ANALYTICS_BUSINESS_OUTCOMES', location)
      }
      if (command === 'hideAnalyticsSearch') {
        return new Hide(parameters[0], 7, 'ui-grid-row', '', 'ANALYTICS_SEARCH_LIST', location)
      }
      if (command === 'hideRemoteService') {
        return new Hide(parameters[0], 3, 'x-grid-row', '', 'APP_BACKEND_LIST', location)
      }
      if (command === 'replaceFlowmapConnection') {
        return new ReplaceFlowmapConnection(parameters[0], parameters[1], value, parameters[2])
      }
      if (command === 'hideFlowmapConnection') {
        return new ReplaceFlowmapConnection(parameters[0], parameters[1], 'Hide')
      }
      if (command === 'hideBrowserPage') {
        return new Hide(parameters[0], 4, 'x-grid-row', '', 'EUM_PAGES_LIST', location)
      }
      if (command === 'replaceMobileScreenshot') {
        const thumbnailHtml = '<img src="' + value + '" height="152" width="84">'
        const screenshotHtml = '<img src="' + value + '" height="400" width="224">'
        return new Group([
          new OverwriteHTML('EUM_MOBILE_SESSION_DETAILS', 'ad-screenshot-tile-stitcher[ad-container-width="500"] > div', screenshotHtml, location),
          new OverwriteHTML('EUM_MOBILE_SESSION_DETAILS', 'ad-screenshot-tile-stitcher[ad-container-width="202"] > div', thumbnailHtml, location)
        ])
      }
      if (command === 'delayLink') {
        return new DelayLink(parameters[0], value, window)
      }
      if (command === 'recolorDashboard' || command === 'recolourDashboard') {
        return new RecolorDashboard(parameters[0], value, parameters[1], location)
      }
      if (command === 'setDashboardBackground') {
        return new SetDashboardBackground(parameters[0], parameters[1], value, location)
      }
      if (command === 'replaceNodeCount') {
        if (typeof value === 'string' && ['λ', 'lambda'].includes(value.toLowerCase())) {
          return new Group([
            new ReplaceNeighbor(parameters[0], '', 2, 'text.adsNodeCountText', '', '', location),
            new ReplaceNeighbor(parameters[0], '', 2, 'text.adsNodeCountTextLarge', '', '', location),
            new ReplaceNeighbor(parameters[0], '', 2, 'text.adsNodeCountTextSmall', '', '', location),
            new ReplaceNeighbor(parameters[0], 'images/tierTypes/AWSLambda.svg', 2, 'g.adsNodeCountContainer image', '', '', location, (search, replace, node) => {
              // <image transform="translate(-15, -15 )" width="30" height="30" xlink:href=""></image>
              const bg = node.parentElement.querySelector('.adsNodeCountBackground')
              if (bg && bg.style && bg.style.fill !== 'rgb(255, 255, 255)') {
                replace = 'images/tierTypes/AWSLambda_white.svg'
              }
              if (node.href.baseVal !== replace) {
                const original = node.href.baseVal
                const originalWidth = node.width.baseVal.value
                const originalHeight = node.height.baseVal.value
                const originalTransform = node.transform
                node.href.baseVal = replace
                node.width.baseVal.value = 30
                node.height.baseVal.value = 30
                node.setAttribute('transform', 'translate(-15,-15)')
                return [
                  new UndoElement(node, 'href.baseVal', original, replace),
                  new UndoElement(node, 'width.baseVal.value', originalWidth, 30),
                  new UndoElement(node, 'height.baseVal.value', originalHeight, 30),
                  new UndoElement(node, 'transform', originalTransform, 'translate(-15,-15)')
                ]
              }
              return false
            })
          ])
        }
        return new Group([
          new ReplaceNeighbor(parameters[0], value, 2, 'text.adsNodeCountText', '', '', location),
          new ReplaceNeighbor(parameters[0], parseInt(value) === 1 ? 'Node' : 'Nodes', 2, 'text.adsNodeCountTextSmall', '', '', location)
        ])
      }
      if (command === 'replaceInnerNodeHealth') {
        if (value && ['normal', 'warning', 'critical'].includes(value.toLowerCase())) {
          value = {'normal': 'rgb(0, 209, 128)', 'warning': 'rgb(255, 211, 1)', 'critical': 'rgb(255, 32, 46)'}[value.toLowerCase()]<commit_msg>Add fix for #54, replaceNodeCount now also works with applications<commit_after>import SearchAndReplace from './SearchAndReplace'
import Protect from './Protect'
import Style from './Style'
import Hide from './Hide'
import Group from './Group'
import ReplaceImage from './ReplaceImage'
import RecolorImage from './RecolorImage'
import ReplaceLink from './ReplaceLink'
import ReplaceNeighbor from './ReplaceNeighbor'
import InsertHTML from './InsertHTML'
import OverwriteHTML from './OverwriteHTML'
import ReplaceFlowmapIcon from './appdynamics/ReplaceFlowmapIcon'
import ReplaceFlowmapConnection from './appdynamics/ReplaceFlowmapConnection'
import RecolorDashboard from './appdynamics/RecolorDashboard'
import SetDashboardBackground from './appdynamics/SetDashboardBackground'
import DelayLink from './appdynamics/DelayLink'
import BlockUrl from './BlockUrl'
import DelayUrl from './DelayUrl'
import ReplaceUrl from './ReplaceUrl'
import Limit from './Limit'
import Eval from './Eval'
import Command from './Command'
import UndoElement from './UndoElement'

class CommandBuilder {
  constructor(namespaces = [], includeRules, excludeRules, withEvalCommand = false) {
    this.namespaces = namespaces
    this.includeRules = includeRules
    this.excludeRules = excludeRules
    this.withEvalCommand = withEvalCommand
  }

  _buildRegex(search, modifiers, replace) {
    // If the provided regular expression is invalid, an exception is thrown
    // We capture that exception and return an dummy command
    try {
      modifiers = typeof modifiers === 'string' ? modifiers : 'g'
      if (modifiers.includes('p')) {
        return new SearchAndReplace(
          new RegExp(search, modifiers.replace('p', '')),
          function (match) {
            if (match.toUpperCase() === match) {
              replace = replace.toUpperCase()
            }
            if (match.toLowerCase() === match) {
              replace = replace.toLowerCase()
            }
            return match.replace(new RegExp(search, modifiers.replace('p', '')), replace)
          })
      }
      return new SearchAndReplace(new RegExp(search, modifiers), replace)
    } catch (e) {
      return new Command()
    }
  }

  _buildCustomCommand(namespace, command, parameters, value) {
    var location = typeof window === 'undefined' ? '' : window.location

    if (namespace === 'appdynamics' || this.namespaces.includes('appdynamics')) {
      if (command === 'replaceFlowmapIcon') {
        return new ReplaceFlowmapIcon(parameters[0], value)
      }

      if (command === 'replaceApplication') {
        return value === '' || value === true
          ? this._buildCustomCommand(namespace, 'hideApplication', parameters, value)
          : new SearchAndReplace(parameters[0], value)
      }
      if (command === 'hideApplication') {
        return new Group([
          new Hide(parameters[0], 4, 'ads-application-card', '', 'APPS_ALL_DASHBOARD', location),
          new Hide(parameters[0], 3, 'x-grid-row', '', 'APPS_ALL_DASHBOARD', location),
          new Hide(parameters[0], 3, 'ads-home-list-action-item', '', 'AD_HOME_OVERVIEW', location, function (node, parentNode) {
            return node.parentElement.hasAttribute('ad-test-id') && node.parentElement.getAttribute('ad-test-id').includes('home-screen-application-card-application-name')
          })
        ])
      }
      if (command === 'hideBrowserApplication') {
        return new Group([
          new Hide(parameters[0], 4, 'x-grid-row', '', 'EUM_WEB_ALL_APPS', location),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewEumWebApplication')
          })
        ])
      }
      if (command === 'hideMobileApplication') {
        return new Group([
          new Hide(parameters[0], 4, 'ads-mobile-app-card', '', 'EUM_MOBILE_ALL_APPS', location),
          new Hide(parameters[0], 4, 'x-grid-row', '', 'EUM_MOBILE_ALL_APPS', location),
          new Hide(parameters[0], 5, 'x-grid-row', '', 'EUM_MOBILE_ALL_APPS', location),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewEumMobileApplication')
          })
        ])
      }
      if (command === 'hideDB' || command === 'hideDatabase') {
        return new Group([
          new Hide(parameters[0], 9, 'ads-database-card', '', 'DB_MONITORING_SERVER_LIST', location),
          new Hide(parameters[0], 4, 'x-grid-row', '', 'DB_MONITORING_SERVER_LIST', location),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewDbServer')
          })
        ])
      }
      if (command === 'hideBT' || command === 'hideBusinessTransaction') {
        return new Hide(parameters[0], 3, 'x-grid-row', '', 'APP_BT_LIST', location)
      }
      if (command === 'hideDashboard') {
        return new Group([
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'DASHBOARDS_REPORTS_HOME', location),
          new Hide(parameters[0], 3, 'x-grid-row', '', 'DASHBOARD_LIST', location, function (node, parentNode) {
            // Make sure that replacements with !not work on the dashboard list, so filter for the first cell
            return node.parentElement.parentElement.className.includes('x-grid-cell-first')
          }),
          new Hide(parameters[0], 2, 'ads-home-list-item', '', 'AD_HOME_OVERVIEW', location, function (_, parentNode) {
            return parentNode.getAttribute('ng-click').includes('ViewCustomDashboard')
          })
        ])
      }
      if (command === 'hideBusinessJourney') {
        return new Hide(parameters[0], 9, 'ads-analytics-business-outcomes-card-size', '', 'ANALYTICS_BUSINESS_OUTCOMES', location)
      }
      if (command === 'hideAnalyticsSearch') {
        return new Hide(parameters[0], 7, 'ui-grid-row', '', 'ANALYTICS_SEARCH_LIST', location)
      }
      if (command === 'hideRemoteService') {
        return new Hide(parameters[0], 3, 'x-grid-row', '', 'APP_BACKEND_LIST', location)
      }
      if (command === 'replaceFlowmapConnection') {
        return new ReplaceFlowmapConnection(parameters[0], parameters[1], value, parameters[2])
      }
      if (command === 'hideFlowmapConnection') {
        return new ReplaceFlowmapConnection(parameters[0], parameters[1], 'Hide')
      }
      if (command === 'hideBrowserPage') {
        return new Hide(parameters[0], 4, 'x-grid-row', '', 'EUM_PAGES_LIST', location)
      }
      if (command === 'replaceMobileScreenshot') {
        const thumbnailHtml = '<img src="' + value + '" height="152" width="84">'
        const screenshotHtml = '<img src="' + value + '" height="400" width="224">'
        return new Group([
          new OverwriteHTML('EUM_MOBILE_SESSION_DETAILS', 'ad-screenshot-tile-stitcher[ad-container-width="500"] > div', screenshotHtml, location),
          new OverwriteHTML('EUM_MOBILE_SESSION_DETAILS', 'ad-screenshot-tile-stitcher[ad-container-width="202"] > div', thumbnailHtml, location)
        ])
      }
      if (command === 'delayLink') {
        return new DelayLink(parameters[0], value, window)
      }
      if (command === 'recolorDashboard' || command === 'recolourDashboard') {
        return new RecolorDashboard(parameters[0], value, parameters[1], location)
      }
      if (command === 'setDashboardBackground') {
        return new SetDashboardBackground(parameters[0], parameters[1], value, location)
      }
      if (command === 'replaceNodeCount') {
        if (typeof value === 'string' && ['λ', 'lambda'].includes(value.toLowerCase())) {
          return new Group([
            new ReplaceNeighbor(parameters[0], '', 2, 'text.adsNodeCountText', '', '', location),
            new ReplaceNeighbor(parameters[0], '', 2, 'text.adsNodeCountTextLarge', '', '', location),
            new ReplaceNeighbor(parameters[0], '', 2, 'text.adsNodeCountTextSmall', '', '', location),
            new ReplaceNeighbor(parameters[0], 'images/tierTypes/AWSLambda.svg', 2, 'g.adsNodeCountContainer image', '', '', location, (search, replace, node) => {
              // <image transform="translate(-15, -15 )" width="30" height="30" xlink:href=""></image>
              const bg = node.parentElement.querySelector('.adsNodeCountBackground')
              if (bg && bg.style && bg.style.fill !== 'rgb(255, 255, 255)') {
                replace = 'images/tierTypes/AWSLambda_white.svg'
              }
              if (node.href.baseVal !== replace) {
                const original = node.href.baseVal
                const originalWidth = node.width.baseVal.value
                const originalHeight = node.height.baseVal.value
                const originalTransform = node.transform
                node.href.baseVal = replace
                node.width.baseVal.value = 30
                node.height.baseVal.value = 30
                node.setAttribute('transform', 'translate(-15,-15)')
                return [
                  new UndoElement(node, 'href.baseVal', original, replace),
                  new UndoElement(node, 'width.baseVal.value', originalWidth, 30),
                  new UndoElement(node, 'height.baseVal.value', originalHeight, 30),
                  new UndoElement(node, 'transform', originalTransform, 'translate(-15,-15)')
                ]
              }
              return false
            })
          ])
        }
        if (typeof value === 'string' && value.includes(',')) {
          const [tierCount, nodeCount] = value.split(',')
          console.log(tierCount, nodeCount, value, value.split(','))
          return new Group([
            new ReplaceNeighbor(parameters[0], tierCount, 2, 'g.adsApplicationNode text.adsNodeCountText:nth-of-type(1)', '', '', location),
            new ReplaceNeighbor(parameters[0], parseInt(tierCount) === 1 ? 'TIER' : 'TIERS', 2, 'g.adsApplicationNode text.adsNodeCountTextSmall:nth-of-type(2)', '', '', location),
            new ReplaceNeighbor(parameters[0], nodeCount, 2, 'g.adsApplicationNode text.adsNodeCountText:nth-of-type(3)', '', '', location),
            new ReplaceNeighbor(parameters[0], parseInt(nodeCount) === 1 ? 'NODE' : 'NODES', 2, 'g.adsApplicationNode text.adsNodeCountTextSmall:nth-of-type(4)', '', '', location)
          ])
        }
        console.log(value, 'value')
        return new Group([
          new ReplaceNeighbor(parameters[0], value, 2, 'g.adsTierNode text.adsNodeCountText', '', '', location),
          new ReplaceNeighbor(parameters[0], parseInt(value) === 1 ? 'Node' : 'Nodes', 2, 'g.adsTierNode text.adsNodeCountTextSmall', '', '', location),
          new ReplaceNeighbor(parameters[0], value, 2, 'g.adsApplicationNode text.adsNodeCountText:nth-of-type(3)', '', '', location),
          new ReplaceNeighbor(parameters[0], parseInt(value) === 1 ? 'NODE' : 'NODES', 2, 'g.adsApplicationNode text.adsNodeCountTextSmall:nth-of-type(4)', '', '', location)
        ])
      }
      if (command === 'replaceInnerNodeHealth') {
        if (value && ['normal', 'warning', 'critical'].includes(value.toLowerCase())) {
          value = {'normal': 'rgb(0, 209, 128)', 'warning': 'rgb(255, 211, 1)', 'critical': 'rgb(255, 32, 46)'}[value.toLowerCase()]
{'fraction_non_alphanumeric': 0.14940821536319332, 'fraction_numerical': 0.013692271988860524, 'mean_word_length': 2.976010334009965, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1531252', 'n_tokens_mistral': 6332, 'n_tokens_neox': 6028, 'n_words': 1365}