text:
Modernizr.testStyles(' #modernizr { display: run-in; } ', function(elem, rule){
  var ret = (window.getComputedStyle ?
         getComputedStyle(elem, null).getPropertyValue('display') :
         elem.currentStyle['display']);

  Modernizr.addTest('display-runin', ret == 'run-in');
});

redpajama_set_name: RedPajamaGithub


text:
{% extends "order/order_wizard/po_upload.html" %}
{% load inventree_extras %}
{% load i18n %}
{% load static %}
{% load crispy_forms_tags %}

{% block form_alert %}
{% if form.errors %}
{% endif %}
{% if form_errors %}

    {% trans "Errors exist in the submitted data" %}

{% endif %}
{% endblock form_alert %}

{% block form_buttons_top %}
    {% if wizard.steps.prev %}
    <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-outline-secondary">{% trans "Previous Step" %}</button>
    {% endif %}
    <button type="submit" class="save btn btn-outline-secondary">{% trans "Submit Selections" %}</button>
{% endblock form_buttons_top %}

{% block form_content %}

                {% trans "Row" %}
                {% trans "Select Supplier Part" %}
                {% trans "Quantity" %}
                {% for col in columns %}
                {% if col.guess != 'Quantity' %}

                    <input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/>
                    <input type='hidden' name='col_guess_{{ forloop.counter0 }}' value='{{ col.guess }}'/>
                    {% if col.guess %}
                    {{ col.guess }}
                    {% else %}
                    {{ col.name }}
                    {% endif %}

                {% endif %}
                {% endfor %}

 {% comment %} Dummy row for javascript del_row method {% endcomment %}
            {% for row in rows %}

                    <button class='btn btn-outline-secondary btn-remove' onClick='removeRowFromBomWizard()' id='del_row_{{ row.index }}' style='display: inline; float: right;' title='{% trans "Remove row" %}'>

                    </button>

                {% add row.index 1 %}

                    {% for field in form.visible_fields %}
                        {% if field.name == row.item_select %}
                            {{ field }}
                        {% endif %}
                    {% endfor %}
                    {% if row.errors.part %}

{{ row.errors.part }}

                    {% endif %}

                    {% for field in form.visible_fields %}
                        {% if field.name == row.quantity %}
                            {{ field|as_crispy_field }}
                        {% endif %}
                    {% endfor %}
                    {% if row.errors.quantity %}

{{ row.errors.quantity }}

                    {% endif %}

                {% for item in row.data %}
                {% if item.column.guess != 'Quantity' %}

                    {% if item.column.guess == 'Purchase_Price' %}
                        {% for field in form.visible_fields %}
                            {% if field.name == row.purchase_price %}
                                {{ field|as_crispy_field }}
                            {% endif %}
                        {% endfor %}
                    {% elif item.column.guess == 'Reference' %}
                        {% for field in form.visible_fields %}
                            {% if field.name == row.reference %}
                                {{ field|as_crispy_field }}
                            {% endif %}
                        {% endfor %}
                    {% elif item.column.guess == 'Notes' %}
                        {% for field in form.visible_fields %}
                            {% if field.name == row.notes %}
                                {{ field|as_crispy_field }}
                            {% endif %}
                        {% endfor %}
                    {% else %}
                        {{ item.cell }}
                    {% endif %}
                    <input type='hidden' name='row_{{ row.index }}_col_{{ forloop.counter0 }}' value='{{ item.cell }}'/>

                {% endif %}
                {% endfor %}

            {% endfor %}

{% endblock form_content %}

{% block form_buttons_bottom %}
{% endblock form_buttons_bottom %}

{% block js_ready %}
{{ block.super }}

$('.bomselect').select2({
    width: '100%',
    matcher: partialMatcher,
});

$('.currencyselect').select2({
    dropdownAutoWidth: true,
});

{% endblock %}


text:
@interface MOBProjectionEPSG4008 : MOBProjection

@end


text:
/**
  * @jsx React.DOM
  */

var BoxContentBig = require('./BoxContentBig'),
	Graph = require('./Graph'),
	BoxBanner = require('./BoxBanner'),
	actions = require('../actions/Symbols'),
	pollingMixin = require('../mixins/Polling')

module.exports = React.createClass({

	mixins: [pollingMixin],

	getInitialState: function() {
		return {
			size: 'small',
			data: {},
			dataHistory: [],
			error: false
		}
	},
	handlePolledData: function(data) {

		var h = this.state.dataHistory
		h.push(data)

		if (h.length > 20)
			h.shift()

		//Put an id on the data...
		h.forEach(function(d, idx) {
			d.id = idx
		})

		this.setState({
			data: data,
			dataHistory: h
		})
	},

	handlePolledError: function(err) {
		this.setState({error: err})
	},

	componentDidMount: function() {

		this.startListening(this.props.symbol.Symbol, this.handlePolledData, this.handlePolledError)

		//Con reconnect, start polling again. Not working well.. :S
		// io().on('connect', this.startListening)
	},
	componentWillUnmount: function() {
		this.stopListening(this.props.symbol.Symbol, this.handlePolledData)
	},
	changeSize: function() {
		var curr = this.state.size

		var next = curr === 'small'
			? 'big'
			: curr === 'big'
				? 'graph'
				: 'small'

		this.setState({size: next})
	},

	getBoxContent: function(size) {
		switch (size) {
			case 'small':
				return null
			case 'big':
				return <BoxContentBig key={this.state.data.Symbol + 'bigbox'} data={this.state.data} />
			case 'graph':
				return <Graph key={this.state.data.Symbol + 'graph'} data={this.state.dataHistory} y='LastPrice' />
		}
	},
	closeSymbol: function() {
		actions.remove(this.props.symbol)
	},
	render: function() {

		var data = this.state.data,
			color = '',
			arrow = ''

		if (data.Change > 0) {
			color = 'positive'
			arrow = '\u25b2'
		}

		if (data.Change < 0) {
			color = 'negative'
			arrow = '\u25bc'
		}

		var content = Object.keys(this.state.data).length === 0
			?
Waiting for quote...

			: this.getBoxContent(this.state.size)

		if (this.state.error)
			content =
{this.state.error.Message || this.state.error.code || this.state.error}

		return (

				<button className='pull-left' title='Change box size' onClick={this.changeSize}>{this.state.size}</button>
				{this.props.symbol.Symbol} {arrow}
				<button className='pull-right' title='Unselect this stock' onClick={this.closeSymbol}>-</button>

			<BoxBanner color={color} data={data} />
			{content}

)
	}
})


text:
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.thorbenlindhauer.factorgraph;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.github.thorbenlindhauer.factor.Factor;
import com.github.thorbenlindhauer.variable.Variable;

public class FactorGraphNode<T extends Factor<T>> {

  protected Variable variable;
  protected Map<Variable, FactorGraphEdge<T>> edges;

  /** all the factors that the variable represented by this node is involved in */
  protected Set<T> factors;

  public FactorGraphNode(Variable variable) {
    this.variable = variable;
    this.edges = new HashMap<Variable, FactorGraphEdge<T>>();
    this.factors = new HashSet<T>();
  }

  public void addFactor(T factor) {
    this.factors.add(factor);
  }

  public Set<T> getFactors() {
    return factors;
  }

  public Variable getVariable() {
    return variable;
  }

  public Set<FactorGraphNode<T>> getNeighbours() {
    Set<FactorGraphNode<T>> neighbours = new HashSet<FactorGraphNode<T>>();

    for (FactorGraphEdge<T> edge : edges.values()) {
      neighbours.add(edge.getConnectedNode(this));
    }

    return neighbours;
  }

  public boolean isConnectedTo(FactorGraphNode<T> other) {
    return getNeighbours().contains(other);
  }

  /**
   * Idempotent method. May be called multiple times with the same parameter, resulting in at most one edge
   */
  public FactorGraphEdge<T> connectTo(FactorGraphNode<T> other) {
    if (!edges.containsKey(other.variable)) {
      FactorGraphEdge<T> edge = new FactorGraphEdge<T>(this, other);

      this.edges.put(other.variable, edge);
      other.edges.put(this.variable, edge);
    }

    return edges.get(other.variable);
  }

  public Map<Variable, FactorGraphEdge<T>> getEdges() {
    return edges;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    sb.append(variable.getId());
    sb.append("] => [");
    for (Variable connectedVariable : edges.keySet()) {
      sb.append(connectedVariable.getId());
      sb.append(", ");
    }

    sb.append("]");

    return sb.toString();
  }
}


