<commit_before><template>
  <div>
    <form novalidate @submit.stop.prevent="runSearch()" id="searchForm">
      <md-input-container>
        <label>{{ $t("Search") }}</label>
        <md-input v-model="searchString" ref="searchInput"></md-input>
        <md-button @click="runSearch()" :disabled="searchString.length<3">{{ $t("Search") }}</md-button>
      </md-input-container>
    </form>
    <md-layout id="searchLayout" :class="{floatSideBar: floatSideBar}">
      <md-layout id="searchResults">
        <ui-loading v-if="isSearching"></ui-loading>
        <div v-else-if="!isSearching && results.total > 0">
          <template v-for="(result, index) in results.results">
            <div class="searchResult" v-if="result" v-bind:key="index">
              <div class="searchImg">
                <router-link :to="'/' + result.slug">
                  <md-image :md-src="result.thumbnail" v-if="result.thumbnail"></md-image>
                  <placeholder-img :text="result.type" v-else></placeholder-img>
                </router-link>
              </div>
              <div class="searchText">
                <router-link :to="'/' + result.slug">{{ result.name || result.type }}</router-link>
                <span class="hidden-status" v-if="result.visibility.private">- Private -</span>
                <span class="hidden-status" v-if="result.visibility.hidden">- Hidden -</span>
                <span class="hidden-status" v-if="result.visibility.encrypted">- Encrypted -</span>
                <span class="hidden-status" v-if="result.visibility.restricted">- Restricted -</span>
                <md-subheader>
                  <span>{{ result.type }}</span>
                  <span>{{ result.date.modified || result.date.created | moment('LLL') }}</span>
                  <router-link v-if="result.user.searchable" :class="result.user.roleClass" :to="'/p/' + result.user.name">{{ result.user.name }}</router-link>
                  <span v-else :class="result.user.roleClass">{{ result.user.name }}</span>
                  <span>{{ $t("[-count-] view", { count: result.viewCount }) }}</span>
                  <span>{{ $t("[-count-] star", { count: result.favoriteCount }) }}</span>
                  <span>{{ $t("[-count-] comment", { count: result.commentCount }) }}</span>
                </md-subheader>
                <formatted-text :text="result.description" truncate="180" :plaintext="true"></Formatted-text>
                <div class="searchTags">
                  <md-chip v-for="cat in result.categories" v-bind:key="cat.id" :class="cat.cls" disabled v-if="cat.text">{{ cat.text }}</md-chip>
                </div>        
              </div>      
            </div>
            <advert :ad="'wago728x90-' + Math.ceil(index / 9)" :belowTheFold="index > 10" v-if="!isCollection && (index %9 === 2 || (results.total < 3 && index === results.total - 1))" />
          </template>
        </div>
        <div class="searchResult" v-else-if="!isSearching && results.total === 0">{{ $t("No results found") }}</div>
      </md-layout>

      <md-layout id="searchSide" v-if="results && results.query">
        <md-layout id="searchMeta" v-if="results && results.query">
          <search-meta :meta="results.query.context" :tagMap="tagMap" :textSearch="results.query.textSearch" :sort="sortVal" @setSort="setSort" @setImportType="setImportType" :catRelevance="catRelevance" @setCategoryRelevance="setCategoryRelevance" :filterExpansion="filterExpansion" @setExpansion="setExpansion"></search-meta>
        </md-layout>
      </md-layout>
    </md-layout>
    <p v-if="isSearchingMore">{{ $t("Loading more") }}</p>
  </div>
</template>

