chromium/tools/code_coverage/html_templates/table.html

{% if table_entry_type == "Component" %}
<p>
&emsp;Filter: <input type="text" id="filter" size="30" /> (e.g. "crypto,VR")
</p>
{% endif %}
<table>
  <thead>
    <tr>
      <th class="column-entry-bold">{{ table_entry_type }}</th>
      <th class="column-entry-bold" onclick="sortTable(SORT_COLUMN.LINE)" title=
          "Line coverage is the percentage of code lines which have been executed at least once. Only executable lines within function bodies are considered to be code lines.">
        Line Coverage
      </th>
      <th class="column-entry-bold" onclick="sortTable(SORT_COLUMN.FUNCTION)" title=
          "Function coverage is the percentage of functions which have been executed at least once. A function is considered to be executed if any of its instantiations are executed.">
        Function Coverage
      </th>
      <th class="column-entry-bold" onclick="sortTable(SORT_COLUMN.REGION)" title=
          "Region coverage is the percentage of code regions which have been executed at least once. A code region may span multiple lines (e.g in a large function body with no control flow). However, it's also possible for a single line to contain multiple code regions (e.g in 'return x || y &amp;&amp; z').">
        Region Coverage
      </th>
    </tr>
  </thead>
  <tbody>
  {% for entry in entries %}
    <tr class="light-row">
      <td>
        {% if entry["is_dir"] == True %}
          <pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}/</a></pre>
        {% else %}
          <pre><a href='{{ entry["href"] }}'>{{ entry["name"] }}</a></pre>
        {% endif %}
      </td>
      {% for feature in ("lines", "functions", "regions") %}
      <td class='column-entry-{{ entry[feature]["color_class"] }}'>
        <pre>{{ entry[feature]["percentage"] }}% ({{ entry[feature]["covered"] }}/{{ entry[feature]["total"] }})</pre>
      </td>
      {% endfor %}
    </tr>
    {% endfor %}
  </tbody>
  {% if total_entry %}
    <tfoot>
      <tr class="light-row-bold">
        <td>
          <pre>Totals</pre>
        </td>
        {% for feature in ("lines", "functions", "regions") %}
        <td class='column-entry-{{ total_entry[feature]["color_class"] }}'>
          <pre>{{ total_entry[feature]["percentage"] }}% ({{ total_entry[feature]["covered"] }}/{{ total_entry[feature]["total"] }})</pre>
        </td>
        {% endfor %}
      </tr>
    </tfoot>
  {% endif %}
</table>

<script>
  const SORT_COLUMN = {
    LINE: 2,
    FUNCTION: 3,
    REGION: 4,
  }

  const SORT_TYPES = {
    UNSET: -1,
    PERCENT: 0,
    AGGREGATE: 1,
  }

  var SORT_ORDER = {
    [SORT_COLUMN.LINE]: [SORT_TYPES.UNSET],
    [SORT_COLUMN.FUNCTION]: [SORT_TYPES.UNSET],
    [SORT_COLUMN.REGION]: [SORT_TYPES.UNSET],
  }

  function sortTable(columnNumber) {
    SORT_ORDER[columnNumber] = ++SORT_ORDER[columnNumber] % 2;

    let columnSortOrder = SORT_ORDER[columnNumber];
    let tbody = document.getElementsByTagName("tbody")[0];

    [].slice.call(tbody.rows).sort(function(a, b) {
      let aColumn = a.cells[columnNumber-1].textContent;
      let bColumn = b.cells[columnNumber-1].textContent;

      let aColumnCompare, bColumnCompare;
      if (columnSortOrder == SORT_TYPES.PERCENT) {
        aColumnCompare = parseFloat(/([0-9.]+)%/.exec(aColumn)[1]);
        bColumnCompare = parseFloat(/([0-9.]+)%/.exec(bColumn)[1]);
      } else {
        aColumnCompare = parseInt(/\/(\d+)/.exec(aColumn)[1]);
        bColumnCompare = parseInt(/\/(\d+)/.exec(bColumn)[1]);
      }

      return (
          aColumnCompare < bColumnCompare ? -1:
              aColumnCompare > bColumnCompare ? 1 : 0);
    }).forEach(function(value, index) {
      tbody.appendChild(value);
    });
  }

{% if table_entry_type == "Component" %}
  function filterInputChanged() {
    let filter = document.getElementById("filter");
    let filterString = filter.value;

    // Update query paramater in URL.
    let queryParams = new URLSearchParams(window.location.search);
    queryParams.set('filter', filterString);
    let newPath = window.location.pathname;
    if (filterString)
      newPath += '?' + queryParams.toString();
    history.pushState(null, '', newPath);

    filterRowsIfNeeded();
  }

  function filterRowsIfNeeded() {
    let queryParams = new URLSearchParams(window.location.search);
    let filterString = queryParams.get('filter') || "";
    let filterValuesLower = filterString.toLowerCase().split(',');
    let tbody = document.getElementsByTagName("tbody")[0];
    let rows = tbody.getElementsByTagName("tr");
    for (let row of rows) {
      let td = row.getElementsByTagName("td");
      let tdContent = row.innerText.toLowerCase();

      // |match| should be true on empty search (show everything).
      let match = !filterValuesLower;
      for (let filterValueLower of filterValuesLower) {
        if (tdContent.includes(filterValueLower)) {
          match = true;
          break
        }
      }

      if (match && row.style.display == 'none')
        row.style.display = 'table-row';
      else if (!match)
        row.style.display = 'none';
    }

    // Update filter value in input box (for cases when filter is provided
    // as part of page load URL).
    let filter = document.getElementById("filter");
    if (filter.value != filterString)
      filter.value = filterString;
  }

  window.onload = filterRowsIfNeeded;

  var filter = document.getElementById("filter");
  filter.onchange = filter.onkeyup = filterInputChanged;
{% endif %}
</script>