text:
class AddStageTypeToStages < ActiveRecord::Migration[5.0]
  def change
    add_column :stages, :stage_type, :text
  end
end


text:
title: 'Simulations remix: Turn up the base'
excerpt: 'Faster still, with base R'
date: '2021-07-08'
slug: simulations-remix-turn-up-the-base
toc: false
mathjax: true
tags:
  - R
  - Econometrics
---

*Note: I apologise for the title of this post and will show myself the door shortly.*

I wanted to quickly follow up on my last post about [efficient simulations in R]({{ site.url }}/efficient-simulations-in-r). If you recall, in that post we used **data.table** and some other tricks to run 40,000 regressions (i.e. 20k simulations with 2 regressions each) in just over 2 seconds. The question before us today is: **Can we go even faster using only base R?** And it turns out that the answer is, yes, we can.

My motivation for a follow-up is partially the result of [this very nice post](https://elbersb.com/public/posts/interaction_simulation/) by Benjamin Elbers, who replicates my simulation using Julia. In so doing, he demonstrates some of Julia's killer features; most notably the fact that we don't need to think about vectorisation --- e.g. when creating the data --- since Julia's compiler will take care of that for us automatically.[^1] But Ben also does another interesting thing, which is to show the speed gains that come from defining our own (super lean) regression function. He uses Cholesky decomposition and it's fairly straightforward to do the same thing in R. ([Here](https://www.theissaclee.com/post/linearqrandchol/) is a nice tutorial by Issac Lee.)

I was halfway on my way to doing this myself when I stumbled on a [totally different post](https://rpubs.com/maechler/fast_lm) by R Core member, Martin Maechler. Therein he introduces the **`.lm.fit()`** function (note the leading dot), which incurs even less overhead than the `lm.fit()` function I mentioned in my last post. I'm slightly embarrassed to say I had never heard about it until now[^2], but a quick bit of testing "confirms" Martin's more rigorous benchmarks: `.lm.fit` yields a consistent 30-40% improvement over even `lm.fit`.

Now, it would be trivial to amend my previous simulation script to slot in `.lm.fit()` and re-run the benchmarks. But I thought I'd make this a bit more interesting by redoing the whole thing using only base R. (I'll load the **parallel** package, but that comes bundled with the [base distribution](https://stackoverflow.com/a/9705725/4115816) so hardly counts as cheating.) Here's the full script with benchmarks for both sequential and parallel implementations at the bottom.

{% highlight r %}
# Data generation ---------------------------------------------------------

gen_data = function(sims=1) {

  ## Total time periods in the the panel = 500
  tt = 500

  ## x1 covariates
  x1_A = 1 + rnorm(tt*sims, 0, 1)
  x1_B = 1/4 + rnorm(tt*sims, 0, 1)
  x1 = c(x1_A, x1_B)

  ## Add second, nested x2 covariates for each country
  x2_A = 1 + x1_A + rnorm(tt*sims, 0, 1)
  x2_B = 1 + x1_B + rnorm(tt*sims, 0, 1)
  x2 = c(x2_A, x2_B)

  ## Outcomes (notice different slope coefs for x2_A and x2_B)
  y_A = x1_A + 1*x2_A + rnorm(tt*sims, 0, 1)
  y_B = x1_B + 2*x2_B + rnorm(tt*sims, 0, 1)
  y = c(y_A, y_B)

  ## Group variables (id and sim)
  id = as.factor(c(rep('A', length(x1_A)), rep('B', length(x1_B))))
  sim = rep(rep(1L:sims, each = tt), times = length(levels(id)))

  ## Demeaned covariates
  x1_dmean = x1 - ave(x1, list(sim, id), FUN = mean)
  x2_dmean = x2 - ave(x2, list(sim, id), FUN = mean)

  ## Bind in a matrix
  mat = cbind('sim' = sim,
              'id' = id,
              'y' = y,
              'intercept' = 1,
              'x1' = x1,
              'x2' = x2,
              'x1:x2' = x1*x2,
              'x1_dmean:x2_dmean' = x1_dmean * x2_dmean)

  ## Set order i.t.o simulations
  mat = mat[order(mat[, 'sim']), ]

  return(mat)
}

## How many simulations do we want?
n_sims = 2e4

## Generate them all as one big matrix
d = gen_data(n_sims)

## Create index list (for efficient subsetting of the large data matrix)
## Note that each simulation is (2*500=)1000 rows long.
ii = lapply(1L:n_sims-1, function(i) 1L:1e3L + rep(1e3L*(i), each=1e3L))

# Benchmarks --------------------------------------------------------------

library(microbenchmark) ## For high-precision timing
library(parallel)
n_cores = detectCores()

## Convenience function for running the two regressions and extracting the
## interaction coefficients of interest (saves having to retype everything).
## The key bit is the .lm.fit() function.
get_coefs =
  function(dat) {
    level = coef(.lm.fit(dat[, c('intercept', 'x1', 'x2', 'x1:x2', 'id')],
                         dat[, 'y']))[4]
    dmean = coef(.lm.fit(dat[, c('intercept', 'x1', 'x2', 'x1_dmean:x2_dmean', 'id')],
                         dat[, 'y']))[4]
    return(cbind(level, dmean))
  }

## Run the benchmarks for both sequential and parallel versions
microbenchmark(

  sims_sequential = lapply(1:n_sims,
                           function(i) {
                             index = ii[[i]]
                             get_coefs(d[index, ])
                             }),

  sims_parallel = mclapply(1:n_sims,
                           function(i) {
                             index = ii[[i]]
                             get_coefs(d[index, ])
                             },
                           mc.cores = n_cores
                           ),

  times = 1
  )
{% endhighlight %}

{% highlight text %}
## Unit: milliseconds
##             expr    min     lq   mean median     uq    max neval
##  sims_sequential 2278.4 2278.4 2278.4 2278.4 2278.4 2278.4     1
##    sims_parallel  880.4  880.4  880.4  880.4  880.4  880.4     1
{% endhighlight %}

There you have it. Down to _less than a second_ for a simulation involving 40,000 regressions using only base R.[^3] On a laptop, no less. Just incredibly impressive.

**Conclusion:** No grand conclusion today... except a sincere note of gratitude to the R Core team (and Julia devs and so many other OSS maintainers) for providing us with such an incredible base to build from.

P.S. Achim Zeileis (who else?) has another great tip for speeding up simulations where the experimental design is fixed [here](https://twitter.com/AchimZeileis/status/1413407892556947465).

[^1]: In this house, we stan both R and Julia.

[^2]: I think Dirk Eddelbuettel had mentioned it to me, but I hadn't grokked the difference.

[^3]: Interestingly enough, this knitted R markdown version is a bit slower than when I run the script directly in my R console. But we're really splitting hairs now. (As an aside: I won't bother plotting the results, but you're welcome to run the simulation yourself and confirm that it yields the same insights as my previous post.)


text:
class CleanupAppearancesSchema < ActiveRecord::Migration[4.2]
  include Gitlab::Database::MigrationHelpers

  # Set this constant to true if this migration requires downtime.
  DOWNTIME = false

  NOT_NULL_COLUMNS = %i[title description created_at updated_at]

  TIME_COLUMNS = %i[created_at updated_at]

  def up
    NOT_NULL_COLUMNS.each do |column|
      change_column_null :appearances, column, false
    end

    TIME_COLUMNS.each do |column|
      change_column :appearances, column, :datetime_with_timezone
    end
  end

  def down
    NOT_NULL_COLUMNS.each do |column|
      change_column_null :appearances, column, true
    end

    TIME_COLUMNS.each do |column|
      change_column :appearances, column, :datetime # rubocop: disable Migration/Datetime
    end
  end
end


text:
#include "config.h"
#include "platform/image-decoders/gif/GIFImageDecoder.h"

#include <limits>
#include "platform/image-decoders/gif/GIFImageReader.h"
#include "wtf/NotFound.h"
#include "wtf/PassOwnPtr.h"

namespace blink {

GIFImageDecoder::GIFImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption colorOptions, size_t maxDecodedBytes)
    : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes)
    , m_repetitionCount(cAnimationLoopOnce)
{
}

GIFImageDecoder::~GIFImageDecoder()
{
}

void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
{
    if (failed())
        return;

    ImageDecoder::setData(data, allDataReceived);
    if (m_reader)
        m_reader->setData(data);
}

int GIFImageDecoder::repetitionCount() const
{
    // This value can arrive at any point in the image data stream.  Most GIFs
    // in the wild declare it near the beginning of the file, so it usually is
    // set by the time we've decoded the size, but (depending on the GIF and the
    // packets sent back by the webserver) not always.  If the reader hasn't
    // seen a loop count yet, it will return cLoopCountNotSeen, in which case we
    // should default to looping once (the initial value for
    // |m_repetitionCount|).
    //
    // There are some additional wrinkles here. First, ImageSource::clear()
    // may destroy the reader, making the result from the reader _less_
    // authoritative on future calls if the recreated reader hasn't seen the
    // loop count.  We don't need to special-case this because in this case the
    // new reader will once again return cLoopCountNotSeen, and we won't
    // overwrite the cached correct value.
    //
    // Second, a GIF might never set a loop count at all, in which case we
    // should continue to treat it as a "loop once" animation.  We don't need
    // special code here either, because in this case we'll never change
    // |m_repetitionCount| from its default value.
    //
    // Third, we use the same GIFImageReader for counting frames and we might
    // see the loop count and then encounter a decoding error which happens
    // later in the stream. It is also possible that no frames are in the
    // stream. In these cases we should just loop once.
    if (isAllDataReceived() && parseCompleted() && m_reader->imagesCount() == 1)
        m_repetitionCount = cAnimationNone;
    else if (failed() || (m_reader && (!m_reader->imagesCount())))
        m_repetitionCount = cAnimationLoopOnce;
    else if (m_reader && m_reader->loopCount() != cLoopCountNotSeen)
        m_repetitionCount = m_reader->loopCount();
    return m_repetitionCount;
}

bool GIFImageDecoder::frameIsCompleteAtIndex(size_t index) const
{
    return m_reader && (index < m_reader->imagesCount()) && m_reader->frameContext(index)->isComplete();
}

float GIFImageDecoder::frameDurationAtIndex(size_t index) const
{
    return (m_reader && (index < m_reader->imagesCount()) &&
        m_reader->frameContext(index)->isHeaderDefined()) ?
        m_reader->frameContext(index)->delayTime() : 0;
}

bool GIFImageDecoder::setFailed()
{
    m_reader.clear();
    return ImageDecoder::setFailed();
}

bool GIFImageDecoder::haveDecodedRow(size_t frameIndex, GIFRow::const_iterator rowBegin, size_t width, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels)
{
    const GIFFrameContext* frameContext = m_reader->frameContext(frameIndex);
    // The pixel data and coordinates supplied to us are relative to the frame's
    // origin within the entire image size, i.e.
    // (frameContext->xOffset, frameContext->yOffset). There is no guarantee
    // that width == (size().width() - frameContext->xOffset), so
    // we must ensure we don't run off the end of either the source data or the
    // row's X-coordinates.
    const int xBegin = frameContext->xOffset();
    const int yBegin = frameContext->yOffset() + rowNumber;
    const int xEnd = std::min(static_cast<int>(frameContext->xOffset() + width), size().width());
    const int yEnd = std::min(static_cast<int>(frameContext->yOffset() + rowNumber + repeatCount), size().height());
    if (!width || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin))
        return true;

    const GIFColorMap::Table& colorTable = frameContext->localColorMap().isDefined() ? frameContext->localColorMap().table() : m_reader->globalColorMap().table();

    if (colorTable.isEmpty())
        return true;

    GIFColorMap::Table::const_iterator colorTableIter = colorTable.begin();

    // Initialize the frame if necessary.
    ImageFrame& buffer = m_frameBufferCache[frameIndex];
    if ((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex))
        return false;

    const size_t transparentPixel = frameContext->transparentPixel();
    GIFRow::const_iterator rowEnd = rowBegin + (xEnd - xBegin);
    ImageFrame::PixelData* currentAddress = buffer.getAddr(xBegin, yBegin);

    // We may or may not need to write transparent pixels to the buffer.
    // If we're compositing against a previous image, it's wrong, and if
    // we're writing atop a cleared, fully transparent buffer, it's
    // unnecessary; but if we're decoding an interlaced gif and
    // displaying it "Haeberli"-style, we must write these for passes
    // beyond the first, or the initial passes will "show through" the
    // later ones.
    //
    // The loops below are almost identical. One writes a transparent pixel
    // and one doesn't based on the value of |writeTransparentPixels|.
    // The condition check is taken out of the loop to enhance performance.
    // This optimization reduces decoding time by about 15% for a 3MB image.
    if (writeTransparentPixels) {
        for (; rowBegin != rowEnd; ++rowBegin, ++currentAddress) {
            const size_t sourceValue = *rowBegin;
            if ((sourceValue != transparentPixel) && (sourceValue < colorTable.size())) {
                *currentAddress = colorTableIter[sourceValue];
            } else {
                *currentAddress = 0;
                m_currentBufferSawAlpha = true;
            }
        }
    } else {
        for (; rowBegin != rowEnd; ++rowBegin, ++currentAddress) {
            const size_t sourceValue = *rowBegin;
            if ((sourceValue != transparentPixel) && (sourceValue < colorTable.size()))
                *currentAddress = colorTableIter[sourceValue];
            else
                m_currentBufferSawAlpha = true;
        }
    }

    // Tell the frame to copy the row data if need be.
    if (repeatCount > 1)
        buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd);

    buffer.setPixelsChanged(true);
    return true;
}

bool GIFImageDecoder::parseCompleted() const
{
    return m_reader && m_reader->parseCompleted();
}

bool GIFImageDecoder::frameComplete(size_t frameIndex)
{
    // Initialize the frame if necessary.  Some GIFs insert do-nothing frames,
    // in which case we never reach haveDecodedRow() before getting here.
    ImageFrame& buffer = m_frameBufferCache[frameIndex];
    if ((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex))
        return false; // initFrameBuffer() has already called setFailed().

    buffer.setStatus(ImageFrame::FrameComplete);

    if (!m_currentBufferSawAlpha) {
        // The whole frame was non-transparent, so it's possible that the entire
        // resulting buffer was non-transparent, and we can setHasAlpha(false).
        if (buffer.originalFrameRect().contains(IntRect(IntPoint(), size()))) {
            buffer.setHasAlpha(false);
            buffer.setRequiredPreviousFrameIndex(kNotFound);
        } else if (buffer.requiredPreviousFrameIndex() != kNotFound) {
            // Tricky case.  This frame does not have alpha only if everywhere
            // outside its rect doesn't have alpha.  To know whether this is
            // true, we check the start state of the frame -- if it doesn't have
            // alpha, we're safe.
            const ImageFrame* prevBuffer = &m_frameBufferCache[buffer.requiredPreviousFrameIndex()];
            ASSERT(prevBuffer->disposalMethod() != ImageFrame::DisposeOverwritePrevious);

            // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then
            // we can say we have no alpha if that frame had no alpha.  But
            // since in initFrameBuffer() we already copied that frame's alpha
            // state into the current frame's, we need do nothing at all here.
            //
            // The only remaining case is a DisposeOverwriteBgcolor frame.  If
            // it had no alpha, and its rect is contained in the current frame's
            // rect, we know the current frame has no alpha.
            if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect()))
                buffer.setHasAlpha(false);
        }
    }

    return true;
}

