<commit_before>const Set = require('es6-set')
const Map = require('es6-map')
const React = require('react')
const ReactDOM = require('react-dom')
const AppState = require('./appstate.js')
const FetchErrorPromise = require('./fetcherrorpromise.js')
const SsPdfView = require('./sspdfview.jsx')
const PaperUtils = require('./paperutils.js')
const AnnotationLayer = require('./annotationlayer.jsx')

const AllowedFormattingNodes = /^([bius])$/i // <b>, <i>, <s>, <u>
let editorNodeTypeNameTable = {}

class BaseEditorNodeComponent extends React.Component {
  static structureFromDataset (dataset) {
    // return { type: ..., ... }
    throw new Error('abstract.')
  }
  constructor (props) {
    super(props)
    // props.structure: structure for this editor node.
    this.handleDelete = this.handleDelete.bind(this)
    this.handleSorthand = this.handleSorthand.bind(this)
    if (new.target === BaseEditorNodeComponent) throw new Error('abstract.')
  }
  render () {
    // assert(this.props.structure.type === ...)
    throw new Error('abstract.')
  }
  toDataset () {
    // return { enType: ..., ... }
    throw new Error('abstract.')
  }
  getSorthand () {
    if (this.props.disabled) return null
    return (
      <span className='sorthand' onMouseDown={this.handleSorthand} onMouseUp={this.handleSorthand} onTouchStart={this.handleSorthand}>
        <svg className="icon ii-sorthand"><use href="#ii-sorthand" xlinkHref="#ii-sorthand" /></svg>
      </span>
    )
  }
  getDeleteBtn () {
    if (this.props.disabled) return null
    return (
      <span className='delete' onClick={this.handleDelete}>
        <svg className="icon ii-del"><use href="#ii-del" xlinkHref="#ii-del" /></svg>
      </span>
    )
  }
  handleSorthand () {
    if (this.props.onSorthand) {
      this.props.onSorthand()
    }
  }
  handleDelete (evt) {
    if (!this.props.onUpdateStructure) {
      throw new Error('no props.onUpdateStructure')
    }
    this.props.onUpdateStructure(null)
  }
}

class HiderEditorNode extends BaseEditorNodeComponent {
  static structureFromDataset (dataset) {
    if (dataset.enType !== 'hider') throw new Error('dataset invalid.')
    return {
      type: 'hider',
      hidden: dataset.hidden === 'true',
      content: JSON.parse(dataset.content || '[]')
    }
  }
  constructor (props) {
    super(props)
    this.handleInputChange = this.handleInputChange.bind(this)
    this.toggleHide = this.toggleHide.bind(this)
  }
  render () {
    return (
      <div className='enHider'>
        <div className='menu'>
          {this.getSorthand()}
          {this.getDeleteBtn()}
          {!this.props.structure.hidden
            ? (
                <span className='hide' onClick={this.toggleHide}>
                  <svg className="icon ii-hider"><use href="#ii-hider" xlinkHref="#ii-hider" /></svg>
                </span>
              ) : null}
          {this.props.structure.hidden
            ? (
                <span className='show' onClick={this.toggleHide}>
                  Show hidden content
                </span>
              ) : null}
        </div>
        <div className='contentcontain'>
          {this.props.structure.hidden
            ? (
                <Editor structure={this.props.structure.content || []} onChange={this.handleInputChange} disabled={this.props.disabled} />
              ) : null}
        </div>
      </div>
    )
  }
  handleInputChange (nContent) {
    this.props.onUpdateStructure(Object.assign({}, this.props.structure, {
      content: nContent
    }))
  }
  toDataset () {
    return {
      enType: 'hider',
      hidden: (this.props.structure.hidden ? 'true' : 'false'),
      content: JSON.stringify(this.props.structure.content || '[]')
    }
  }
  toggleHide () {
    this.props.onUpdateStructure(Object.assign({}, this.props.structure, {
      hidden: !this.props.structure.hidden
    }))
  }
}<commit_msg>Make enHider::hidden a state rather than a part of structure.<commit_after>const Set = require('es6-set')
const Map = require('es6-map')
const React = require('react')
const ReactDOM = require('react-dom')
const AppState = require('./appstate.js')
const FetchErrorPromise = require('./fetcherrorpromise.js')
const SsPdfView = require('./sspdfview.jsx')
const PaperUtils = require('./paperutils.js')
const AnnotationLayer = require('./annotationlayer.jsx')

