Skip to content

Commit fa9a88c

Browse files
committed
Metadata for all pages, some options cleanup, quotes on home page
1 parent 312242a commit fa9a88c

File tree

13 files changed

+202
-61
lines changed

13 files changed

+202
-61
lines changed

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# To Do
22

33

4-
4+
- [ ] quotes on home page
55
- [ ] [analytics](https://nextjs.org/docs/app/building-your-application/optimizing/analytics)
66
- [ ] get engine release level from remote instead of hard-coded
77
- [ ] display status (and alpha/beta warning) on testing page

next.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ const nextConfig = {
2525
permanent: false,
2626
},
2727
*/
28+
{
29+
source: '/simple/previous.html',
30+
destination: '/advanced/java/index.html',
31+
permanent: false,
32+
},
2833
{
2934
source: '/support/',
3035
destination: '/support/index.html',
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use client'
2+
import React, { useState } from 'react';
3+
import { PiArrowSquareOut } from "react-icons/pi";
4+
import { runTest } from '@/engines';
5+
import { TestInput } from '@/types/TestInput';
6+
import { TestOutput } from '@/types/TestOutput';
7+
import { TestResults } from '@/components/TestResults';
8+
import { RegexEngine } from '@/engines/RegexEngine';
9+
10+
type props = {
11+
engine: RegexEngine;
12+
}
13+
14+
export default function TestForm({ engine }: props) {
15+
const [testOutput, setTestOutput] = useState<TestOutput | null>();
16+
const [testInput, setTestInput] = useState<TestInput | null>();
17+
18+
const inputs = ["", "", "", "", ""];
19+
20+
const inputRows = inputs.map((input, index) => (
21+
<div className="mb-2" key={`key${index}`}>
22+
{index <= 0 ? <label htmlFor={`row${index}`} className="col-sm-2 col-form-label">Inputs</label> : <></> }
23+
<input type="text" className="form-control" id={`input${index}`} name="input" value={input} />
24+
</div>
25+
));
26+
27+
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
28+
event.preventDefault();
29+
const form = event.currentTarget;
30+
const formData = new FormData(form);
31+
const localInput: TestInput = {
32+
regex: formData.get('regex') as string,
33+
replacement: formData.get('replacement') as string,
34+
options: formData.get('options') as string,
35+
inputs: formData.getAll('input') as string[]
36+
};
37+
console.log(localInput);
38+
setTestInput(localInput);
39+
setTestOutput(null);
40+
setTestOutput(await runTest(engine, formData));
41+
42+
//window.history.pushState(null, "", `/advanced/${engine.handle}/results.html`);
43+
};
44+
45+
return (
46+
<>
47+
{(testInput ?
48+
(testOutput ? <TestResults testOutput={testOutput} /> : <><h2>Results</h2><p>Loading...</p></>)
49+
: <></>)
50+
}
51+
<h2>Expression to test</h2>
52+
<form method="post" action="results.html" onSubmit={onSubmit}>
53+
<div className="mb-3">
54+
<label htmlFor="regex" className="form-label">Regular Expression</label>
55+
<input type="text" className="form-control" id="regex" name="regex" />
56+
</div>
57+
<div className="mb-3">
58+
<label htmlFor="replacement" className="form-label">Replacement</label>
59+
<input type="text" className="form-control" id="replacement" name="replacement" />
60+
</div>
61+
<div className="mb-3">
62+
<label htmlFor="options" className="form-label">Options</label>
63+
<div className="row">
64+
<div className="col-7 col-sm-6 col-md-4 col-lg-3 col-xl-2">
65+
<input type="text" className="form-control" id="options" name="options" />
66+
</div>
67+
<div className="col-5 col-sm-6 col-md-8 col-lg-9 col-xl-10">
68+
<a href="options.html" target="_new">Help<PiArrowSquareOut className="ms-2" /></a>
69+
</div>
70+
</div>
71+
</div>
72+
<button type="submit" className="btn btn-primary">Test</button>
73+
{inputRows}
74+
<button type="submit" className="btn btn-primary">Test</button>
75+
</form>
76+
</>
77+
);
78+
}
Lines changed: 15 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
'use client'
21
import React, { useState } from 'react';
32
import { getEngine, runTest } from '@/engines';
43
import { ShareLinks } from '@/components/ShareLinks';
54
import { notFound } from 'next/navigation';
65
import { TestInput } from '@/types/TestInput';
76
import { TestOutput } from '@/types/TestOutput';
87
import { TestResults } from '@/components/TestResults';
8+
import { Metadata } from 'next';
9+
import TestForm from './TestForm';
10+
11+
export async function generateMetadata({ params }: { params: { engine: string } }) {
12+
const engine = getEngine(params.engine);
13+
if (!engine) {
14+
return {};
15+
}
16+
17+
return {
18+
title: `Test your ${engine.short_name} regular expression - RegexPlanet`,
19+
description: `Online testing for ${engine.short_name} regular expressions.`,
20+
}
21+
}
922

1023
export default function Page({ params }: { params: { engine: string } }) {
11-
const [testOutput, setTestOutput] = useState<TestOutput | null>();
12-
const [testInput, setTestInput] = useState<TestInput | null>();
1324
const engine = getEngine(params.engine);
1425
if (!engine) {
1526
return notFound();
@@ -26,35 +37,6 @@ export default function Page({ params }: { params: { engine: string } }) {
2637
</div>;
2738
}
2839

29-
const inputs = ["", "", "", "", ""];
30-
31-
const inputRows = inputs.map((input, index) => (
32-
<div className="mb-3 col-6 row" key={`key${index}`}>
33-
<label htmlFor={`row${index}`} className="col-sm-2 col-form-label">Input {index + 1}</label>
34-
<div className="col-sm-10">
35-
<input type="text" className="form-control" id={`input${index}`} name="input" />
36-
</div>
37-
</div>
38-
));
39-
40-
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
41-
event.preventDefault();
42-
const form = event.currentTarget;
43-
const formData = new FormData(form);
44-
const localInput: TestInput = {
45-
regex: formData.get('regex') as string,
46-
replacement: formData.get('replacement') as string,
47-
options: formData.get('options') as string,
48-
inputs: formData.getAll('input') as string[]
49-
};
50-
console.log(localInput);
51-
setTestInput(localInput);
52-
setTestOutput(null);
53-
setTestOutput(await runTest(engine, formData));
54-
55-
//window.history.pushState(null, "", `/advanced/${engine.handle}/results.html`);
56-
};
57-
5840
return (
5941
<>
6042
<div className="d-flex justify-content-between align-items-center">
@@ -64,28 +46,7 @@ export default function Page({ params }: { params: { engine: string } }) {
6446
<ShareLinks url={`https://regexplanet.com/advanced/${engine.handle}/index.html`} text={`Test your ${engine.short_name} regular expression`} />
6547
<hr />
6648
{flash}
67-
{(testInput ?
68-
(testOutput ? <TestResults testOutput={testOutput} /> : <><h2>Results</h2><p>Loading...</p></>)
69-
: <></>)
70-
}
71-
<h2>Expression to test</h2>
72-
<form method="post" action="results.html" onSubmit={onSubmit}>
73-
<div className="mb-3">
74-
<label htmlFor="regex" className="form-label">Regular Expression</label>
75-
<input type="text" className="form-control" id="regex" name="regex" />
76-
</div>
77-
<div className="mb-3">
78-
<label htmlFor="replacement" className="form-label">Replacement</label>
79-
<input type="text" className="form-control" id="replacement" name="replacement" />
80-
</div>
81-
<div className="mb-3">
82-
<label htmlFor="options" className="form-label">Options</label>
83-
<input type="text" className="form-control" id="options" name="options" />
84-
</div>
85-
<button type="submit" className="btn btn-primary">Test</button>
86-
{inputRows}
87-
<button type="submit" className="btn btn-primary">Test</button>
88-
</form>
49+
<TestForm engine={engine} />
8950
</>
9051
);
9152
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { useState } from 'react';
2+
import { getEngine, runTest } from '@/engines';
3+
import { ShareLinks } from '@/components/ShareLinks';
4+
import { notFound } from 'next/navigation';
5+
import { TestInput } from '@/types/TestInput';
6+
import { TestOutput } from '@/types/TestOutput';
7+
import { TestResults } from '@/components/TestResults';
8+
import { Metadata } from 'next';
9+
10+
export async function generateMetadata({ params }: { params: { engine: string } }) {
11+
const engine = getEngine(params.engine);
12+
if (!engine) {
13+
return {};
14+
}
15+
16+
return {
17+
title: `Options for ${engine.short_name} regular expressions - RegexPlanet`,
18+
description: `Options (aka flags) that you can set for ${engine.short_name} regular expressions.`,
19+
}
20+
}
21+
22+
export default function Page({ params }: { params: { engine: string } }) {
23+
const engine = getEngine(params.engine);
24+
if (!engine) {
25+
return notFound();
26+
}
27+
28+
return (
29+
<>
30+
<h1>Options for {engine.short_name} Regular Expressions</h1>
31+
<hr />
32+
<div className="alert alert-info" role="alert">Regular expressions can have options (also known as flags) that modify their behavior. Each engine supports a different set of options.</div>
33+
<table className="table table-striped">
34+
<thead>
35+
<tr>
36+
<th>Option</th>
37+
<th>Description</th>
38+
</tr>
39+
</thead>
40+
<tbody>
41+
{Object.entries(engine.options).map((option) => (
42+
<tr key={option[0]}>
43+
<td>{option[0]}</td>
44+
<td>{option[1]}</td>
45+
</tr>
46+
))}
47+
</tbody>
48+
</table>
49+
</>
50+
)
51+
}

src/app/layout.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ import 'bootstrap/dist/css/bootstrap.css'
66
import './global.css'
77
import { Footer } from "@/components/Footer";
88

9-
export const metadata: Metadata = {
10-
title: "RegexPlanet",
11-
description: "LATER",
12-
};
13-
149
export const viewport: Viewport = {
1510
width: 'device-width',
1611
initialScale: 1,

src/app/legal/privacy.html/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import { Metadata } from 'next';
2+
3+
export const metadata: Metadata = {
4+
title: "Privacy Policy - RegexPlanet",
5+
};
6+
17
export default function Page() {
28
return (
39
<>

src/app/legal/terms.html/page.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import { Metadata } from 'next';
2+
3+
export const metadata: Metadata = {
4+
title: "Terms of Service - RegexPlanet",
5+
};
6+
17
export default function Page() {
28

39
return (

src/app/page.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
/* eslint-disable @next/next/no-img-element */
22
import { EngineButton } from '@/components/EngineButton';
33
import { getEngines } from '@/engines';
4+
import { Metadata } from 'next';
5+
6+
export const metadata: Metadata = {
7+
title: "RegexPlanet",
8+
description: `Regular expression (regex/regexp) testing and debugging for ${getEngines().map(x => x.short_name).join(', ')}.`,
9+
};
410

511
export default function Home() {
612

713
const buttons = getEngines().map((engine) => {
8-
return ( <EngineButton key={engine.handle} engine={engine} />);
14+
return (<EngineButton key={engine.handle} engine={engine} />);
915
});
1016

1117
return (
@@ -24,6 +30,22 @@ export default function Home() {
2430
{buttons}
2531
</div>
2632
</div>
33+
<h2 className="mt-3">One last thing</h2>
34+
35+
<div className="card my-3 bg-light">
36+
<div className="card-body">
37+
Some people, when confronted with a problem, think &ldquo;I know, I’ll use regular expressions.&rdquo; Now they have two problems.<br />
38+
&nbsp;&nbsp;-- <a href="http://www.jwz.org/">Jamie Zawinski</a> in comp.lang.emacs (or <a href="http://regex.info/blog/2006-09-15/247">somewhere else</a>).
39+
</div>
40+
</div>
41+
42+
<div className="card my-3 bg-light">
43+
<div className="card-body">
44+
I define UNIX as &ldquo;30 definitions of regular expressions living under one roof&rdquo;.<br />
45+
&nbsp;&nbsp;-- <a href="https://www-cs-faculty.stanford.edu/~knuth/">Donald Knuth</a> in <a href="http://amzn.to/GXRTbS">Digital Typography</a>, ch. 33, p. 649 (1999) via <a href="http://code.google.com/p/re2/wiki/Syntax">re2</a>.
46+
</div>
47+
</div>
48+
2749
</>
2850
);
2951
}

src/app/sitemap.xml/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export async function GET() {
1515

1616
getEngines().forEach((engine) => {
1717
urls.push(`/advanced/${engine.handle}/index.html`);
18+
urls.push(`/advanced/${engine.handle}/options.html`);
1819
});
1920

2021
const body = urls

0 commit comments

Comments
 (0)