frontend and backend
This commit is contained in:
19
frontend/src/preg/Code.js
Normal file
19
frontend/src/preg/Code.js
Normal 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)} />
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
29
frontend/src/preg/Fields.js
Normal file
29
frontend/src/preg/Fields.js
Normal 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
102
frontend/src/preg/Help.js
Normal 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<lbl>...)</code> labelize subpatterns</div>
|
||||
<div><code>(?:...)</code> non-capture group</div>
|
||||
<div><code>(?>...)</code> Atomic group</div>
|
||||
<div><code>(?=...)</code> Positive lookahead</div>
|
||||
<div><code>(?!...)</code> Negative lookahead</div>
|
||||
<div><code>(?<=..)</code> Positive lookbehind</div>
|
||||
<div><code>(?<!..)</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
55
frontend/src/preg/Opts.js
Normal 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>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
70
frontend/src/preg/Output.js
Normal file
70
frontend/src/preg/Output.js
Normal 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} />
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
18
frontend/src/preg/Return.js
Normal file
18
frontend/src/preg/Return.js
Normal 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
20
frontend/src/preg/Tabs.js
Normal 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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user