const AllowedFormattingNodes = /^([bius])$/i // <b>, <i>, <s>, <u>
let editorNodeTypeNameTable = {}

class BaseEditorNodeComponent extends React.Component {
  static structureFromDataset (dataset) {
    // return { type: ..., ... }
    throw new Error('abstract.')
  }
  constructor (props) {
    super(props)
    // props.structure: structure for this editor node.
    this.handleDelete = this.handleDelete.bind(this)
    this.handleSorthand = this.handleSorthand.bind(this)
    if (new.target === BaseEditorNodeComponent) throw new Error('abstract.')
  }
  render () {
    // assert(this.props.structure.type === ...)
    throw new Error('abstract.')
  }
  toDataset () {
    // return { enType: ..., ... }
    throw new Error('abstract.')
  }
  getSorthand () {
    if (this.props.disabled) return null
    return (
      <span className='sorthand' onMouseDown={this.handleSorthand} onMouseUp={this.handleSorthand} onTouchStart={this.handleSorthand}>
        <svg className="icon ii-sorthand"><use href="#ii-sorthand" xlinkHref="#ii-sorthand" /></svg>
      </span>
    )
  }
  getDeleteBtn () {
    if (this.props.disabled) return null
    return (
      <span className='delete' onClick={this.handleDelete}>
        <svg className="icon ii-del"><use href="#ii-del" xlinkHref="#ii-del" /></svg>
      </span>
    )
  }
  handleSorthand () {
    if (this.props.onSorthand) {
      this.props.onSorthand()
    }
  }
  handleDelete (evt) {
    if (!this.props.onUpdateStructure) {
      throw new Error('no props.onUpdateStructure')
    }
    this.props.onUpdateStructure(null)
  }
}

class HiderEditorNode extends BaseEditorNodeComponent {
  static structureFromDataset (dataset) {
    if (dataset.enType !== 'hider') throw new Error('dataset invalid.')
    return {
      type: 'hider',
      content: JSON.parse(dataset.content || '[]')
    }
  }
  constructor (props) {
    super(props)
    this.state = {
      hidden: true
    }
    this.handleInputChange = this.handleInputChange.bind(this)
    this.toggleHide = this.toggleHide.bind(this)
  }
  render () {
    return (
      <div className='enHider'>
        <div className='menu'>
          {this.getSorthand()}
          {this.getDeleteBtn()}
          {!this.state.hidden
            ? (
                <span className='hide' onClick={this.toggleHide}>
                  <svg className="icon ii-hider"><use href="#ii-hider" xlinkHref="#ii-hider" /></svg>
                </span>
              ) : null}
          {this.state.hidden
            ? (
                <span className='show' onClick={this.toggleHide}>
                  Show hidden content
                </span>
              ) : null}
        </div>
        <div className='contentcontain'>
          {!this.state.hidden
            ? (
                <Editor structure={this.props.structure.content || []} onChange={this.handleInputChange} disabled={this.props.disabled} />
              ) : null}
        </div>
      </div>
    )
  }
  componentWillReceiveProps (nextProps) {
    if (nextProps.structure.content !== this.props.structure.content) {
      this.setState({
        hidden: false
      })
    }
  }
  handleInputChange (nContent) {
    this.props.onUpdateStructure(Object.assign({}, this.props.structure, {
      content: nContent
    }))
  }
  toDataset () {
    return {
      enType: 'hider',
      content: JSON.stringify(this.props.structure.content || '[]')
    }
  }
  toggleHide () {
    this.setState({
      hidden: !this.state.hidden
    })
  }
}
{'fraction_non_alphanumeric': 0.1523760988660976, 'fraction_numerical': 0.0005096190597528347, 'mean_word_length': 2.5877513711151736, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 59, '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': '4522039', 'n_tokens_mistral': 2410, 'n_tokens_neox': 2398, 'n_words': 442}