Niedzielski has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/392570 )
Change subject: Update: capture wiki link clicks and navigation
......................................................................
Update: capture wiki link clicks and navigation
Extract Link.onClick to link-on-click#onClick and use in ContentSection
so that visiting wiki pages only loads the minimal content needed
inline.
Bug: T177367
Change-Id: I5175d9473c128fce87820e9d11788db7b4dd6df1
---
M package.json
M src/common/components/content-section/content-section.tsx
A src/common/components/link-on-click.ts
M src/common/components/link.tsx
4 files changed, 58 insertions(+), 38 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/marvin refs/changes/70/392570/1
diff --git a/package.json b/package.json
index 2ff5df7..33ff1af 100644
--- a/package.json
+++ b/package.json
@@ -103,7 +103,7 @@
"bundlesize": [
{
"path": "dist/public/index.*.js",
- "maxSize": "3.1KB"
+ "maxSize": "3.2KB"
},
{
"path": "dist/public/runtime.*.js",
diff --git a/src/common/components/content-section/content-section.tsx
b/src/common/components/content-section/content-section.tsx
index a87ad83..601fa17 100644
--- a/src/common/components/content-section/content-section.tsx
+++ b/src/common/components/content-section/content-section.tsx
@@ -1,16 +1,25 @@
+import { History } from "history";
import { h } from "preact";
import { PageSection } from "../../models/page/page";
import Content from "../content/content";
import DynamicHeader from "../dynamic-header/dynamic-header";
+import { onClick } from "../link-on-click";
import "./content-section.css";
export interface Props {
section: PageSection;
}
-export default function ContentSection({ section }: Props): JSX.Element {
+export default function ContentSection(
+ { section }: Props,
+ context: { history?: History }
+): JSX.Element {
return (
- <section class="ContentSection" id={section.fragment}>
+ <section
+ onClick={event => onClick(context, event)}
+ class="ContentSection"
+ id={section.fragment}
+ >
{section.titleHTML && ( // Omit empty headers such as the lead.
<DynamicHeader class="ContentSection-header" level={section.level + 1}>
<Content dangerouslySetInnerHTML={{ __html: section.titleHTML }} />
diff --git a/src/common/components/link-on-click.ts
b/src/common/components/link-on-click.ts
new file mode 100644
index 0000000..85c6cc4
--- /dev/null
+++ b/src/common/components/link-on-click.ts
@@ -0,0 +1,43 @@
+import { History } from "history";
+
+function isModifiedEvent(event: MouseEvent): boolean {
+ return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey;
+}
+
+function isInternalLink(link: HTMLAnchorElement) {
+ // N.B. link.href is used because browsers will transform relative paths to
+ // the full path when set on the HTML anchor, which is what is used to check
+ // against the current origin.
+ return link.href && link.href.indexOf(window.location.origin) === 0;
+}
+
+// TODO: add unit tests
+export function onClick(
+ context: { history?: History },
+ event: MouseEvent
+): void {
+ // When set on an anchor, currentTarget is the anchor. When set on a parent
to
+ // capture all clicks, currentTarget may be something else. Use target and
+ // walk the DOM inclusively upwards until an anchor is found.
+ const link = (event.target as HTMLElement).closest(
+ "a"
+ ) as HTMLAnchorElement | null;
+ if (
+ link &&
+ isInternalLink(link) &&
+ // onClick not prevented default
+ !event.defaultPrevented &&
+ // Ignore everything but left clicks
+ event.button === 0 &&
+ // Let browser handle "target=_blank" etc.
+ !link.target &&
+ // Ignore clicks with modifier keys
+ !isModifiedEvent(event) &&
+ // We have a context history
+ context.history
+ ) {
+ event.preventDefault();
+ const path = link.href.replace(window.location.origin, "");
+ context.history.push(path);
+ }
+}
diff --git a/src/common/components/link.tsx b/src/common/components/link.tsx
index 75ec31c..668fb96 100644
--- a/src/common/components/link.tsx
+++ b/src/common/components/link.tsx
@@ -1,13 +1,10 @@
-import { h } from "preact";
import { History } from "history";
+import { h } from "preact";
import { ChildrenProps, classOf, ClassProps } from "./preact-utils";
+import { onClick } from "./link-on-click";
export interface Props extends ClassProps, ChildrenProps {
href: string;
-}
-
-function isModifiedEvent(event: MouseEvent): boolean {
- return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey;
}
/**
@@ -22,36 +19,7 @@
<a
class={classOf("Link", props.class)}
href={href}
- onClick={event => {
- const origin = window.location.origin;
- // Use currentTarget as target may be other DOM elements inside the
- // anchor element
- const link = event.currentTarget as HTMLAnchorElement;
- // TODO: Move all the logic to check if an event should be captured to
a
- // DOM utilities module and add unit tests
- if (
- // Check if the href is internal
- //
- // N.B. link.href is used because browsers will transform relative
- // paths to the full path when set on the HTML anchor, which is what
- // is used to check against the current origin
- link.href &&
- link.href.indexOf(origin) === 0 &&
- // onClick not prevented default
- !event.defaultPrevented &&
- // Ignore everything but left clicks
- event.button === 0 &&
- // Let browser handle "target=_blank" etc.
- !link.target &&
- // Ignore clicks with modifier keys
- !isModifiedEvent(event) &&
- // We have a context history
- context.history
- ) {
- event.preventDefault();
- context.history.push(href);
- }
- }}
+ onClick={event => onClick(context, event)}
>
{children}
</a>
--
To view, visit https://gerrit.wikimedia.org/r/392570
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I5175d9473c128fce87820e9d11788db7b4dd6df1
Gerrit-PatchSet: 1
Gerrit-Project: marvin
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: Sniedzielski <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits