~emersion/public-inbox

gamja: Linkify channel names v3 APPLIED

Tom Lebreux: 1
 Linkify channel names

 4 files changed, 62 insertions(+), 8 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~emersion/public-inbox/patches/23114/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH gamja v3] Linkify channel names Export this patch

---
Changes from v2:
- Rebased on master

Changes from v1:
- Fixed issues mentionned

As said in the v2 patch, I chose the TODO route for the channel name
regex, I could try experimenting with (\w|-|_) though if you prefer.
 components/app.js           | 17 ++++++++++++++-
 components/buffer-header.js |  2 +-
 components/buffer.js        |  9 +++++---
 lib/linkify.js              | 42 ++++++++++++++++++++++++++++++++++---
 4 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/components/app.js b/components/app.js
index 0f55d6835370..5fc2034c971e 100644
--- a/components/app.js
+++ b/components/app.js
@@ -225,6 +225,7 @@ export default class App extends Component {
		this.toggleBufferList = this.toggleBufferList.bind(this);
		this.toggleMemberList = this.toggleMemberList.bind(this);
		this.handleComposerSubmit = this.handleComposerSubmit.bind(this);
		this.handleChannelClick = this.handleChannelClick.bind(this);
		this.handleNickClick = this.handleNickClick.bind(this);
		this.autocomplete = this.autocomplete.bind(this);
		this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this);
@@ -908,6 +909,16 @@ export default class App extends Component {
		this.connect(connectParams);
	}

	handleChannelClick(channel) {
		var netID = getActiveNetworkID(this.state);
		var buf = getBuffer(this.state, { network: netID, name: channel });
		if (buf) {
			this.switchBuffer(buf.id);
		} else {
			this.open(channel);
		}
	}

	handleNickClick(nick) {
		this.open(nick);
	}
@@ -1361,6 +1372,7 @@ export default class App extends Component {
						network=${activeNetwork}
						isBouncer=${isBouncer}
						bouncerNetwork=${activeBouncerNetwork}
						onChannelClick=${this.handleChannelClick}
						onClose=${() => this.close(activeBuffer)}
						onJoin=${() => this.handleJoinClick(activeBuffer.network)}
						onAddNetwork=${this.handleAddNetworkClick}
@@ -1475,7 +1487,10 @@ export default class App extends Component {
				onScrollTop=${this.handleBufferScrollTop}
			>
				<section id="buffer" ref=${this.buffer}>
					<${Buffer} buffer=${activeBuffer} onNickClick=${this.handleNickClick}/>
					<${Buffer}
						buffer=${activeBuffer}
						onChannelClick=${this.handleChannelClick}
						onNickClick=${this.handleNickClick}/>
				</section>
			</>
			${memberList}
diff --git a/components/buffer-header.js b/components/buffer-header.js
index 4fe08352bb4b..586c467dc6f8 100644
--- a/components/buffer-header.js
+++ b/components/buffer-header.js
@@ -114,7 +114,7 @@ export default function BufferHeader(props) {
		break;
	case BufferType.CHANNEL:
		if (props.buffer.topic) {
			description = linkify(stripANSI(props.buffer.topic));
			description = linkify(stripANSI(props.buffer.topic), props.onChannelClick);
		}
		actions = html`
			<button
diff --git a/components/buffer.js b/components/buffer.js
index c2cd20f5e6b5..cc19f83ceb65 100644
--- a/components/buffer.js
+++ b/components/buffer.js
@@ -64,6 +64,7 @@ class LogLine extends Component {
	render() {
		var msg = this.props.message;

		var onChannelClick = this.props.onChannelClick;
		var onNickClick = this.props.onNickClick;
		function createNick(nick) {
			return html`
@@ -82,7 +83,7 @@ class LogLine extends Component {
			if (ctcp) {
				if (ctcp.command == "ACTION") {
					lineClass = "me-tell";
					content = html`* ${createNick(msg.prefix.name)} ${linkify(stripANSI(ctcp.param))}`;
					content = html`* ${createNick(msg.prefix.name)} ${linkify(stripANSI(ctcp.param), onChannelClick)}`;
				} else {
					content = html`
						${createNick(msg.prefix.name)} has sent a CTCP command: ${ctcp.command} ${ctcp.param}
@@ -94,7 +95,7 @@ class LogLine extends Component {
				if (msg.command == "NOTICE") {
					prefix = suffix = "-";
				}
				content = html`${prefix}${createNick(msg.prefix.name)}${suffix} ${linkify(stripANSI(text))}`;
				content = html`${prefix}${createNick(msg.prefix.name)}${suffix} ${linkify(stripANSI(text), onChannelClick)}`;
			}

			if (msg.isHighlight) {
@@ -135,7 +136,7 @@ class LogLine extends Component {
		case "TOPIC":
			var topic = msg.params[1];
			content = html`
				${createNick(msg.prefix.name)} changed the topic to: ${linkify(stripANSI(topic))}
				${createNick(msg.prefix.name)} changed the topic to: ${linkify(stripANSI(topic), onChannelClick)}
			`;
			break;
		case irc.RPL_MOTD:
@@ -364,6 +365,7 @@ export default class Buffer extends Component {
			children.push(html`<${NotificationNagger}/>`);
		}

		var onChannelClick = this.props.onChannelClick;
		var onNickClick = this.props.onNickClick;
		function createLogLine(msg) {
			return html`
@@ -371,6 +373,7 @@ export default class Buffer extends Component {
					key=${"msg-" + msg.key}
					message=${msg}
					buffer=${buf}
					onChannelClick=${onChannelClick}
					onNickClick=${onNickClick}
				/>
			`;
diff --git a/lib/linkify.js b/lib/linkify.js
index c9697cd1bd4a..aee4512a134d 100644
--- a/lib/linkify.js
+++ b/lib/linkify.js
@@ -1,12 +1,46 @@
import { anchorme, html } from "./index.js";

export default function linkify(text) {
function linkifyChannel(text, transformChannel) {
	var children = [];
	// TODO: Don't match punctuation
	const channelRegex = /(^|\s)(#[^\s]+)/gid;
	let match;

	var last = 0;
	while ((match = channelRegex.exec(text)) !== null) {
		const [_, spaces, channel] = match;

		const start = match.index + spaces.length;
		children.push(text.substring(last, start));
		children.push(transformChannel(channel));

		last = match.index + spaces.length + channel.length;
	}
	children.push(text.substring(last));

	return children;
}

export default function linkify(text, onChannelClick) {
	function transformChannel(channel) {
		function onClick(event) {
			event.preventDefault();
			onChannelClick(channel);
		}
		return html`
			<a
				href="irc:///${encodeURIComponent(channel)}"
				onClick=${onClick}
			>${channel}</a>`;
	}

	var links = anchorme.list(text);

	var children = [];
	var last = 0;
	links.forEach((match) => {
		children.push(text.substring(last, match.start));
		const prefix = text.substring(last, match.start)
		children.push(...linkifyChannel(prefix, transformChannel));

		var proto = match.protocol || "https://";
		if (match.isEmail) {
@@ -22,7 +56,9 @@ export default function linkify(text) {

		last = match.end;
	});
	children.push(text.substring(last));

	const suffix = text.substring(last)
	children.push(...linkifyChannel(suffix, transformChannel));

	return children;
}
-- 
2.31.1
LGTM, pushed. Thanks a lot!

On Tuesday, June 1st, 2021 at 4:39 AM, Tom Lebreux <me@tomlebreux.com> wrote: