<commit_before>import React, { Component } from 'react';
import TextArea from 'react-textarea-autosize';

let PDFDocument = require('fzcs-pdfkit-fontkit');
let BlobStream = require('blob-stream');

class Main extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.setCharacters = this.setCharacters.bind(this);
    this.setSquaresPerLine = this.setSquaresPerLine.bind(this);
    this.setNumGray = this.setNumGray.bind(this);
    this.generatePdf = this.generatePdf.bind(this);
    this.generatePage = this.generatePage.bind(this);

    this.state = {
      characters: '怎麼樣',
      charactersOnCurrentPage: '',
      squaresPerLine: 9,
      numGray: 3,
      loading: false,
      percentComplete: 0
    }
  }

  componentDidMount() {
    this.setState({loading: true});
    let request = new XMLHttpRequest();
    request.open("GET", "fonts/UKaiCN.ttf", true);
    request.responseType = "arraybuffer";
    request.addEventListener("progress", (evt) => {
      if (evt.lengthComputable) {
        let percentComplete = Math.round(100 * evt.loaded / evt.total);
        this.setState({percentComplete: percentComplete});
      }
    }, false);
    request.send(null);
    request.onload = () => {
      this.setState({fontBuffer: request.response, loading: false});
    }
  }

  setCharacters(e) {
    this.setState({characters: e.target.value});
  }

  setSquaresPerLine(e) {
    this.setState({
      squaresPerLine: e.target.value,
      numGray: Math.min(this.state.numGray, e.target.value - 1)
    })
  }

  setNumGray(e) {
    this.setState({
      numGray: e.target.value
    })
  }

  generatePdf(e) {
    e.preventDefault();
    let size = Math.round(500 / this.state.squaresPerLine);
    if (size % 2 === 1) size += 1;
    let h = size / 2;

    let charsPerPage = Math.floor(297 * this.state.squaresPerLine / 210);
    let pages = [];
    let chars = this.state.characters;
    while (chars.length > 0) {
      pages.push(chars.substr(0, charsPerPage));
      chars = chars.substr(charsPerPage);
    }

    let doc = new PDFDocument({margin: 1});
    doc.registerFont('UKaiCN', this.state.fontBuffer);

    for (let p = 0; p < pages.length; p++) {
      if (p > 0) doc.addPage();
      doc.font('Helvetica').fontSize(8).text('(c) <NAME>, <EMAIL>', 440, 760);
      doc.font('UKaiCN').fontSize(size - Math.round(size / 8));
      for (let i = 0; i < this.state.squaresPerLine; i++) {
        for (let j = 0; j < pages[p].length; j++) {
          let x = 40 + i * size;
          let y = 40 + j * size;
          doc.rect(x, y, size, size);
          doc.lineWidth(1).undash().strokeColor('#000', '1').stroke();
          doc.lineWidth(0.5).dash(3, 6).strokeColor('#000', '0.2')
              .moveTo(x, y + h).lineTo(x + size, y + h)
              .moveTo(x + h, y).lineTo(x + h, y + size)
              .stroke();

          doc.fillColor('#000', '1');
          if (i > 0 && i <= this.state.numGray) doc.opacity('0.3');
          if (i <= this.state.numGray) doc.text(pages[p].charAt(j), x + Math.round(size / 20), y);
        }
      }
    }

    let stream = doc.pipe(BlobStream());
    doc.end();
    stream.on('finish', () => {
      let url = stream.toBlobURL('application/pdf');
      document.getElementById("pdf-preview").src = url;
    });
  }

  generatePage(pdf, pages) {
    let grid = document.getElementById('print-grid');
    this.setState({charactersOnCurrentPage: pages[0]},
        () => {
          grid.style.display = 'block';
          pdf.setFontSize(12);
          pdf.text(400, 830, '(c) <NAME>, <EMAIL>');
          pdf.addHTML(grid, 0, 40, () => {
            if (pages.length > 1) {
              pdf.addPage();
              this.generatePage(pdf, pages.slice(1))
            } else {
              pdf.output('save', 'grid.pdf');
              this.setState({generating: false});
            }
          })
          grid.style.display = 'none';
        });
  }

  render() {
    return (
          <div>
            <nav className="navbar navbar-default">
              <div className="container">
                <div className="navbar-header">
                  <div className="navbar-brand">Chinese Character Practice Sheets</div>
                </div>
              </div>
            </nav>
            <div className="container-fluid">
              <div className="row">
                <div className="col-sm-4">
                  <form>
                    <div className="form-group">
                      <label htmlFor="input-characters">Type characters here</label>
                      <TextArea className="form-control" id="input-characters" type="text" minRows={2}
                             value={this.state.characters} onChange={this.setCharacters} />
                    </div>
                    <div className="form-group">
                      <label htmlFor="input-squaresperline">{'Number of squares per line: ' + this.state.squaresPerLine}</label>
                      <input type="range" min={4} max={10} step={1}
                             value={this.state.squaresPerLine} onChange={this.setSquaresPerLine}>
                      </input>
                    </div>
                    <div className="form-group">
                      <label htmlFor="input-numgray">{'Number of gray characters: ' + this.state.numGray}</label>
                      <input type="range" min={0} max={this.state.squaresPerLine - 1} step={1}
                             value={this.state.numGray} onChange={this.setNumGray}>
                      </input>
                    </div>
                  </form>
                  <div className="row higher">
                    <div className="col-md-12">
                      <button className="btn btn-primary btn-lg pull-right"
                              disabled={this.state.loading} onClick={this.generatePdf}>
                        Generate PDF
                      </button>
                      {this.state.loading ?
                          (<div className="col-md-12">
                            <span className="pull-right">
                            {'Please wait while font is loading... ' + this.state.percentComplete + '%'}</span>
                          </div>) : false}
                    </div>
                  </div>
                </div>
                <div className="col-sm-8">
                  <iframe id="pdf-preview" width="595" height="800" src=""></iframe>
                </div>
              </div>
            </div>
          </div>
    );
  }
}