<script>
import Categories from '../libs/categories'
export default {
  data: function () {
    return {
      results: {
        total: 0
      },
      searchString: '',
      searchOptions: 'sort: Date',
      floatSideBar: false,
      tagContext: [],
      searchTime: 0,
      tagMap: {},
      isSearching: true,
      isSearchingMore: false,
      sortVal: this.$store.state.user && this.$store.state.user.config && this.$store.state.user.config.searchOptions.sort || 'bestmatch',
      uiSearchValue: false,
      catRelevance: this.$store.state.user && this.$store.state.user.config && this.$store.state.user.config.searchOptions.relevance || 'standard',
      uiRelevanceValue: false,
      filterExpansion: this.$store.state.user && this.$store.state.user.config && this.$store.state.user.config.searchOptions.expansion || 'all',
      uiExpansionValue: false,
      contextSearchData: this.contextSearch,
      isCollection: false
    }
  },
  props: ['contextSearch', 'contextGame'],
  components: {
    'search-meta': require('../UI/SearchMeta.vue'),
    'formatted-text': require('../UI/FormattedText.vue'),
    'placeholder-img': require('../UI/PlaceHolderImage.vue')
  },
  watch: {
    '$route' (to, from) {
      this.searchString = ''
      this.runSearch(false)
    }
  },
  methods: {
    runSearch: function (query) {
      if (!query && this.searchString) {
        var _this = this
        // super hacky but vue.nextTick isn't updating the input value if form is submitted too quickly after typing, so just wait
        return setTimeout(function () {
          if (!_this.searchString) {
            return
          }
          _this.runSearch(_this.searchString)
        }, 100)
      }
      // throttle searches
      if (this.searchTime < +new Date() - 500) {
        this.searchTime = +new Date()
      }
      else {
        return
      }
      var opt = ''
      // if loaded via category menu
      if (this.contextSearchData && !query) {
        this.contextSearchData = this.contextSearchData.replace(this.searchOptions, '')
        this.searchString = this.contextSearchData
        query = this.contextSearchData
      }
      // if loaded direct
      else if (!query && this.$route.params.query) {
        query = this.$route.params.query.replace(/\+/g, ' ').replace(this.searchOptions, '')
        this.searchString = query
      }
      // if loaded as component from other file
      else if (typeof query === 'string' && query) {
        query = query.replace(this.searchOptions.trim(), '')
        // this.$router.push('/search/' + query.replace(/\s+/g, '+'))
        this.searchString = query
      }
      // if navigating forward/back
      else if (this.$route.params.query) {
        query = this.$route.params.query.replace('+', ' ').replace(this.searchOptions, '')
      }
      // something broke, no query found (empty string?)
      else {
        return
      }

      this.isSearching = true

      // check if sort value needs to be added to query
      if (this.uiSearchValue) {
        opt = opt + ' Sort: ' + this.sortVal
      }

      if (this.uiExpansionValue) {
        opt = opt + ' Expansion: ' + this.filterExpansion
      }

      // check if we're searching for any localized tags
      const regex = /\btag:\s*"([^"]+)"|\btag:\s*([^\s]+)/ig
      var tagSearch = query.match(regex)
      if (tagSearch && tagSearch.length > 0) {
        // check for relevance if tags are found
        if (this.uiRelevanceValue) {
          opt = opt + ' Relevance: ' + this.catRelevance
        }

        this.tagContext = []
        this.tagMap = {}
        tagSearch.forEach((tagQuery) => {
          var tagMatch<commit_msg>fix broken profile for some users<commit_after><template>
  <div>
    <form novalidate @submit.stop.prevent="runSearch()" id="searchForm">
      <md-input-container>
        <label>{{ $t("Search") }}</label>
        <md-input v-model="searchString" ref="searchInput"></md-input>
        <md-button @click="runSearch()" :disabled="searchString.length<3">{{ $t("Search") }}</md-button>
      </md-input-container>
    </form>
    <md-layout id="searchLayout" :class="{floatSideBar: floatSideBar}">
      <md-layout id="searchResults">
        <ui-loading v-if="isSearching"></ui-loading>
        <div v-else-if="!isSearching && results.total > 0">
          <template v-for="(result, index) in results.results">
            <div class="searchResult" v-if="result" v-bind:key="index">
              <div class="searchImg">
                <router-link :to="'/' + result.slug">
                  <md-image :md-src="result.thumbnail" v-if="result.thumbnail"></md-image>
                  <placeholder-img :text="result.type" v-else></placeholder-img>
                </router-link>
              </div>
              <div class="searchText">
                <router-link :to="'/' + result.slug">{{ result.name || result.type }}</router-link>
                <span class="hidden-status" v-if="result.visibility.private">- Private -</span>
                <span class="hidden-status" v-if="result.visibility.hidden">- Hidden -</span>
                <span class="hidden-status" v-if="result.visibility.encrypted">- Encrypted -</span>
                <span class="hidden-status" v-if="result.visibility.restricted">- Restricted -</span>
                <md-subheader>
                  <span>{{ result.type }}</span>
                  <span>{{ result.date.modified || result.date.created | moment('LLL') }}</span>
                  <router-link v-if="result.user.searchable" :class="result.user.roleClass" :to="'/p/' + result.user.name">{{ result.user.name }}</router-link>
                  <span v-else :class="result.user.roleClass">{{ result.user.name }}</span>
                  <span>{{ $t("[-count-] view", { count: result.viewCount }) }}</span>
                  <span>{{ $t("[-count-] star", { count: result.favoriteCount }) }}</span>
                  <span>{{ $t("[-count-] comment", { count: result.commentCount }) }}</span>
                </md-subheader>
                <formatted-text :text="result.description" truncate="180" :plaintext="true"></Formatted-text>
                <div class="searchTags">
                  <md-chip v-for="cat in result.categories" v-bind:key="cat.id" :class="cat.cls" disabled v-if="cat.text">{{ cat.text }}</md-chip>
                </div>        
              </div>      
            </div>
            <advert :ad="'wago728x90-' + Math.ceil(index / 9)" :belowTheFold="index > 10" v-if="!isCollection && (index %9 === 2 || (results.total < 3 && index === results.total - 1))" />
          </template>
        </div>
        <div class="searchResult" v-else-if="!isSearching && results.total === 0">{{ $t("No results found") }}</div>
      </md-layout>

      <md-layout id="searchSide" v-if="results && results.query">
        <md-layout id="searchMeta" v-if="results && results.query">
          <search-meta :meta="results.query.context" :tagMap="tagMap" :textSearch="results.query.textSearch" :sort="sortVal" @setSort="setSort" @setImportType="setImportType" :catRelevance="catRelevance" @setCategoryRelevance="setCategoryRelevance" :filterExpansion="filterExpansion" @setExpansion="setExpansion"></search-meta>
        </md-layout>
      </md-layout>
    </md-layout>
    <p v-if="isSearchingMore">{{ $t("Loading more") }}</p>
  </div>
</template>

<script>
import Categories from '../libs/categories'
export default {
  data: function () {
    return {
      results: {
        total: 0
      },
      searchString: '',
      searchOptions: 'sort: Date',
      floatSideBar: false,
      tagContext: [],
      searchTime: 0,
      tagMap: {},
      isSearching: true,
      isSearchingMore: false,
      sortVal: this.$store.state.user && this.$store.state.user.config && this.$store.state.user.config.searchOptions.sort || 'bestmatch',
      uiSearchValue: false,
      catRelevance: this.$store.state.user && this.$store.state.user.config && this.$store.state.user.config.searchOptions.relevance || 'standard',
      uiRelevanceValue: false,
      filterExpansion: this.$store.state.user && this.$store.state.user.config && this.$store.state.user.config.searchOptions.expansion || 'all',
      uiExpansionValue: false,
      contextSearchData: this.contextSearch,
      isCollection: false
    }
  },
  props: ['contextSearch', 'contextGame'],
  components: {
    'search-meta': require('../UI/SearchMeta.vue'),
    'formatted-text': require('../UI/FormattedText.vue'),
    'placeholder-img': require('../UI/PlaceHolderImage.vue')
  },
  watch: {
    '$route' (to, from) {
      this.searchString = ''
      this.runSearch(false)
    }
  },
  methods: {
    runSearch: function (query) {
      if (!query && this.searchString) {
        var _this = this
        // super hacky but vue.nextTick isn't updating the input value if form is submitted too quickly after typing, so just wait
        return setTimeout(function () {
          if (!_this.searchString) {
            return
          }
          _this.runSearch(_this.searchString)
        }, 100)
      }
      // throttle searches
      if (this.searchTime < +new Date() - 500) {
        this.searchTime = +new Date()
      }
      else {
        return
      }
      var opt = ''
      // if loaded via category menu
      if (this.contextSearchData && !query) {
        this.contextSearchData = this.contextSearchData.replace(this.searchOptions, '')
        this.searchString = this.contextSearchData
        query = this.contextSearchData
      }
      // if loaded direct
      else if (!query && this.$route.params.query) {
        query = this.$route.params.query.replace(/\+/g, ' ').replace(this.searchOptions, '')
        this.searchString = query
      }
      // if loaded as component from other file
      else if (typeof query === 'string' && query) {
        query = query.replace(this.searchOptions.trim(), '')
        // this.$router.push('/search/' + query.replace(/\s+/g, '+'))
        this.searchString = query
      }
      // if navigating forward/back
      else if (this.$route.params.query) {
        query = this.$route.params.query.replace('+', ' ').replace(this.searchOptions, '')
      }
      // something broke, no query found (empty string?)
      else {
        return
      }

      this.isSearching = true

      // check if sort value needs to be added to query
      if (this.uiSearchValue) {
        opt = opt + ' Sort: ' + this.sortVal
      }

      if (this.uiExpansionValue && this.filterExpansion && this.filterExpansion.match(/all|classic|legion|bfa|sl/)) {
        opt = opt + ' Expansion: ' + this.filterExpansion
      }

      // check if we're searching for any localized tags
      const regex = /\btag:\s*"([^"]+)"|\btag:\s*([^\s]+)/ig
      var tagSearch = query.match(regex)
      if (tagSearch && tagSearch.length > 0) {
        // check for relevance if tags are found
        if (this.uiRelevanceValue) {
          opt = opt + ' Relevance: ' + this.catRelevance
        }

        this.tagContext = []
        this.tagMap = {}
        tagSearch.forEach((tagQuery) => {
          var tagMatch
{'fraction_non_alphanumeric': 0.16940112078860306, 'fraction_numerical': 0.0036459388292485314, 'mean_word_length': 2.351889567775515, 'pattern_counts': {'":': 0, '<': 169, '<?xml version=': 0, '>': 171, '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': '4878062', 'n_tokens_mistral': 4564, 'n_tokens_neox': 4355, 'n_words': 884}