frontend and backend

This commit is contained in:
2022-01-09 12:08:42 +01:00
parent cbff7c5d22
commit dde65761e5
75 changed files with 37830 additions and 19 deletions

19
frontend/src/preg/Code.js Normal file
View File

@ -0,0 +1,19 @@
import React, { Component } from 'react';
function createMarkup(html) {
return {__html: html}
}
export default class Code extends Component {
render() {
const { response } = this.props;
return (
<>
{'code' in response &&
<code dangerouslySetInnerHTML={createMarkup(response.code)} />
}
</>
)
}
}

View File

@ -0,0 +1,29 @@
import React, { Component } from 'react';
import Form from 'react-bootstrap/Form';
export default class Fields extends Component {
render() {
return (
<>
{this.props.fields.includes('pattern') &&
<Form.Group className="mb-3" controlId="pattern">
<Form.Label>Regular Expression / Pattern</Form.Label>
<Form.Control type="text" onChange={this.props.onChange} name="pattern" value={this.props.pattern} placeholder="#...#" className="font-monospace" />
</Form.Group>
}
{this.props.fields.includes('replacement') &&
<Form.Group className="mb-3" controlId="replacement">
<Form.Label>Replacement</Form.Label>
<Form.Control type="text" onChange={this.props.onChange} name="replacement" value={this.props.replacement} />
</Form.Group>
}
{this.props.fields.includes('subject') &&
<Form.Group className="mb-3" controlId="subject">
<Form.Label>String / Subject</Form.Label>
<Form.Control as="textarea" onChange={this.props.onChange} name="subject" value={this.props.subject} rows={3} />
</Form.Group>
}
</>
);
}
}

102
frontend/src/preg/Help.js Normal file
View File