export default Main;<commit_msg>Show iframe only after first PDF is generated<commit_after>import React, { Component } from 'react';
import TextArea from 'react-textarea-autosize';

let PDFDocument = require('fzcs-pdfkit-fontkit');
let BlobStream = require('blob-stream');

class Main extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.setCharacters = this.setCharacters.bind(this);
    this.setSquaresPerLine = this.setSquaresPerLine.bind(this);
    this.setNumGray = this.setNumGray.bind(this);
    this.generatePdf = this.generatePdf.bind(this);
    this.generatePage = this.generatePage.bind(this);

    this.state = {
      characters: '怎麼樣',
      charactersOnCurrentPage: '',
      squaresPerLine: 9,
      numGray: 3,
      loading: false,
      percentComplete: 0,
      generated: false
    }
  }

  componentDidMount() {
    this.setState({loading: true});
    let request = new XMLHttpRequest();
    request.open("GET", "fonts/UKaiCN.ttf", true);
    request.responseType = "arraybuffer";
    request.addEventListener("progress", (evt) => {
      if (evt.lengthComputable) {
        let percentComplete = Math.round(100 * evt.loaded / evt.total);
        this.setState({percentComplete: percentComplete});
      }
    }, false);
    request.send(null);
    request.onload = () => {
      this.setState({fontBuffer: request.response, loading: false});
    }
  }

  setCharacters(e) {
    this.setState({characters: e.target.value});
  }

  setSquaresPerLine(e) {
    this.setState({
      squaresPerLine: e.target.value,
      numGray: Math.min(this.state.numGray, e.target.value - 1)
    })
  }

  setNumGray(e) {
    this.setState({
      numGray: e.target.value
    })
  }

  generatePdf(e) {
    this.setState({loading: true});
    e.preventDefault();
    let size = Math.round(500 / this.state.squaresPerLine);
    if (size % 2 === 1) size += 1;
    let h = size / 2;

    let charsPerPage = Math.floor(297 * this.state.squaresPerLine / 210);
    let pages = [];
    let chars = this.state.characters;
    while (chars.length > 0) {
      pages.push(chars.substr(0, charsPerPage));
      chars = chars.substr(charsPerPage);
    }

    let doc = new PDFDocument({margin: 1});
    doc.registerFont('UKaiCN', this.state.fontBuffer);

    for (let p = 0; p < pages.length; p++) {
      if (p > 0) doc.addPage();
      doc.font('Helvetica').fontSize(8).text('(c) <NAME>, robbertbrak.com', 440, 760);
      doc.font('UKaiCN').fontSize(size - Math.round(size / 8));
      for (let i = 0; i < this.state.squaresPerLine; i++) {
        for (let j = 0; j < pages[p].length; j++) {
          let x = 40 + i * size;
          let y = 40 + j * size;
          doc.rect(x, y, size, size);
          doc.lineWidth(1).undash().strokeColor('#000', '1').stroke();
          doc.lineWidth(0.5).dash(3, 6).strokeColor('#000', '0.2')
              .moveTo(x, y + h).lineTo(x + size, y + h)
              .moveTo(x + h, y).lineTo(x + h, y + size)
              .stroke();

          doc.fillColor('#000', '1');
          if (i > 0 && i <= this.state.numGray) doc.opacity('0.3');
          if (i <= this.state.numGray) doc.text(pages[p].charAt(j), x + Math.round(size / 20), y);
        }
      }
    }

    let stream = doc.pipe(BlobStream());
    doc.end();
    stream.on('finish', () => {
      let url = stream.toBlobURL('application/pdf');
      this.setState({generated: true}, () => {
        document.getElementById("pdf-preview").src = url;
        this.setState({loading: false});
      });
    });
  }

  generatePage(pdf, pages) {
    let grid = document.getElementById('print-grid');
    this.setState({charactersOnCurrentPage: pages[0]},
        () => {
          grid.style.display = 'block';
          pdf.setFontSize(12);
          pdf.text(400, 830, '(c) <NAME>, <EMAIL>');
          pdf.addHTML(grid, 0, 40, () => {
            if (pages.length > 1) {
              pdf.addPage();
              this.generatePage(pdf, pages.slice(1))
            } else {
              pdf.output('save', 'grid.pdf');
              this.setState({generating: false});
            }
          })
          grid.style.display = 'none';
        });
  }

  render() {
    return (
          <div>
            <nav className="navbar navbar-default">
              <div className="container">
                <div className="navbar-header">
                  <div className="navbar-brand">Chinese Character Practice Sheets</div>
                </div>
              </div>
            </nav>
            <div className="container-fluid">
              <div className="row">
                <div className="col-sm-4">
                  <form>
                    <div className="form-group">
                      <label htmlFor="input-characters">Type characters here</label>
                      <TextArea className="form-control" id="input-characters" type="text" minRows={2}
                             value={this.state.characters} onChange={this.setCharacters} />
                    </div>
                    <div className="form-group">
                      <label htmlFor="input-squaresperline">{'Number of squares per line: ' + this.state.squaresPerLine}</label>
                      <input type="range" min={4} max={10} step={1}
                             value={this.state.squaresPerLine} onChange={this.setSquaresPerLine}>
                      </input>
                    </div>
                    <div className="form-group">
                      <label htmlFor="input-numgray">{'Number of gray characters: ' + this.state.numGray}</label>
                      <input type="range" min={0} max={this.state.squaresPerLine - 1} step={1}
                             value={this.state.numGray} onChange={this.setNumGray}>
                      </input>
                    </div>
                  </form>
                  <div className="row higher">
                    <div className="col-md-12">
                      <button className="btn btn-primary btn-lg pull-right"
                              disabled={this.state.loading} onClick={this.generatePdf}>
                        Generate PDF
                      </button>
                      {this.state.loading ?
                          (<div className="col-md-12">
                            <span className="pull-right">
                            {'Please wait while font is loading... ' + this.state.percentComplete + '%'}</span>
                          </div>) : false}
                    </div>
                  </div>
                </div>
                <div className="col-sm-8">
                  {this.state.generated ?
                      <iframe id="pdf-preview" width="595" height="810" src=""></iframe> : false
                  }
                </div>
              </div>
            </div>
          </div>
    );
  }
}

export default Main;
{'fraction_non_alphanumeric': 0.15215773809523808, 'fraction_numerical': 0.014285714285714285, 'mean_word_length': 1.7764924602354886, 'pattern_counts': {'":': 0, '<': 118, '<?xml version=': 0, '>': 127, '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': '7082947', 'n_tokens_mistral': 4179, 'n_tokens_neox': 3928, 'n_words': 766}