size_t GIFImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
{
    // We need to preserve frames such that:
    //  1. We don't clear |clearExceptFrame|;
    //  2. We don't clear any frame from which a future initFrameBuffer() call
    //     will copy bitmap data.
    // All other frames can be cleared.
    while ((clearExceptFrame < m_frameBufferCache.size()) && (m_frameBufferCache[clearExceptFrame].status() == ImageFrame::FrameEmpty))
        clearExceptFrame = m_frameBufferCache[clearExceptFrame].requiredPreviousFrameIndex();

    return ImageDecoder::clearCacheExceptFrame(clearExceptFrame);
}

void GIFImageDecoder::clearFrameBuffer(size_t frameIndex)
{
    if (m_reader && m_frameBufferCache[frameIndex].status() == ImageFrame::FramePartial) {
        // Reset the state of the partial frame in the reader so that the frame
        // can be decoded again when requested.
        m_reader->clearDecodeState(frameIndex);
    }
    ImageDecoder::clearFrameBuffer(frameIndex);
}

size_t GIFImageDecoder::decodeFrameCount()
{
    parse(GIFFrameCountQuery);
    // If decoding fails, |m_reader| will have been destroyed.  Instead of
    // returning 0 in this case, return the existing number of frames.  This way
    // if we get halfway through the image before decoding fails, we won't
    // suddenly start reporting that the image has zero frames.
    return failed() ? m_frameBufferCache.size() : m_reader->imagesCount();
}