@ -0,0 +1,102 @@
import React, { Component } from 'react';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Modal from 'react-bootstrap/Modal';
export default class Help extends Component {
render() {
return (
<Modal {...this.props} size="xl">
<Modal.Header closeButton>
<Modal.Title>Regexp spreadsheet (<a href="http://php.net/manual/en/pcre.pattern.php">full documentation</a>)</Modal.Title>
</Modal.Header>
<Modal.Body>
<Container>
<Row>
<Col>
<h4>Pattern Modifiers</h4>
<div><code>i</code> PCRE_CASELESS</div>
<div><code>m</code> PCRE_MULTILINE</div>
<div><code>s</code> PCRE_DOTALL</div>
<div><code>x</code> PCRE_EXTENDED</div>
<div><code>A</code> PCRE_ANCHORED</div>
<div><code>D</code> PCRE_DOLLAR_ENDONLY</div>
<div><code>S</code> Extra analysis</div>
<div><code>U</code> PCRE_UNGREEDY</div>
<div><code>X</code> PCRE_EXTRA</div>
<div><code>J</code> PCRE_INFO_JCHANGED</div>
<div><code>u</code> PCRE_UTF8</div>
</Col>
<Col>
<h4>Meta-characters outside <code>[ ]</code></h4>
<div><code>\</code> general escape character</div>
<div><code>^</code> assert start of subject (or line, in multiline mode)</div>
<div><code>$</code> assert end of subject (or line, in multiline mode)</div>
<div><code>.</code> match any character except newline (by default)</div>
<div><code>[ ]</code> character class definition</div>
<div><code>|</code> start of alternative branch</div>
<div><code>( )</code> subpattern</div>
<div><code>?</code> extends the meaning of '(', also 0 or 1 quantifier</div>
<div><code>*</code> 0 or more quantifier</div>
<div><code>+</code> 1 or more quantifier</div>
<div><code>{'{ }'}</code> min/max quantifier, {'{n[,n]}'}</div>
<h4 className="mt-4">Meta-characters inside <code>[ ]</code></h4>
<div><code>\</code> general escape character</div>
<div><code>^</code> negate the class, but only if the first character</div>
<div><code>-</code> indicates character range</div>
<h4 className="mt-4">Others</h4>
<div><code>{'\\1-9'}</code> in-group back references</div>
<div><code>(?P&lt;lbl&gt;...)</code> labelize subpatterns</div>
<div><code>(?:...)</code> non-capture group</div>
<div><code>(?&gt;...)</code> Atomic group</div>
<div><code>(?=...)</code> Positive lookahead</div>
<div><code>(?!...)</code> Negative lookahead</div>
<div><code>(?&lt;=..)</code> Positive lookbehind</div>
<div><code>(?&lt;!..)</code> Negative lookbehind</div>
<div><code>(?(?=.).|.)</code> if . then . else .</div>
<div><code>(?#...)</code> Comment</div>
</Col>
<Col>
<h4>Scape sequences</h4>
<div><code>\a</code> alarm, that is, the BEL character (hex 07)</div>
<div><code>\cx</code> "control-x", where x is any character</div>
<div><code>\e</code> escape (hex 1B)</div>
<div><code>\f</code> formfeed (hex 0C)</div>
<div><code>\n</code> newline (hex 0A)</div>
<div><code>\r</code> carriage return (hex 0D)</div>
<div><code>\R</code> line break: matches \n, \r and \r\n</div>
<div><code>\t</code> tab (hex 09)</div>
<div><code>\p{'{xx}'}</code> a character with the xx <a href="http://www.php.net/manual/en/regexp.reference.unicode.php">property</a></div>
<div><code>\P{'{xx}'}</code> a character without the xx <a href="http://www.php.net/manual/en/regexp.reference.unicode.php">property</a></div>
<div><code>\xhh</code> character with hex code hh</div>
<div><code>\ddd</code> character with octal code ddd, or backreference</div>
<div><code>\d</code> any decimal digit</div>
<div><code>\D</code> any character that is not a decimal digit</div>
<div><code>\s</code> any whitespace character</div>
<div><code>\S</code> any character that is not a whitespace character</div>
<div><code>\h</code> any horizontal whitespace character</div>
<div><code>\H</code> any character that is not a horizontal whitespace</div>
<div><code>\v</code> any vertical whitespace character</div>
<div><code>\V</code> any character that is not a vertical whitespace character</div>
<div><code>\w</code> any "word" character</div>
<div><code>\W</code> any "non-word" character</div>
<div><code>\b</code> word boundary</div>
<div><code>\B</code> not a word boundary</div>
<div><code>\A</code> start of subject (independent of multiline mode)</div>
<div><code>\Z</code> end of subject or newline at end (independent of multiline mode)</div>
<div><code>\z</code> end of subject (independent of multiline mode)</div>
<div><code>\G</code> first matching position in subject</div>
</Col>
</Row>
</Container>
</Modal.Body>
</Modal>
)
}
}

55
frontend/src/preg/Opts.js Normal file
View File

@ -0,0 +1,55 @@
import React, { Component } from 'react';
import Form from 'react-bootstrap/Form';
import InputGroup from 'react-bootstrap/InputGroup';
import Col from 'react-bootstrap/Col';
function Checkbox(props) {
return props.opts.includes(props.id)? (
<Form.Group className="mb-3" controlId={props.id}>
<Form.Check type="checkbox" name={props.id} label={props.id} checked={props[props.id]} onChange={props.onChange} />
</Form.Group>
): '';
}
export default class Opts extends Component {
render() {
return (
<>
{this.props.opts.includes('PREG_SET_ORDER') &&
<p className="text-muted"><tt>PREG_PATTERN_ORDER</tt> is the default order method.</p>
}
<Checkbox id="PREG_SET_ORDER" {...this.props} />
<Checkbox id="PREG_OFFSET_CAPTURE" {...this.props} />
<Checkbox id="PREG_UNMATCHED_AS_NULL" {...this.props} />
<Checkbox id="PREG_SPLIT_NO_EMPTY" {...this.props} />
<Checkbox id="PREG_SPLIT_DELIM_CAPTURE" {...this.props} />
<Checkbox id="PREG_SPLIT_OFFSET_CAPTURE" {...this.props} />
{this.props.opts.includes('offset') &&
<Col xl="2" md="3" sm="4" xs="6">
<InputGroup className="mb-3">
<InputGroup.Text id="offset">offset</InputGroup.Text>
<Form.Control type="number" name="offset" placeholder="0" aria-label="offset" aria-describedby="offset" value={this.props.offset ?? ''} onChange={this.props.onChange} min="0" />
</InputGroup>
</Col>
}
{this.props.opts.includes('limit') &&
<Col xl="2" md="3" sm="4" xs="6">
<InputGroup className="mb-3">
<InputGroup.Text id="limit">limit</InputGroup.Text>
<Form.Control type="number" name="limit" placeholder="-1" aria-label="limit" aria-describedby="limit" value={this.props.limit ?? ''} onChange={this.props.onChange} min="-1" />
</InputGroup>
</Col>
}
{this.props.opts.includes('delimeter') &&
<Col xl="2" md="3" sm="4" xs="6">
<InputGroup className="mb-3">
<InputGroup.Text id="delimiter">delimiter</InputGroup.Text>
<Form.Control name="delimiter" aria-label="delimiter" aria-describedby="delimiter" value={this.props.delimiter ?? ''} onChange={this.props.onChange} />
</InputGroup>
</Col>
}
</>
);
}
}

View File

@ -0,0 +1,70 @@
import React, { Component } from 'react';
import Table from 'react-bootstrap/Table'
function mapObject(object, callback) {
return Object.keys(object).map(key => {
return callback(key, object[key])
})
}
const DumpList = (props) => {
const type = typeof props.dump
if (type === "object") {
if (Object.keys(props.dump).length === 0) {
return <tt className="text-secondary">[]</tt>
}
const items = mapObject(props.dump, (key, value) => {
if (['number', 'string'].includes(typeof value)) {
// .replace(" ", '⎵')
return (
<tr key={key}>
<td className="table-active text-end text-muted font-monospace">{key}</td>
<td className="px-2">{value}</td>
</tr>
)
} else {
return (
<tr key={key}>
<td className="table-active text-end text-muted font-monospace">{key}</td>
<td><DumpList dump={value} indent={props.indent + 1} /></td>
</tr>
)
}
})
return (
<Table borderless variant="light" size="sm">
<tbody>
{items}
</tbody>
</Table>
)
} else if (type === 'string') {
return (<tt>{props.dump}</tt>)
}
return (<em>empty result</em>)
}
export default class Output extends Component {
render() {
const { response } = this.props;
return (
<>
{'fatal' in response &&
<div>
<code>{response.fatal}</code>
</div>
}
{'dump' in response &&
<DumpList dump={response.dump} indent={0} />
}
</>
)
}
}

View File

@ -0,0 +1,18 @@
import React, { Component } from 'react';
export default class Return extends Component {
render() {
const { response } = this.props;
return (
<>
{'returnType' in response && 'returnValue' in response &&
<span>
<code>{response.returnType}</code>:{' '}<code>{response.returnValue}</code>
</span>
}
</>
)
}
}

20
frontend/src/preg/Tabs.js Normal file
View File

@ -0,0 +1,20 @@
import React, { Component } from 'react';
import Nav from 'react-bootstrap/Nav';
export default class Tabs extends Component {
render() {
const tabs = this.props.functions.map((func) => {
return (
<Nav.Item key={func} className="bg-light font-monospace"><Nav.Link eventKey={func}>{func}</Nav.Link></Nav.Item>
)
})
return (
<Nav fill variant="pills" defaultActiveKey={this.props.functions[0]} activeKey={this.props.method} onSelect={this.props.onChange}>
{tabs}
</Nav>
);
}
}