void GIFImageDecoder::initializeNewFrame(size_t index)
{
    ImageFrame* buffer = &m_frameBufferCache[index];
    const GIFFrameContext* frameContext = m_reader->frameContext(index);
    buffer->setOriginalFrameRect(intersection(frameContext->frameRect(), IntRect(IntPoint(), size())));
    buffer->setDuration(frameContext->delayTime());
    buffer->setDisposalMethod(frameContext->disposalMethod());
    buffer->setRequiredPreviousFrameIndex(findRequiredPreviousFrame(index, false));
}

void GIFImageDecoder::decode(size_t index)
{
    parse(GIFFrameCountQuery);

    if (failed())
        return;

    Vector<size_t> framesToDecode;
    size_t frameToDecode = index;
    do {
        framesToDecode.append(frameToDecode);
        frameToDecode = m_frameBufferCache[frameToDecode].requiredPreviousFrameIndex();
    } while (frameToDecode != kNotFound && m_frameBufferCache[frameToDecode].status() != ImageFrame::FrameComplete);

    for (auto i = framesToDecode.rbegin(); i != framesToDecode.rend(); ++i) {
        if (!m_reader->decode(*i)) {
            setFailed();
            return;
        }

        // We need more data to continue decoding.
        if (m_frameBufferCache[*i].status() != ImageFrame::FrameComplete)
            break;
    }

    // It is also a fatal error if all data is received and we have decoded all
    // frames available but the file is truncated.
    if (index >= m_frameBufferCache.size() - 1 && isAllDataReceived() && m_reader && !m_reader->parseCompleted())
        setFailed();
}

void GIFImageDecoder::parse(GIFParseQuery query)
{
    if (failed())
        return;

    if (!m_reader) {
        m_reader = adoptPtr(new GIFImageReader(this));
        m_reader->setData(m_data);
    }

    if (!m_reader->parse(query))
        setFailed();
}

bool GIFImageDecoder::initFrameBuffer(size_t frameIndex)
{
    // Initialize the frame rect in our buffer.
    ImageFrame* const buffer = &m_frameBufferCache[frameIndex];

    size_t requiredPreviousFrameIndex = buffer->requiredPreviousFrameIndex();
    if (requiredPreviousFrameIndex == kNotFound) {
        // This frame doesn't rely on any previous data.
        if (!buffer->setSize(size().width(), size().height()))
            return setFailed();
    } else {
        const ImageFrame* prevBuffer = &m_frameBufferCache[requiredPreviousFrameIndex];
        ASSERT(prevBuffer->status() == ImageFrame::FrameComplete);

        // Preserve the last frame as the starting state for this frame.
        if (!buffer->copyBitmapData(*prevBuffer))
            return setFailed();

        if (prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) {
            // We want to clear the previous frame to transparent, without
            // affecting pixels in the image outside of the frame.
            const IntRect& prevRect = prevBuffer->originalFrameRect();
            ASSERT(!prevRect.contains(IntRect(IntPoint(), size())));
            buffer->zeroFillFrameRect(prevRect);
        }
    }

    // Update our status to be partially complete.
    buffer->setStatus(ImageFrame::FramePartial);

    // Reset the alpha pixel tracker for this frame.
    m_currentBufferSawAlpha = false;
    return true;
}

} // namespace blink


text:
package middleware

import (
	"fmt"

	"github.com/docker/distribution"
)

// InitFunc is the type of a RepositoryMiddleware factory function and is
// used to register the constructor for different RepositoryMiddleware backends.
type InitFunc func(repository distribution.Repository, options map[string]interface{}) (distribution.Repository, error)

var middlewares map[string]InitFunc

// Register is used to register an InitFunc for
// a RepositoryMiddleware backend with the given name.
func Register(name string, initFunc InitFunc) error {
	if middlewares == nil {
		middlewares = make(map[string]InitFunc)
	}
	if _, exists := middlewares[name]; exists {
		return fmt.Errorf("name already registered: %s", name)
	}

	middlewares[name] = initFunc

	return nil
}

// Get constructs a RepositoryMiddleware with the given options using the named backend.
func Get(name string, options map[string]interface{}, repository distribution.Repository) (distribution.Repository, error) {
	if middlewares != nil {
		if initFunc, exists := middlewares[name]; exists {
			return initFunc(repository, options)
		}
	}

	return nil, fmt.Errorf("no repository middleware registered with name: %s", name)
}


text:
class CreateFormElements < ActiveRecord::Migration[4.2]
  def change
    create_table :form_elements do |t|
      t.references :form, index: true, foreign_key: true
      t.string :label
      t.string :data_type
      t.string :field_type
      t.string :default_value
      t.boolean :required
      t.boolean :visible

      t.timestamps null: false
    end
  end
end


text:
[![Latest Version on Packagist](https://img.shields.io/packagist/v/laravel-notification-channels/discord.svg?style=flat-square)](https://packagist.org/packages/laravel-notification-channels/discord)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Build Status](https://img.shields.io/github/workflow/status/laravel-notification-channels/discord/PHP.svg?style=flat-square)](https://github.com/laravel-notification-channels/discord/actions)
[![StyleCI](https://styleci.io/repos/65772492/shield)](https://styleci.io/repos/65772492)
[![Quality Score](https://img.shields.io/scrutinizer/g/laravel-notification-channels/discord.svg?style=flat-square)](https://scrutinizer-ci.com/g/laravel-notification-channels/discord)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/laravel-notification-channels/discord/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/laravel-notification-channels/discord/?branch=master)
[![Total Downloads](https://img.shields.io/packagist/dt/laravel-notification-channels/discord.svg?style=flat-square)](https://packagist.org/packages/laravel-notification-channels/discord)

This package makes it easy to send notifications using the [Discord bot API](https://discord.com/developers/docs/intro) with Laravel.

## Contents

- [Discord notification channel for Laravel 6.0+](#discord-notification-channel-for-laravel-56)
    - [Contents](#contents)
    - [Installation](#installation)
        - [Setting up your Discord bot](#setting-up-your-discord-bot)
    - [Usage](#usage)
        - [Available Message methods](#available-message-methods)
    - [Changelog](#changelog)
    - [Testing](#testing)
    - [Security](#security)
    - [Contributing](#contributing)
    - [Credits](#credits)
    - [License](#license)

## Installation

You can install the package via composer:

```bash
composer require laravel-notification-channels/discord
```

Next, you must load the service provider:

```php
// config/app.php
'providers' => [
    // ...
    NotificationChannels\Discord\DiscordServiceProvider::class,
],
```

### Setting up your Discord bot

1. [Create a Discord application.](https://discord.com/developers/applications)
2. Click the `Create a Bot User` button on your Discord application.
3. Paste your bot's API token, found under `App Bot User`, in your `services.php` config file:

    ```php
    // config/services.php
    'discord' => [
        'token' => 'YOUR_API_TOKEN',
    ],
    ```

4. Add the bot to your server and identify it by running the artisan command:

    ```shell
    php artisan discord:setup
    ```

## Usage

In every model you wish to be notifiable via Discord, you must add a channel ID property to that model accessible through a `routeNotificationForDiscord` method:

```php
class Guild extends Eloquent
{
    use Notifiable;

    public function routeNotificationForDiscord()
    {
        return $this->discord_channel;
    }
}
```

> **NOTE**: Discord handles direct messages as though they are a regular channel. If you wish to allow users to receive direct messages from your bot, you will need to create a private channel with that user.
>
> An example workflow may look like the following:
>
> 1. Your `users` table has two discord columns: `discord_user_id` and `discord_private_channel_id`
> 2. When a user updates their Discord user ID (`discord_user_id`), generate and save a private channel ID (`discord_private_channel_id`)
> 3. Return the user's `discord_private_channel_id` in the `routeNotificationForDiscord` method on the `User` model
>
> You can generate direct message channels by using the `getPrivateChannel` method in the `NotificationChannels\Discord\Discord` class
>
> ```php
> use NotificationChannels\Discord\Discord;
>
> class UserDiscordSettingsController
> {
>     public function store(Request $request)
>     {
>         $userId = $request->input('discord_user_id');
>         $channelId = app(Discord::class)->getPrivateChannel($userId);
>
>         Auth::user()->update([
>             'discord_user_id' => $userId,
>             'discord_private_channel_id' => $channelId,
>         ]);
>     }
> }
> ```
>
> Please take note that the `getPrivateChannel` method only accepts [Discord's snowflake IDs](https://discord.com/developers/docs/reference#snowflakes). There is no API route provided by Discord to lookup a user's ID by their name and tag, and the process for copying and pasting a user ID can be confusing to some users. Because of this, it is recommended to add the option for users to connect their Discord account to their account within your application either by logging in with Discord or linking it to their pre-existing account.

You may now tell Laravel to send notifications to Discord channels in the `via` method:

```php
// ...
use NotificationChannels\Discord\DiscordChannel;
use NotificationChannels\Discord\DiscordMessage;

class GameChallengeNotification extends Notification
{
    public $challenger;

    public $game;

    public function __construct(Guild $challenger, Game $game)
    {
        $this->challenger = $challenger;
        $this->game = $game;
    }

    public function via($notifiable)
    {
        return [DiscordChannel::class];
    }

    public function toDiscord($notifiable)
    {
        return DiscordMessage::create("You have been challenged to a game of *{$this->game->name}* by **{$this->challenger->name}**!");
    }
}
```

### Available Message methods

* `body(string)`: Set the content of the message. ([Supports basic markdown](https://support.discord.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline-))
* `embed(array)`: Set the embedded content. ([View embed structure](https://discord.com/developers/docs/resources/channel#embed-object))

## Changelog

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

## Testing

```bash
$ composer test
```

## Security

If you discover any security related issues, please email cs475x@icloud.com instead of using the issue tracker.

## Contributing

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

## Credits

- [Cody Scott](https://github.com/codyphobe)
- [All Contributors](../../contributors)

## License

The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.


text:
document.addEventListener('DOMContentLoaded', load, false);

function load() {
  var doc = document.getElementById("content");
  removePreTags(doc);
  removeEscapedPipes(doc);
  removeEscapedHashes(doc);
  escapeHtml(doc);
  processBody(doc);
  tabulateExamples(doc);
  replaceRemovedEscapedPipes(doc);
  replaceRemovedEscapedHashes(doc);

  var fontLink = document.createElement('link');
  fontLink.rel = 'stylesheet';
    fontLink.type = 'text/css';
    fontLink.href = 'OpenSans.css';
    document.head.appendChild(fontLink);

}

function escapeHtml(doc) {
    doc.innerHTML = doc.innerHTML.replace(/</g, "<");
    doc.innerHTML = doc.innerHTML.replace(/>/g, ">");
    doc.innerHTML = doc.innerHTML.replace(/"/g, """);
    doc.innerHTML = doc.innerHTML.replace(/'/g, "'");
}

function tabulateExamples(doc) {
    wrapExamplesInPreTags(doc);
    // Replace first pipe in table
  doc.innerHTML = doc.innerHTML.replace(/^(\s*)\|\s*/gm, '$1');
  // Remove last pipe and any trailing whitespace
  doc.innerHTML = doc.innerHTML.replace(/[ \t]+\|\s*$/gm, '');
  // Trim any remaining whitespace around pipes
  doc.innerHTML = doc.innerHTML.replace(/[ \t]*(\|)[\w]*[ \t]*/g, '$1');

    processTables(doc);
}

function removeEscapedPipes(doc) {
    doc.innerHTML = doc.innerHTML.replace(/\\\|/gmi, '@@@£££@@@');
}

function replaceRemovedEscapedPipes(doc) {
    doc.innerHTML = doc.innerHTML.replace(/\@\@\@£££\@\@\@/gmi, '\\\|');
}

function removeEscapedHashes(doc) {
    doc.innerHTML = doc.innerHTML.replace(/\\\#/gmi, '@@@$$$@@@');
}

function replaceRemovedEscapedHashes(doc) {
    doc.innerHTML = doc.innerHTML.replace(/\@\@\@\$\$\$\@\@\@/gmi, '\\\#');
}

function processTables(doc) {
    var table = '';
    var rows = new Array();
    var columnChars;
    var tableId = "1";
    var currentTableId = "1";
    var columnsInCurrentTable;
    var columnCharLength = [];
    columnCharLength[0] = 0;

    var Tables = document.getElementsByClassName('exampleTable');
    for (var k = 0; k < Tables.length; k++) {
        rows = Tables[k].innerHTML.split('\n');
        table = '
';
        currentTableId = Tables[k].getAttribute('data-table-id');
        if(currentTableId != tableId){
            // do the replace on table with the value of columnCharlength
            //table = table.replace(/\^xx\^/g, columnCharLength);
            for(var i = 0; i < columnsInCurrentTable + 1; i++){
                var re = new RegExp("\\^xxcol" + i + "\\^","g");
                doc.innerHTML = doc.innerHTML.replace(re, columnCharLength[i]);
            }
            tableId = currentTableId;
            columnCharLength = [];
            columnCharLength[0] = 0;
        }

        for(var i = 0; i < rows.length-1; i++) {
            var columns = rows[i].split('|');
            table += '
';

            for(var j = 0; j < columns.length; j++) {
                columnsInCurrentTable = j;
                if(columns[j] == ''){
                    table += 'NO VALUE	';
                    if(columnCharLength[j] < 8) {
                        columnCharLength[j] = 8;
                    }
                    if(rows[i]=='|'){ j++; } // skip the next column
                } else {
                    table += '' + columns[j] + '	';
                    if(columnCharLength[j] < columns[j].length || columnCharLength[j] == undefined) {
                        columnCharLength[j] = columns[j].length;
                    }
                }
            }
            table += '
';
        }

        table += '
';
        Tables[k].innerHTML = table;
    }

    for(var i = 0; i < columnsInCurrentTable + 1; i++){
        var re = new RegExp("\\^xxcol" + i + "\\^","g");
        doc.innerHTML = doc.innerHTML.replace(re, columnCharLength[i]);
    }

}

  function generateId() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }

function addFeatureToToc(featureTitle, genId) {
  var featureLink = document.createElement("a");
  featureLink.href = "#" + genId;
  featureLink.innerHTML = featureTitle;
  var featureScenarioList = document.createElement("ol");
  featureScenarioList.classList.add("sectlevel2");
  var featureItem = document.createElement("li");
  featureItem.classList.add("sectlevel1");
  featureItem.appendChild(featureLink);
  featureItem.appendChild(featureScenarioList);
  var toclist = document.getElementById("toclist");
  toclist.appendChild(featureItem);
}

function addScenarioToToc(scenarioTitle, genId) {
  var scenarioLink = document.createElement("a");
  scenarioLink.href = "#" + genId;
  scenarioLink.innerHTML = scenarioTitle;

  var scenarioItem = document.createElement("li");
  scenarioItem.classList.add("sectlevel2");
  scenarioItem.appendChild(scenarioLink);

  var toclist = document.getElementById("toclist");
  toclist.lastElementChild.lastElementChild.appendChild(scenarioItem);
}

function processBody(doc) {

  // Doc String vars
  var currentlyInsideDocString = false;
    var docStringTagOpen = '
\n
';
  var docStringTagClose = '
\n
\n';
    var docStringRegexp = /^"""/gmi;

  // Comment vars
  var currentlyInsideComment = false;
  var commentOpeningReplacementString = '

$2
\n';
  var commentMiddleReplacementString = '
$2
\n';
  var commentTagClose = '
\n';
    var commentRegexp = /^(\s*#\s*)(.*)/gmi;

  // Feature vars
  var currentlyInsideFeatureDescription = false;
    var featureTagOpen = '

\n';
  var featureTagClose = '

\n';
    var featureRegexp = /^(Feature|Fonctionnalité):\s*(.*)/gmi;

  // Annotation vars
  var currentlyProcessingAnnotations = false;
    var annotationTagOpen = '
\n tag(s) ';
  var annotationTagClose = '
\n';
  var annotationNameTagOpen = '';
  var annotationNameTagClose = '';
    var annotationRegexp = /^@.*/gmi;

  // Scenario vars
  var scenarioReplacementString = '
$2
\n';
    var scenarioRegexp = /(Sc[eé]n.*:[ \t]*)(.*)/gmi;

  // Background vars
    var backgroundTagOpen = '

';
  var backgroundTagClose = '
\n';
    var backgroundRegexp = /(Background|Contexte):.*/gmi;

  // Example vars
  var examplesReplacementString = '
$1 $2
\n';
    var examplesRegexp = /^(Ex[ae]mples.*:)[ \t]*(.*)/gmi;

  // Keyword vars
    var keywordReplacementString = '
$1$2
';
    var keywordRegexp = /^(Given|When|Then|And|But|Etant donné|Et|Alors|Quand)(.*)/gmi;

  // Parameter vars
  var parameterReplacementString = '$1';
  var parameterRegexp = /"?<(.*?)>"?/gmi;

  // Split all by \n
    linesArray = doc.innerHTML.split("\n");

  var parsedText = '';

    // Process array
    for (var i = 0; i < linesArray.length; i++) {
        var lineText = linesArray[i];

      // Get the line text to be processed
    lineTextLeadingWhitespaceStripped = lineText.replace(/^[ \t]+/gm, '');

    // This block preserves layout inside a pre tag for docStrings - make json look better
     if (!currentlyInsideDocString || lineText.match(/^\s*"""/gmi) != null) {
      lineText = lineTextLeadingWhitespaceStripped;
    }

        // Look for a match on """
        quotesMatch = lineText.match(docStringRegexp);

    // If the lineText includes """ and we're not already inside a docString
    if (quotesMatch != null) {
            if (!currentlyInsideDocString) {
        lineText = docStringTagOpen;
                currentlyInsideDocString = true;
            }
            else {
        lineText = docStringTagClose;
                currentlyInsideDocString = false;
            }
    }

    // Look for a match on #
        commentMatch = lineText.match(commentRegexp);

    // If the lineText includes # and we're not already inside a comment
    if (commentMatch != null && !currentlyInsideDocString) {
            if (!currentlyInsideComment) {
        lineText = lineText.replace(commentRegexp, commentOpeningReplacementString);
      } else {
        lineText = lineText.replace(commentRegexp, commentMiddleReplacementString);
      }
      currentlyInsideComment = true;
    } else {
      if (currentlyInsideComment) {
        lineText = commentTagClose + lineText;
                currentlyInsideComment = false;
      }
    }

    // Look for a match on Feature
        featureMatch = lineText.match(featureRegexp);

    // If the lineText includes Feature: and we're not already inside a feature description
    if (featureMatch != null && !currentlyInsideFeatureDescription && !currentlyInsideDocString) {
            if (!currentlyInsideFeatureDescription) {
                var genId = generateId();
                addFeatureToToc(lineText.replace(featureRegexp,'$2'), genId);
                lineText = lineText.replace(featureRegexp,  '
Feature
' + featureTagOpen + '$2');
                currentlyInsideFeatureDescription = true;
            }
    }
    else {
      if (currentlyInsideFeatureDescription && lineText.match(/Background:|Scenario:|Scenario Outline:|Contexte:|Scénario:|Plan du Scénario:|@.*|#.*|"""/gmi) != null) {
        lineText = featureTagClose + lineText;
        currentlyInsideFeatureDescription = false;
      }
    }

    // Look for a match on Annotations e.g. @tag
    annotationMatch = lineText.match(annotationRegexp);

    // If the lineText includes @tag and we're not already processing tags on a line
    if (annotationMatch != null && !currentlyInsideDocString && !currentlyInsideFeatureDescription) {

        if (!currentlyProcessingAnnotations) {
          lineText = lineText.replace(/(@[^\s]*)/mi, annotationTagOpen + '$1');
          lineText = lineText.replace(/@([^\s]*)/gmi, annotationNameTagOpen + '$1' + annotationNameTagClose);
          //lineText = annotationTagOpen + lineText;
        } else {
          lineText = lineText.replace(/@([^\s]*)/gmi, annotationNameTagOpen + '$1' + annotationNameTagClose);
        }
        currentlyProcessingAnnotations = true;
    }
    else {
      if (currentlyProcessingAnnotations) {
        lineText = annotationTagClose + lineText;
        currentlyProcessingAnnotations = false;
      }
    }

    // Look for a match on Scenario
    scenarioMatch = lineText.match(scenarioRegexp);

    // If the lineText includes Scenario: or Scenario Outline:
    if (scenarioMatch != null && !currentlyInsideDocString && !currentlyInsideComment && !currentlyInsideFeatureDescription) {
        var genId = generateId();
        addScenarioToToc(lineText.replace(scenarioRegexp,'$2'), genId);
        lineText = '' + lineText;
        lineText = lineText.replace(scenarioRegexp, scenarioReplacementString);
    }

    // Look for a match on Background
    backgroundMatch = lineText.match(backgroundRegexp);

    // If the lineText includes Background:
    if (backgroundMatch != null && !currentlyInsideDocString && !currentlyInsideComment) {
        lineText = lineText.replace(backgroundRegexp, backgroundTagOpen + '$1' + backgroundTagClose);
    }

    // Look for a match on Examples
    examplesMatch = lineText.match(examplesRegexp);

    // If the lineText includes Examples:
    if (examplesMatch != null && !currentlyInsideDocString && !currentlyInsideComment && !currentlyInsideFeatureDescription) {
        lineText = lineText.replace(examplesRegexp, examplesReplacementString);
    }

    // Look for a match on Keywords
    keywordMatch = lineText.match(keywordRegexp);

    // If the lineText includes Given, When, Then...
    if (keywordMatch != null && !currentlyInsideDocString && !currentlyInsideComment && !currentlyInsideFeatureDescription) {
        lineText = lineText.replace(keywordRegexp, keywordReplacementString);
    }

    // Look for a match on Parameters
    parameterMatch = lineText.match(parameterRegexp);

    // If the lineText includes <parameter>..
    if (parameterMatch != null && !currentlyInsideDocString && !currentlyInsideComment && !currentlyInsideFeatureDescription) {
        lineText = lineText.replace(parameterRegexp, parameterReplacementString);
    }

    // Find next instance of newline
        if(i == linesArray.length - 1) {
      if (currentlyInsideComment) {
        lineText = lineText + "\n" + commentTagClose;
      }
      if (currentlyInsideFeatureDescription) {
        lineText = lineText + "\n" + featureTagClose;
      }
      if (currentlyProcessingAnnotations){
        lineText = lineText + "\n" + annotationTagClose;
      }
      if (currentlyInsideDocString){
        lineText = lineText + "\n" + preTagClose;
      }
      linesArray[i] = lineText;
            break;
        }

    linesArray[i] = lineText;
  }

  var newInnerHTML = "";
  // reconstruct innerHTML from array
  for (var i = 0; i < linesArray.length; i++) {
    newInnerHTML += linesArray[i] + "\n";
  }
  newInnerHTML = newInnerHTML.replace(/\n+$/m, "");

  doc.innerHTML = newInnerHTML;
}

function wrapExamplesInPreTags(doc) {

    var previousLineContainsPipe = false;
    var startOfLine = 0;
    var endOfLine = 0;
    var textToParse = doc.innerHTML;
    var textToParseRemainder = textToParse;
    var lineText = '';
    var preTagOpenTemplate = '
\n\n';
    var preTagOpen;
    var preTagClose = '
\n';
    var positionOfNextLineBreak = 0;

    var pipesRegexp = /\|/gmi;
    var escapedPipesRegexp = /\\\|/gmi;
    var scenarioLineRegexp = /
/g;
    var exampleTextRegexp = /Examples:/g;
    var tagLineRegexp = /^
/g;
    var pipesMatchCount;
    var escapedPipesMatchCount;
    var isScenarioLineOrTagLineOrNextStepLine;
    var numberOfRowsSinceRowWithPipe = 0;
    var dataTableId = 1;
    var isFirstExampleRow = true;
    var isATableOfExamples = false; // as opposed to just a table of data
    var isInsideDocString = false;  // we do nothing with tables if inside a DocString
    var docStringRegexp = /
/g;
    var preTagCloseRegexp = /<\/pre>/g;

    while (positionOfNextLineBreak != -1) {

        // Find the next line break
        positionOfNextLineBreak = textToParseRemainder.indexOf("\n");

        // Find next instance of newline
        if (positionOfNextLineBreak == -1) {
            endOfLine = textToParse.length;
            textToParse = textToParse + "\n" + preTagClose;
            break;
        } else {
            endOfLine += positionOfNextLineBreak + 1; // Since indexOf is zero-based
        }

        // Get the line text to be processed
        lineText = textToParse.substring(startOfLine, endOfLine);

        // strip leading whitespace
        lineText = lineText.replace(/^[ \t]*\|/gm, '');

        // Get the number of pipes in the line
        pipesMatchCount = (lineText.match(pipesRegexp) || []).length;

        // If this looks like the start of a docString...
        if ((lineText.match(docStringRegexp) || []).length > 0) {
            isInsideDocString = true;
        }

        // If we're not inside a docString
        if (!isInsideDocString) {

            // Get the number of escaped pipes in the line \|
            escapedPipesMatchCount = (lineText.match(escapedPipesRegexp) || []).length;

            // Is the line a new scenario or an annotation?
            if ((lineText.match(scenarioLineRegexp) || []).length == 0 && (lineText.match(tagLineRegexp) || []).length == 0 && (lineText.match(//g) || []).length == 0) {
                isScenarioLineOrTagLineOrNextStepLine = false;
            } else {
                isScenarioLineOrTagLineOrNextStepLine = true;
            }

            // If the lineText includes a pipe and the previous line does not and we're not already within a table
            if ((pipesMatchCount > escapedPipesMatchCount) && !previousLineContainsPipe) {

                // Set the table id for the
 tag - we need to do this so that we can group different tables if they belong to the same
                // Scenario Outline Examples (for example, if the table rows are separated by comments or a new Examples label
                preTagOpen = preTagOpenTemplate.replace(/table_id/g, dataTableId);

                // If it's the first row of a new examples table, we wrap this in a
 so that we can style it as one thing
                if (isFirstExampleRow) {
                    textToParse = [textToParse.slice(0, startOfLine), '
\n' + preTagOpen, textToParse.slice(startOfLine)].join('');
                    endOfLine += preTagOpen.length + 26;
                    isFirstExampleRow = false;
                } else {
                    textToParse = [textToParse.slice(0, startOfLine), preTagOpen, textToParse.slice(startOfLine)].join('');
                    endOfLine += preTagOpen.length;
                }

                // When we move on we need to know state that the previous line contained a pipe
                previousLineContainsPipe = true;
            }
            // If the lineText does not include a pipe and the previous line does i.e. we have left the table (potentially for good in this scenario)
            else if ((pipesMatchCount == escapedPipesMatchCount) && (previousLineContainsPipe || numberOfRowsSinceRowWithPipe > 0)) {

                // Close the
 tag (and therefore the table)
                textToParse = [textToParse.slice(0, startOfLine), preTagClose, textToParse.slice(startOfLine)].join('');
                endOfLine += preTagClose.length;

                numberOfRowsSinceRowWithPipe++;

                // When we move on we need to know state that the previous line did not contain a pipe
                previousLineContainsPipe = false;

                // If we've reached a new scenario or annotation (tag) we need to close the
 tag and the

                if (isScenarioLineOrTagLineOrNextStepLine) {
                    // The next time we start creating tables we want to know this is the first example row (we open the exampleArea div)
                    isFirstExampleRow = true;

                    // Reset this value for use with the next scenario
                    isATableOfExamples = false;

                    // The next scenario will need a new table ID to assign any example tables
                    dataTableId++;
                    numberOfRowsSinceRowWithPipe = 0;

                    // Close the
 tag and the

                    textToParse = [textToParse.slice(0, startOfLine), preTagClose, textToParse.slice(startOfLine)].join('');
                    textToParse = [textToParse.slice(0, startOfLine), "
 ", textToParse.slice(startOfLine)].join('');
                    endOfLine += preTagClose.length + 33; // we just increased the length to add the close pre tag in
                }

            }

        } // end if (isInsideDocString)

    // Check to see if the docString
 is closed
    if (((lineText.match(preTagCloseRegexp) || []).length > 0) && isInsideDocString) {
        isInsideDocString = false;
    }

    // We are at the end of the document!
    if (positionOfNextLineBreak == -1) {
        textToParse += "\n" + preTagClose + "
 "; // closing the
 tag
    }

    // Move to the next line - set startOfLine to the end of the previous line
    startOfLine = endOfLine + 1;
    textToParseRemainder = textToParse.substr(endOfLine + 1, textToParse.length - 1);
}
doc.innerHTML = textToParse;
}

function removePreTags(doc) {
    doc.innerHTML = doc.innerHTML.replace(/<\/*pre.*>/g, '');
}


text:
#include <openssl/ecdsa.h>

#include <assert.h>
#include <string.h>

#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/sha.h>
#include <openssl/type_check.h>

#include "../bn/internal.h"
#include "../ec/internal.h"
#include "../../internal.h"

// digest_to_scalar interprets |digest_len| bytes from |digest| as a scalar for
// ECDSA. Note this value is not fully reduced modulo the order, only the
// correct number of bits.
static void digest_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
                             const uint8_t *digest, size_t digest_len) {
  const BIGNUM *order = &group->order;
  size_t num_bits = BN_num_bits(order);
  // Need to truncate digest if it is too long: first truncate whole bytes.
  if (8 * digest_len > num_bits) {
    digest_len = (num_bits + 7) / 8;
  }
  OPENSSL_memset(out, 0, sizeof(EC_SCALAR));
  for (size_t i = 0; i < digest_len; i++) {
    out->bytes[i] = digest[digest_len - 1 - i];
  }

  // If still too long truncate remaining bits with a shift
  if (8 * digest_len > num_bits) {
    size_t shift = 8 - (num_bits & 0x7);
    for (int i = 0; i < order->top - 1; i++) {
      out->words[i] =
          (out->words[i] >> shift) | (out->words[i + 1] << (BN_BITS2 - shift));
    }
    out->words[order->top - 1] >>= shift;
  }
}

// field_element_to_scalar reduces |r| modulo |group->order|. |r| must
// previously have been reduced modulo |group->field|.
static int field_element_to_scalar(const EC_GROUP *group, BIGNUM *r) {
  // We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
  // can reduce by performing at most one subtraction.
  //
  // Proof: We only work with prime order curves, so the number of points on
  // the curve is the order. Thus Hasse's theorem gives:
  //
  //     |order - (p + 1)| <= 2×sqrt(p)
  //         p + 1 - order <= 2×sqrt(p)
  //     p + 1 - 2×sqrt(p) <= order
  //       p + 1 - 2×(p/4)  < order       (p/4 > sqrt(p) for p >= 17)
  //         p/2 < p/2 + 1  < order
  //                     p  < 2×order
  //
  // Additionally, one can manually check this property for built-in curves. It
  // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
  //
  // TODO(davidben): Introduce |EC_FIELD_ELEMENT|, make this a function from
  // |EC_FIELD_ELEMENT| to |EC_SCALAR|, and cut out the |BIGNUM|. Does this need
  // to be constant-time for signing? |r| is the x-coordinate for kG, which is
  // public unless k was rerolled because |s| was zero.
  assert(!BN_is_negative(r));
  assert(BN_cmp(r, &group->field) < 0);
  if (BN_cmp(r, &group->order) >= 0 &&
      !BN_sub(r, r, &group->order)) {
    return 0;
  }
  assert(!BN_is_negative(r));
  assert(BN_cmp(r, &group->order) < 0);
  return 1;
}

ECDSA_SIG *ECDSA_SIG_new(void) {
  ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
  if (sig == NULL) {
    return NULL;
  }
  sig->r = BN_new();
  sig->s = BN_new();
  if (sig->r == NULL || sig->s == NULL) {
    ECDSA_SIG_free(sig);
    return NULL;
  }
  return sig;
}

void ECDSA_SIG_free(ECDSA_SIG *sig) {
  if (sig == NULL) {
    return;
  }

  BN_free(sig->r);
  BN_free(sig->s);
  OPENSSL_free(sig);
}

void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **out_r,
                    const BIGNUM **out_s) {
  if (out_r != NULL) {
    *out_r = sig->r;
  }
  if (out_s != NULL) {
    *out_s = sig->s;
  }
}

int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) {
  if (r == NULL || s == NULL) {
    return 0;
  }
  BN_free(sig->r);
  BN_free(sig->s);
  sig->r = r;
  sig->s = s;
  return 1;
}

int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
                    const ECDSA_SIG *sig, const EC_KEY *eckey) {
  const EC_GROUP *group = EC_KEY_get0_group(eckey);
  const EC_POINT *pub_key = EC_KEY_get0_public_key(eckey);
  if (group == NULL || pub_key == NULL || sig == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS);
    return 0;
  }

  BN_CTX *ctx = BN_CTX_new();
  if (!ctx) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    return 0;
  }
  int ret = 0;
  EC_POINT *point = NULL;
  BN_CTX_start(ctx);
  BIGNUM *X = BN_CTX_get(ctx);
  if (X == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }

  EC_SCALAR r, s, m, u1, u2, s_inv_mont;
  const BIGNUM *order = EC_GROUP_get0_order(group);
  if (BN_is_zero(sig->r) ||
      BN_is_negative(sig->r) ||
      BN_ucmp(sig->r, order) >= 0 ||
      !ec_bignum_to_scalar(group, &r, sig->r) ||
      BN_is_zero(sig->s) ||
      BN_is_negative(sig->s) ||
      BN_ucmp(sig->s, order) >= 0 ||
      !ec_bignum_to_scalar(group, &s, sig->s)) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
    goto err;
  }
  // s_inv_mont = s^-1 mod order. We convert the result to Montgomery form for
  // the products below.
  int no_inverse;
  if (!BN_mod_inverse_odd(X, &no_inverse, sig->s, order, ctx) ||
      !ec_bignum_to_scalar(group, &s_inv_mont, X) ||
      !bn_to_montgomery_small(s_inv_mont.words, order->top, s_inv_mont.words,
                              order->top, group->order_mont)) {
    goto err;
  }
  // u1 = m * s_inv_mont mod order
  // u2 = r * s_inv_mont mod order
  //
  // |s_inv_mont| is in Montgomery form while |m| and |r| are not, so |u1| and
  // |u2| will be taken out of Montgomery form, as desired. Note that, although
  // |m| is not fully reduced, |bn_mod_mul_montgomery_small| only requires the
  // product not exceed R * |order|. |s_inv_mont| is fully reduced and |m| <
  // 2^BN_num_bits(order) <= R, so this holds.
  digest_to_scalar(group, &m, digest, digest_len);
  if (!bn_mod_mul_montgomery_small(u1.words, order->top, m.words, order->top,
                                   s_inv_mont.words, order->top,
                                   group->order_mont) ||
      !bn_mod_mul_montgomery_small(u2.words, order->top, r.words, order->top,
                                   s_inv_mont.words, order->top,
                                   group->order_mont)) {
    goto err;
  }

  point = EC_POINT_new(group);
  if (point == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  if (!ec_point_mul_scalar(group, point, &u1, pub_key, &u2, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }
  if (!field_element_to_scalar(group, X)) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
    goto err;
  }
  // The signature is correct iff |X| is equal to |sig->r|.
  if (BN_ucmp(X, sig->r) != 0) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
    goto err;
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  BN_CTX_free(ctx);
  EC_POINT_free(point);
  return ret;
}

static int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx,
                            EC_SCALAR *out_kinv_mont, BIGNUM **rp,
                            const uint8_t *digest, size_t digest_len,
                            const EC_SCALAR *priv_key) {
  EC_POINT *tmp_point = NULL;
  int ret = 0;
  EC_SCALAR k;
  BIGNUM *r = BN_new();  // this value is later returned in *rp
  if (r == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  const EC_GROUP *group = EC_KEY_get0_group(eckey);
  const BIGNUM *order = EC_GROUP_get0_order(group);
  tmp_point = EC_POINT_new(group);
  if (tmp_point == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
    goto err;
  }

  // Check that the size of the group order is FIPS compliant (FIPS 186-4
  // B.5.2).
  if (BN_num_bits(order) < 160) {
    OPENSSL_PUT_ERROR(ECDSA, EC_R_INVALID_GROUP_ORDER);
    goto err;
  }

  do {
    // Include the private key and message digest in the k generation.
    if (eckey->fixed_k != NULL) {
      if (!ec_bignum_to_scalar(group, &k, eckey->fixed_k)) {
        goto err;
      }
    } else {
      // Pass a SHA512 hash of the private key and digest as additional data
      // into the RBG. This is a hardening measure against entropy failure.
      OPENSSL_COMPILE_ASSERT(SHA512_DIGEST_LENGTH >= 32,
                             additional_data_is_too_large_for_sha512);
      SHA512_CTX sha;
      uint8_t additional_data[SHA512_DIGEST_LENGTH];
      SHA512_Init(&sha);
      SHA512_Update(&sha, priv_key->words, order->top * sizeof(BN_ULONG));
      SHA512_Update(&sha, digest, digest_len);
      SHA512_Final(additional_data, &sha);
      if (!ec_random_nonzero_scalar(group, &k, additional_data)) {
        goto err;
      }
    }

    // Compute k^-1. We leave it in the Montgomery domain as an optimization for
    // later operations.
    if (!bn_to_montgomery_small(out_kinv_mont->words, order->top, k.words,
                                order->top, group->order_mont) ||
        !bn_mod_inverse_prime_mont_small(out_kinv_mont->words, order->top,
                                         out_kinv_mont->words, order->top,
                                         group->order_mont)) {
      goto err;
    }

    // Compute r, the x-coordinate of generator * k.
    if (!ec_point_mul_scalar(group, tmp_point, &k, NULL, NULL, ctx) ||
        !EC_POINT_get_affine_coordinates_GFp(group, tmp_point, r, NULL,
                                             ctx)) {
      goto err;
    }

    if (!field_element_to_scalar(group, r)) {
      goto err;
    }
  } while (BN_is_zero(r));

  BN_clear_free(*rp);
  *rp = r;
  r = NULL;
  ret = 1;

err:
  OPENSSL_cleanse(&k, sizeof(k));
  BN_clear_free(r);
  EC_POINT_free(tmp_point);
  return ret;
}

ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
                         const EC_KEY *eckey) {
  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
    return NULL;
  }

  const EC_GROUP *group = EC_KEY_get0_group(eckey);
  const BIGNUM *priv_key_bn = EC_KEY_get0_private_key(eckey);
  if (group == NULL || priv_key_bn == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
    return NULL;
  }
  const BIGNUM *order = EC_GROUP_get0_order(group);

  int ok = 0;
  ECDSA_SIG *ret = ECDSA_SIG_new();
  BN_CTX *ctx = BN_CTX_new();
  EC_SCALAR kinv_mont, priv_key, r_mont, s, tmp, m;
  if (ret == NULL || ctx == NULL) {
    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
    return NULL;
  }

  digest_to_scalar(group, &m, digest, digest_len);
  if (!ec_bignum_to_scalar(group, &priv_key, priv_key_bn)) {
    goto err;
  }
  for (;;) {
    if (!ecdsa_sign_setup(eckey, ctx, &kinv_mont, &ret->r, digest, digest_len,
                          &priv_key)) {
      goto err;
    }

    // Compute priv_key * r (mod order). Note if only one parameter is in the
    // Montgomery domain, |bn_mod_mul_montgomery_small| will compute the answer
    // in the normal domain.
    if (!ec_bignum_to_scalar(group, &r_mont, ret->r) ||
        !bn_to_montgomery_small(r_mont.words, order->top, r_mont.words,
                                order->top, group->order_mont) ||
        !bn_mod_mul_montgomery_small(s.words, order->top, priv_key.words,
                                     order->top, r_mont.words, order->top,
                                     group->order_mont)) {
      goto err;
    }

    // Compute s += m in constant time. Reduce one copy of |order| if necessary.
    // Note this does not leave |s| fully reduced. We have
    // |m| < 2^BN_num_bits(order), so subtracting |order| leaves
    // 0 <= |s| < 2^BN_num_bits(order).
    BN_ULONG carry = bn_add_words(s.words, s.words, m.words, order->top);
    BN_ULONG v = bn_sub_words(tmp.words, s.words, order->d, order->top) - carry;
    v = 0u - v;
    for (int i = 0; i < order->top; i++) {
      s.words[i] = constant_time_select_w(v, s.words[i], tmp.words[i]);
    }

    // Finally, multiply s by k^-1. That was retained in Montgomery form, so the
    // same technique as the previous multiplication works. Although the
    // previous step did not fully reduce |s|, |bn_mod_mul_montgomery_small|
    // only requires the product not exceed R * |order|. |kinv_mont| is fully
    // reduced and |s| < 2^BN_num_bits(order) <= R, so this holds.
    if (!bn_mod_mul_montgomery_small(s.words, order->top, s.words, order->top,
                                     kinv_mont.words, order->top,
                                     group->order_mont) ||
        !bn_set_words(ret->s, s.words, order->top)) {
      goto err;
    }
    if (!BN_is_zero(ret->s)) {
      // s != 0 => we have a valid signature
      break;
    }
  }

  ok = 1;

err:
  if (!ok) {
    ECDSA_SIG_free(ret);
    ret = NULL;
  }
  BN_CTX_free(ctx);
  OPENSSL_cleanse(&kinv_mont, sizeof(kinv_mont));
  OPENSSL_cleanse(&priv_key, sizeof(priv_key));
  OPENSSL_cleanse(&r_mont, sizeof(r_mont));
  OPENSSL_cleanse(&s, sizeof(s));
  OPENSSL_cleanse(&tmp, sizeof(tmp));
  OPENSSL_cleanse(&m, sizeof(m));
  return ret;
}