0% found this document useful (0 votes)
24 views81 pages

92775424

The document promotes the ebook 'Fullstack Web Components: Complete Guide to Building UI Libraries with Web Components' by Steve Belovarich, which covers the development of UI libraries using Web Components. It includes links to download the book and other related ebooks, along with a detailed table of contents outlining various topics and chapters. The book aims to provide readers with hands-on experience in creating reusable UI components and applications using web specifications.

Uploaded by

pitadaneekie
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views81 pages

92775424

The document promotes the ebook 'Fullstack Web Components: Complete Guide to Building UI Libraries with Web Components' by Steve Belovarich, which covers the development of UI libraries using Web Components. It includes links to download the book and other related ebooks, along with a detailed table of contents outlining various topics and chapters. The book aims to provide readers with hands-on experience in creating reusable UI components and applications using web specifications.

Uploaded by

pitadaneekie
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Download the Full Ebook and Access More Features - ebooknice.

com

(Ebook) Fullstack Web Components: Complete Guide


to Building UI Libraries with Web Components by
Steve Belovarich; (edited by) Nate Murray ISBN
B0BGYPWQVR
https://ebooknice.com/product/fullstack-web-components-
complete-guide-to-building-ui-libraries-with-web-
components-46387712

OR CLICK HERE

DOWLOAD EBOOK

Download more ebook instantly today at https://ebooknice.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

(Ebook) Fullstack Web Components: Complete Guide to


Building UI Libraries with Web Components by Steve
Belovarich; (edited by) Nate Murray ISBN B0BGYPWQVR
https://ebooknice.com/product/fullstack-web-components-complete-guide-
to-building-ui-libraries-with-web-components-46387706

ebooknice.com

(Ebook) Fullstack Web Components: Complete Guide to


Building UI Libraries with Web Components by Steve
Belovarich; (edited by) Nate Murray ISBN B0BGYPWQVR
https://ebooknice.com/product/fullstack-web-components-complete-guide-
to-building-ui-libraries-with-web-components-46387712

ebooknice.com

(Ebook) Developing Web Components with Svelte: Building a


Library of Reusable UI Components by Alex Libby ISBN
9781484290385, 1484290380
https://ebooknice.com/product/developing-web-components-with-svelte-
building-a-library-of-reusable-ui-components-47898820

ebooknice.com

(Ebook) Developing Web Components with Svelte: Building a


Library of Reusable UI Components by Alex Libby ISBN
9781484290392, 1484290399
https://ebooknice.com/product/developing-web-components-with-svelte-
building-a-library-of-reusable-ui-components-54929064

ebooknice.com
(Ebook) Fullstack Node.js: The Complete Guide to Building
Production Apps with Node.js by Davit Guttman; Nate Murray
(ed) ISBN 08671X
https://ebooknice.com/product/fullstack-node-js-the-complete-guide-to-
building-production-apps-with-node-js-11798290

ebooknice.com

(Ebook) Developing Web Components with TypeScript: Native


Web Development Using Thin Libraries by Jorg Krause
[Krause, Jörg] ISBN 9781484268391, 1484268393
https://ebooknice.com/product/developing-web-components-with-
typescript-native-web-development-using-thin-libraries-23948638

ebooknice.com

(Ebook) Developing Web Components: UI from jQuery to


Polymer by Jarrod Overson, Jason Strimpel ISBN
9781491949023, 1491949023
https://ebooknice.com/product/developing-web-components-ui-from-
jquery-to-polymer-5035788

ebooknice.com

(Ebook) Developing Web Components with TypeScript: Native


Web Development Using Thin Libraries by Jorg Krause
[Krause, Jörg] ISBN 9781484268391, 9781484268407,
1484268393, 1484268407
https://ebooknice.com/product/developing-web-components-with-
typescript-native-web-development-using-thin-libraries-24047404

ebooknice.com

(Ebook) Fullstack GraphQL: The Complete Guide to Writing


GraphQL Servers and Clients with TypeScript by Gaetano
Checinskil; Roy Derks; (ed) Nate Murray
https://ebooknice.com/product/fullstack-graphql-the-complete-guide-to-
writing-graphql-servers-and-clients-with-typescript-23430186

ebooknice.com
Fullstack Web Components
The Complete Guide to Building UI Libraries
and Web Applications with Web Components

Nate Murray

This book is for sale at http://leanpub.com/fullstackwebcomponents

This version was published on 2022-06-10

* * * * *

This is a Leanpub book. Leanpub empowers authors and publishers


with the Lean Publishing process. Lean Publishing is the act of
publishing an in-progress ebook using lightweight tools and many
iterations to get reader feedback, pivot until you have the right book
and build traction once you do.

* * * * *

© 2022 Nate Murray


Table of Contents

Book Revision
Join Our Discord
Bug Reports
Be notified of updates via Twitter
We’d love to hear from you!

Introduction
Foreword
About the author
Web Components
About this book
Who is this book for
Introduction to Web Components
What are Web Components?
The many uses of Web Components
Implementing a design system with Web Components
Conventions used in this Book
Storybook
Application
Cypress
Storyshots
Monorepo
Setting up the development environment
Prerequisites
Summary

Part One
Part One
Specification
What you will learn
Developing in Part One

Getting to Know Web Components


Chapter One
Introduction
What you will build
What you will learn
Acceptance criteria
Getting started
Scaffolding CardComponent
Structure content with template slots
Create controls for the story
Styling
Testing the card
Summary

Form-associated custom elements


Chapter Two
Introduction
What you will build
What you will learn
Acceptance criteria
Getting started
Scaffolding TextInputComponent
Structure the content
Define the story
Form Associated and ElementInternals
Handling Validation
Listening for attribute changes
User feedback
Handling Disabled State
Make stories
Styling with CSS variables
Emulating HTMLInputElement
Making a form
Handling FormData
Testing TextInputComponent
Summary

Customized built-in elements


Chapter Three
Introduction
What you will build
What you will learn
Acceptance criteria
Getting started
Scaffolding ButtonComponent
Styling ButtonComponent
Making the form accessible
Testing ButtonComponent
Summary

Part Two
Part Two
UI Library
What you will learn
Developing in Part Two

Micro-library
Chapter Four
Introduction
What is a micro-library?
Coding in a monorepo
What you will build
What you will learn
Acceptance criteria
Getting started
Class Decorator
Method Decorator
Define the Listen decorator
Refactor TextInputComponent
Summary
Compound Custom Elements
Chapter Five
Component Communication
What you will build
What you will learn
Acceptance criteria
Getting started
Mocking Table Data in Storybook
Coding Compound Components
Attribute Drilling
BroadcastChannel
Rendering Columns and Rows
Styling TableComponent
Handling CRUD Events with BroadcastChannel
Making the Table Editable
Testing the Table
Summary

Powering Dialogs with HTML Templates


Chapter Six
HTML Templates
What you will build
What you will learn
Acceptance criteria
Getting started
Mocking the Dialog in Storybook
DialogComponent
Modal and Tooltip
Querying DOM Across Shadow Boundaries
DialogStack
Testing Dialogs
Summary

Distributing Custom Element Libraries


Chapter Seven
UI Libraries
What you will build
What you will learn
Acceptance criteria
Getting started
Distributing Custom Element UI Libraries
Providing Documentation with Custom Elements Manifest and
Storybook
Set up Continuous Integration with Github Actions
Summary

Part Three
Part Three
Application
What you will learn
Developing in Part Three

Application Development with Custom Elements


Chapter Eight
Application Development with Custom Elements
What you will build
What you will learn
Acceptance criteria
Getting started
Landing Page
App Header
Cookie Footer
Landing Page Content
Summary

Routing Custom Elements in a SPA


Chapter Nine
Routing Custom Elements in a SPA
What you will build
What you will learn
Acceptance criteria
Getting started
Routing
Login View
Dashboard View
Summary

Server-side Rendering with Declarative Shadow


DOM
Chapter Ten
Server-Side Rendering Custom Elements
What you will build
What you will learn
Acceptance criteria
Getting started
Declarative Shadow DOM Templates
Shim
Ponyfill
Express Middleware
Summary

Fullstack Web Components


Conclusion
Specification
Benefits
The future is bright

Changelog
Revision 1 (04-04-2022)
Revision 2 (12-06-2022)
Book Revision
Revision 1 - Initial pre-release of the book - 04-04-2022

Revision 2 - Change book cover - 12-06-2022

Join Our Discord


Come chat with other readers of the book in the official newline
Discord channel:

Join here: https://newline.co/discord/webcomponents

Bug Reports
If you’d like to report any bugs, typos, or suggestions just email us
at: [email protected].

Be notified of updates via Twitter


If you’d like to be notified of updates to the book on Twitter, follow
us at @fullstackio.

We’d love to hear from you!


Did you like the book? Did you find it helpful? We’d love to add your
face to our list of testimonials on the website! Email us at:
[email protected].
Introduction
Acknowledgements

For my wife Susanne.

Foreword
This is a book about Web Components. UI components are a
common pattern in many front end web development frameworks
like Angular, React or Vue, but coding user interfaces in the context
of a framework usually makes sharing those components difficult.
Angular components can’t be easily loaded in the context of React,
for instance. The framework is a closed system.

If you can move past the framework, and possibly enjoy the
simplification and standardization offered by web specifications,
coding with Web Components can be quite rewarding. Working
directly with specifications opens up a world once obscured by the
framework. The web platform is yours to explore and find interesting
ways to utilize parts of HTML, CSS, and JavaScript. By using web
specifications to code UI components you can achieve extraordinary
results. When used responsibly, adopting Web Components as your
UI component pattern can lead to stellar performance, compliance
with accessibility standards, and reusability.

At enterprise corporations it can be rather costly to support several


development teams. One way to reduce operational overhead is to
standardize UI components and reuse them across a software
product. This cuts down on teams “reinventing the wheel”. I’ve
witnessed teams struggle with user interface development at several
companies. It can be quite difficult to coordinate the use of a UI
library, particularly when it’s coded with a JavaScript framework.
User interfaces built with the Web Components are interoperable
with any JavaScript framework. Dependencies become hard to
maintain over a distributed software ecosystem, teams have
conflicting priorities making it difficult to not just upgrade
components, but also framework dependencies. When companies
adopt Web Components as the solution for a UI component library, it
can reduce the churn associated with framework dependencies. I
wrote this guide for developing user interfaces using only web
specifications because I believe it’s in the best interests of software
engineers at enterprise corporations to code in a way that allows
user interfaces to be used over a long lifespan. Corporations
shouldn’t have the reinvest in user interfaces at the rate JavaScript
frameworks go in and out of fashion.

It’s one thing to help by providing examples or peer programming,


but I didn’t think that was enough. While coding a micro-library for
developing Web Components, I found it difficult to find resources.
This book is designed to take on a journey with Web Components as
if you were developing a UI library at an enterprise corporation. You
won’t just get hands-on experience coding UI with Web
Components, but also learn how to test and maintain those
components in the context of a distributed UI library. This book will
make you proficient enough to develop a UI library, web application
or some other fantastical flights of fancy with Web Components.

About the author


Stephen Belovarich is a web engineer who started tinkering with
web development in the 90s. After developing his first website,
Stephen became enamored with the extraordinary potential of the
web. For several years after attending college at Rensselaer
Polytechnic Institute, he coded e-commerce solutions and marketing
portals for freelance clients while creating net art for display in fine
art galleries. Specializing in user interface library and web application
architecture, Stephen has developed interactive user experiences for
Lexus, Ubiquiti Networks, NBC Universal, Nike, and Symantec.
Stephen Belovarich is a Principal Software Development Engineer at
Workday. Stephen is passionate about teaching the next generation
of web engineers how to navigate the ever-expanding web platform.
He taught computer science and engineering at General Assembly
and Syracuse University, has presented at ng-conf, ACT-W, and
meetups around Portland, Oregon where he currently resides.

Web Components
Before the set of technologies known as Web Components were
available engineers had to select an opinionated JavaScript
framework to abstract user interfaces into “components”. Web
Components are interoperable with virtually any JavaScript library or
framework because they are developed using only browser
specifications. The lifespan of a user interface component built with
Web Components can be much greater than a component built with
a library since browser specifications exist for a very long time. Web
Components can have dynamic templates, handle complex form
behaviors, even inherit characteristics of familiar HTML elements like
<button> or <table>. By coding a UI library with Web Components,
you can ensure the components have a farther reach than
components only compatible with a specific library or framework.
Depending on implementation, components coded with Web
Components specifications can out perform framework-based
components as well, due to the lack of dependencies and overhead
inherit in JavaScript frameworks.

About this book


In this book, we’re going to learn how to develop a user interface
library and web application with Web Components. We’ll start by
coding UI components using the set of specifications that comprise
Web Components, increasing in complexity while covering real world
problems: forms, custom templates, editable tables, and dialogs. In
a lerna monorepo, we’ll code almost exclusively with Storybook as
our development environment and write tests for each component
using Cypress. After configuring the UI library for distribution, we’ll
import the components into a fullstack web application built entirely
with Web Components. In each chapter, you’ll find step-by-step
instructions for coding each component and developing a web
application with Web Components. By the end of this book, you’ll
have developed a user interface library from a design system in
Figma and used those components in the context of a web
application.

Who is this book for


This book is for anyone who wants to learn how to architect and
develop a user interface library with Web Components. By learning
how to architect reusable components, you’ll be able to make better
decisions when developing user interfaces in the future. Web
Components are a fundamental building block of front end web
development. Anyone with some prior knowledge of JavaScript,
HTML, and CSS should be able to make sense of this book.

In the next section we’re going to provide an in-depth introduction


to Web Components and how they are used in the real world. This
will get much of the theory and vocabulary out of the way and allow
us to buckle down and develop Web Components in the chapters
that follow.

Introduction to Web Components


In the nineties web development was egalitarian. HTML provided a
syntax anyone could learn. A <p> element displays a paragraph. An
<img> element displays an image, provided a src attribute has a valid
address for an image file. The HTML standard evolved over time,
however the elements used in development in the nineties still work
today.
What it takes to develop a website has dramatically changed over
the years. Web development became even more sophisticated when
corporations discovered an advantage web had over native: anyone
can access software in a web browser and updates can be pushed
server-side, without the need for the end-user to trigger a software
update. JavaScript frameworks like React, Angular, and Vue filled in
the gaps of the ECMAScript standard, giving web engineers
sophisticated tools and patterns for coding feature-rich web
applications. React, in particular, popularized the notion of classes
with React.createClass before ECMAScript delivered the standards-
based class with the ES2015 standard, otherwise known as ES6.
While JavaScript frameworks created fragmentation with
incompatible component models, JavaScript frameworks have one
thing in common. React, Angular, and Vue all feature a discrete unit
of functionality that encapsulates template, styling, and user
interface behaviors called the “component”.

Framework-based UI components solved a distinct problem in web


development by providing a component model, but the web platform
lagged behind. There was no way to create a custom HTML element.
Web developers could only use the HTML elements provided by the
HTML standard, and extending the prototype of a native HTML
element was considered a bad practice. In web application
templates, each of the frameworks allow framework components to
be declared alongside HTML elements, although components from
two different frameworks don’t necessarily work together in the
same template. The opinionated implementation of one framework
component clashes with another. Rendering multiple framework
components in a single architecture can become extremely brittle.
It’s amazing how much JavaScript frameworks provide out of-the-
box, but they don’t really play nice together.

The fragmentation caused by JavaScript frameworks pose a problem


at scale in corporations. Maintaining a consistent look and feel
across a portfolio of many web applications is seemingly impossible
when several engineering teams develop with different JavaScript
frameworks. The same UI component could be duplicated many
times over as the component is developed specifically for each
framework. Pushing out changes to design and UX behavior
becomes a herculean task, dealing the dependency chain of each
JavaScript framework along the way.

Supporting accessible behaviors in framework-based UI components


is challenging because when developing custom UI you essentially
have to reinvent the wheel. Engineers may create a button
component with a framework, but mistakingly use the template of a
<div>, losing the accessibility behaviors of <button> in the process.
The engineer would have to implement event listeners on keydown
to listen for the spacebar and return keys being pressed, adding to
the complexity of the codebase they maintain. Custom elements can
extend from native HTML elements, retaining the accessibility
behaviors of the element they extend from. This isn’t to say Web
Components aren’t without challenges when it comes to accessibility.
Shadow DOM can block screen readers from analyzing WAI-ARIA
attributes when ids are deeply nested across Shadow boundaries, so
developer intervention maybe needed to coax screen readers to
obtain the desired results for accessibility.

Other problems with framework-based UI component development


occur over time. Breaking changes in major versions of frameworks
can cause churn. As frameworks optimize over time, breaking
changes to syntax or different ways of working force engineers to
relearn how UI components are developed. Rarely nowadays would
you see React.createClass in a modern React application, instead
engineers would use the class-based React.Component or a functional
implementation with React hooks. A standards-based Web
Component has a longer lifespan than framework components. Like
those HTML elements <p> and <img>, Web Components are part of
the HTML specification. A custom element registered with the
CustomElementRegistry will work in browsers for several years to
come.
1 export class CardComponent extends HTMLElement {
2 constructor() {
3 super();
4 const shadowRoot = this.attachShadow({ mode: 'open' }\
5 );
6 const template = document.createElement('template');
7 template.innerHTML = `
8 <style>
9 :host {
10 display: block;
11 background: white;
12 border-radius: 12px;
13 border: 4px solid black;
14 overflow: hidden;
15 max-width: 320px;
16 min-height: 120px;
17 }
18 </style>
19 <header>
20 <slot name="header"></slot>
21 </header>
22 <section>
23 <slot name="body"></slot>
24 </section>
25 <footer>
26 <slot name="footer"></slot>
27 </footer>
28 `;
29 shadowRoot.appendChild(template.content.cloneNode(tru\
30 e));
31 }
32 }
33 customElements.define('in-card', CardComponent);

Web Components are interoperable, meaning custom elements can


be used in the context JavaScript frameworks like any other HTML
element.
1 export {CardComponent} from "./custom-element";
2
3 export const App = () => {
4 return (
5 <div>
6 <in-card></in-card>
7 </div>
8 )
9 }
10
11 ReactDOM.render(<App />, document.querySelector("#root"));
Custom elements created with the Web Components standard can
retain the accessibility behaviors of the HTML elements they extend.
A customized built-in element that extends from HTMLButtonElement
includes all the traits of a typical HTML <button> element. When the
user presses Enter or Space, the button is activated without any
custom logic. This isn’t to say sometimes accessibility behaviors are
not necessary to implement in autonomous custom elements or
form-associated custom elements.
1 export class ButtonComponent extends HTMLButtonElement {
2 constructor() {
3 super();
4 }
5 connectedCallback() {
6 this.addEventListener('click', this.onClick);
7 }
8 onClick() {
9 this.dispatchEvent(new CustomEvent('buttonClicked'));
10 }
11 }
12
13 customElements.define('in-button', ButtonComponent, {exte\
14 nds: 'button'});

Somehow we find ourselves at a place where web development is no


longer egalitarian. The learning curve for web development is absurd
for anyone who just wants to put a custom element on a page. Not
only does someone have to learn the component model for a
particular JavaScript framework, but how to test, maintain, and
deploy complex framework code. Then another framework becomes
popular and engineers have to relearn everything. We call this
JavaScript fatigue. Part of the problem is the fragmentation, but in
my opinion, it’s mostly a problem with education. If people new to
web development are skipping web standards in favor of learning
frameworks, they are adding complexity, without learning about how
things work. HTML elements are the most primitive Object we have
to deal with in web development. Anyone can start developing UI
with Web Components right in the browser.
While it’s not practical to develop custom elements this way in the
browser, the example above is useful to demonstrate that Web
Components require zero dependencies to work.

What are Web Components?


Front end web development usually requires handling templates,
styling, and logic that defines the behavior of discrete functional
units, commonly referred to as UI components. Web Components
are a set of browser specifications that provides encapsulation and
organization for user-interface logic in a standard component model.
The term “custom elements” is often used interchangeably with
“web components”, although custom elements are just one of the
specifications that comprise Web Components.

Web Components is a marketing term that refers to several browser


standards maintained by the Web Hypertext Application
Technology Working Group (WHATWG) and the World Wide
Web Consortium (W3C) in the HTML Living Standard and
DOM Standard, documents that establish the ongoing state of
Hyper Text Markup Language (HTML) and Document Object Model
(DOM). WHATWG is comprised of web engineers from Apple,
Google, Microsoft, Mozilla, Opera and the broader web development
community. In 2019, W3C and WHATWG agreed to work together to
maintain the HTML standard as a living document that constantly
evolves over time.
In contrast to open source JavaScript frameworks that are
maintained by corporate teams or the broader community, Web
Components are developed through a rigorous standardization
process. Once a particular Web Component standard is finalized,
browser vendors prioritize and implement the specification. As of
January 2020, all major web browsers including Apple Safari, Google
Chrome, Microsoft Edge, Mozilla Firefox, and Opera implemented the
major feature of Custom Elements v1 specification: autonomous
custom elements. Other specifications under the Web Components
umbrella, such as Shadow DOM and HTML templates, have been
part of the HTML standard for quite some time, while some like
Declarative Shadow DOM or Constructable Stylesheets have yet to
be included in all major web browsers. As HTML is a living
document, support changes over time and any feature that lacks
support in some browsers can be polyfilled. We’ll look into this in
more detail later. For now, let’s define the various specifications that
make up Web Components.

Custom elements

The cornerstone of the Web Components featureset, custom


elements allow new HTML tags to be defined in a web browser.
Custom Elements v1 is the stable implementation of the custom
elements specification. This standard allows you to define a new
HTML element and the HTML element’s JavaScript API. Other
specifications like ElementInternals extend the functionality of
custom elements beyond the set of specifications known as Custom
Elements v1. Custom elements allow you to observe changes to
element attributes and manage content and styling for the new
element’s template. Custom elements behave like any other HTML
element, with some syntactical sugar that promotes standardization
across any custom element behavior.

There are three different types of custom elements: autonomous


custom elements, customized built-in elements, and form-associated
custom elements.

Autonomous custom elements

Autonomous custom elements allow you to define customized


functionality for a new HTML element. Autonomous custom
elements extend from the HTMLElement class. The most compatible
custom element type, autonomous custom elements are available in
all evergreen browsers. This specification is what people are typically
referring to when describing Web Components or Custom Elements
v1.

Customized built-in elements

Customized built-in elements extend from known HTML


elements, retaining the behaviors of those elements. Customized
built-in elements behave differently than autonomous custom
elements, although this specification retains many of the features of
autonomous custom elements. Customized built-in elements can be
used in several evergreen browsers, except Apple Safari which
requires a polyfill.

Form-associated custom elements

HTMLFormElementcannot access form controls like HTMLInputElement


and HTMLSelectElement that are within a custom element’s Shadow
DOM tree. This means form validation is precarious at best. Form-
associated custom elements provide an extended API from
autonomous custom elements that gives you hooks into form
validation. This means you can still encapsulate a form control’s
template, while exposing the validity of the control to the parent
HTMLFormElement. Form-associated custom elements open the door
for the creation of truly customized user experiences that participate
in HTML forms. Instead of merely relying on traditional form
elements, it’s now possible to make your own.
In the first part of this book, we’ll investigate the similarities and
differences between the different types of custom elements and see
how they work together to provide complex, reusable components.

CustomElementRegistry

This interface on the window.customElements property provides


methods for registering custom elements and querying registered
elements. Every custom element must be registered with the
CustomElementRegistry through a declarative syntax.

Shadow DOM

Shadow DOM is a browser technology that provides encapsulation


for a HTML element, isolating the HTML element’s template from the
rest of DOM. When using Shadow DOM with custom elements, you
can isolate <style> and <script> within the ShadowRoot: the root
node of a DOM substructure rendered outside the scope of DOM.
The top level element that employs Shadow DOM is considered the
host element. The ShadowRoot is attached to the host element. In
contrast to Shadow DOM, anything outside of the shadow boundary
in the global scope of the document is considered Light DOM.

When you query for an element on the document using


document.querySelector or similar method, you are essentially
querying the entire document because the Document Object Model
(DOM) has a global scope. If you wanted to style an element or
enhance an element with some logic via JavaScript, you would have
to inject a <style> or <script> tag into the document, usually the
<head> or before the closing <body> tag in the case of JavaScript that
relies on querying for DOM that is fully loaded. Because of the global
nature of DOM, CSS or JavaScript intended for one HTML element
could collide with another the styling or logic wasn’t intended for.
When developing UI components it’s extremely helpful to rely on an
isolated scope for the component, so CSS and JavaScript collisions
can’t happen.

HTML Template

The <template> tag, first introduced in HTML5, allows HTML to be


predefined and reused throughout DOM. HTML templates are parsed
but not rendered until cloned. This behavior allows for custom
element templates to be rendered performantly when HTML
templates are used in conjunction with Shadow DOM.

HTML, CSS, and JSON Modules

Replacing the deprecated specification for JSON, CSS and HTML


modules allow for custom elements to request resources
asynchronously. Yet to be finalized the JSON, CSS and HTML
modules specifications are currently in development by WHATWG
and W3C.

CSS Shadow Parts

When Shadow DOM was introduced, the only way to style a custom
element’s ShadowRoot from the context of Light DOM was to use CSS
variables. CSS variables were the only method that pierced the
Shadow boundary.

CSS Shadow Parts is a CSS pseudo selector ::part that allows styling
of any elements within a Shadow DOM tree that has a matching part
attribute. ::part is available in all evergreen browsers. WHATWG is
currently working on new specifications that enable greater flexibility
when styling Shadow DOM including a specification known as
Constructable Stylesheets.
Declarative Shadow DOM

Declarative Shadow DOM allows you declare Shadow DOM directly in


HTML, without the need for JavaScript. This specification opens the
doors for server-side rendering Shadow DOM and reduces the
complexity when testing Web Components. With Declarative Shadow
DOM, a custom element’s Shadow Root tree can be statically
generated and analyzed.

Typically there are limitations when server-side rendering custom


elements. With the available tools, you may only be able to render a
Shadow Root that is directly exposed to Light DOM, but not render
any templates deeper in that Shadow Root’s tree. Even though
you’ve the ability for web crawlers to analyze Shadow DOM that’s
server-side rendered, there could be an unsettling flash of unstyled
content or layout shifting while loading a Shadow Root stylesheet in
the browser.

Declarative Shadow DOM negates prior limitations to server-side


rendering custom elements by providing a way to declare Shadow
DOM via HTML, without JavaScript. Declarative Shadow DOM is
available in Google Chrome and Microsoft Edge. A simple polyfill
brings Declarative Shadow DOM to browsers that have not
implemented the specification.

The many uses of Web Components


Web Components have been growing in popularity since the main
specification that drives the standard, Custom Elements v1, became
available in all evergreen browsers in January 2020 with the release
of the Chromium-based Microsoft Edge browser. In 2022, Google
reported Web Component usage had almost quadrupled since 2019:
18% of websites include a custom element on the page.
Single page applications

Web Components don’t replace all the functionality provided by a


JavaScript framework. Frameworks provide abstraction around
common web development tasks: routing, state management, data
binding, and coding UI components. Web Components overlap only
this last feature of JavaScript frameworks: the UI component.

You probably wouldn’t develop a complex single page application


solely with Web Components, opting to integrate custom elements
with a JavaScript framework instead. If the desire is to code a single
page application with minimal to zero external dependencies, Web
Components require, at the very least, a routing mechanism that can
instantiate and destroy custom elements. In Part Three of this book,
we’re going to cover how to use Web Components in the context of
a single page application.

Standalone widgets

Sometimes you need to code a standalone user interface that


shouldn’t interact with the rest of the page and needs to work on
several different sites. It doesn’t make sense to use a JavaScript
framework because you incur the cost of loading a dependency that
may be larger in filesize than your implementation.

Web Components work out extremely well in this scenario because


you’re coding with “vanilla” JavaScript. You can encapsulate the
template of a custom element with Shadow DOM so your component
can’t easily interact with the surrounding page. If your task is to
develop a standalone widget, you’ll learn most of what you need in
the first chunk of this book. Part One features several hands-on
exercises where you’ll explore the custom elements specification.
Static websites

Given the portability of custom elements, you can bundle custom


elements and include them in a <script> tag. When the browser
parses DOM, the custom element will be instantiated. If you want to
avoid a flash of unstyled content, it’s possible to server-side render
custom elements. In Part Three, we’re going to talk about server-
side rendering Web Components using Declarative Shadow DOM.

So far I’ve talked about how Web Components behave and where
you might find custom elements. In the next sections, I further
define Web Components through the HTML specification, then talk
about how custom elements can be viewed through the lens of a
design system, followed by a guide for getting started developing
with the repository that accompanies this book.

UI Library

The main appeal of Web Components is due to how custom


elements are interoperable and portable. UI libraries built with Web
Components make a lot of sense at large corporations that need to
scale. If you want UI components to as compatible as possible with
any framework, Web Components are well suited for that task. Don’t
take my word for it! Large corporations like Salesforce, Microsoft,
and Google have adopted Web Components for their open source UI
libraries.

Developing a UI library with Web Components is intuitive because


the goals of the library align with the behavior of Web Components.
UI libraries can gain greater adoption when they are portable,
interoperable, and have a long lifespan. In Part Two of this book,
we’re going to focus on developing a UI library with Web
Components.
Implementing a design system with Web
Components
When developing user interfaces you’ll most likely reference a
mockup provided by a Designer. The UI component you’re
developing is part of a design system. The definition of “design
system” is tricky, as different people have proposed vastly different
definitions, but I’m going to try anyways.

A design system is a set of guidelines for the look and feel of a


product or project. Design systems can feature a mission statement,
design ethos, vocabulary, values and measurements often referred
to as “tokens”, components, layouts, and possibly more. The design
system is a living document that defines reusable patterns engineers
can reference when developing user interfaces.

The main touchpoints for a design system web developers should be


concerned with are the following:

Tokens

Constants that define common reusable design patterns including


color, size, spacing, typography, and more.

Components

Discrete units of user interface functionality that have a distinct


purpose and behavior.

Layouts

Organization of components in a web site.


Conventions used in this Book
Each chapter of this book presents a problem statement and
orientation, followed by acceptance criteria then a step-by-step
walkthrough of the implementation, ending with a summary.

Figma

It’s practical to look at Web Components through the lens of a


design system. Web Components uses tokens as building blocks for
developing a reuseable user interface. Web Components can display
in different orientations or states: a layout. Web Components can
also be part of another layout compromised of one or many
components.

Design systems offer guidance for developing user interfaces.


Throughout this book you’ll reference the Fullstack Web Components
Design System in Figma.

In Figma, you can reference different values of design tokens and


inspect and measure parts of UI components and layouts. Take a
moment and familiarize yourself with the Figma interface. On the left
sidebar is a navigation menu that lists different layers in the focused
artboard. When you click on elements in the artwork, various
properties of the selected element are displayed in the right sidebar.
Whenever an element is selected, the color of that element is
displayed in the right sidebar by token name followed by the
hexidecimal value of the color.

A global CSS stylesheet provided in the development environment


for this book contains CSS variables that map to each design token.
To use the Red/300 token, you’d reference the --color-red-300 CSS
variable:
1 color: var(--color-red-300);

Similarly, CSS variables for sizing, border radius, font, icons and box
shadow are provided on the global stylesheet found in
src/style/style.css. You may reference these CSS variables when
styling each UI component.

Storybook
The main development environment for a considerable portion of
this book is Storybook, “an open source tool for building UI
components and pages in isolation.”
Storybook is run locally on your computer. In several chapters, you’ll
define Stories for the UI component you’re coding. A Story is a
configurable template that hosts your component. Through the
Storybook user interface, you can define different controls that
change UI component behavior. By the end of this book you should
have a good understanding of how to develop and maintain UI
components in Storybook.

Development lifecycle of a UI component in Storybook

1. Reference the mockup in Figma


2. Define the story in Storybook
3. Style the component with design tokens
4. Develop behaviors with JavaScript / TypeScript
5. Write tests

Application
In the third part of this book, you transition from developing user
interface components to developing with those components in the
context of a web application. When developing the application, you’ll
change up the local environment to a custom Webpack server and
only use Storybook when necessary.
The application you’re going to develop is called “In”, a web app
used to store a user’s contact list. After the user authenticates with a
login form, a user interface displays a table filled with contacts. The
user can view or edit the contact list. User interfaces found in the
application are developed in Storybook first, exported from a UI
library package, then imported into the application source code.

Cypress
Cypress is a test runner you’ll use to write end-to-end tests for each
UI component.

Storyshots
Storyshots is a Storybook addon you’ll use to generate automatic
visual snapshots for each UI component.

Monorepo
When developing against the content in this book, you’ll be working
in a monorepo built with lerna. Lerna allows you to manage multiple
projects in the same repository. Those projects are defined as:

client web application front end


common reusable functions, utilities
component UI library
server web application back end
style resources exported from the design system such as CSS
styles, icons, fonts
Throughout the book, you’ll switch between different projects in the
repository depending on what you’re currently working on. When
developing UI components, you’ll work in the component directory.
If you’re developing the web application, you’ll code in files found in
the client or server directories.

Naming

Class names are prefixed to avoid collisions with other UI


component libraries.
File names are in kebab-case.

Setting up the development environment


Getting started is easy. Great care was taken to setup a development
environment that can be used throughout the book, allowing you to
focus on the content of each chapter. To start development, clone
the repository from Github, install project dependencies, and run a
script that runs a local Webpack development server. Each of these
steps are outlined below.

Prerequisites
The following tools should be installed prior to starting development.

Terminal application

Which Terminal you use depends on your system. MacOS and Linux
systems come with the Terminal application. For Windows 10 and
above, all Terminal commands featured in this book should be run
with PowerShell and Windows Subsystem for Linux. Follow these
instructions to install Windows Subsystem for Linux. Running node
scripts in Windows Subsystem for Linux ensures the commands will
work.
git

Changes to the codebase are tracked via git. git is a version control
system that allows projects like this one to track changes across the
codebase effectively. If you have little or no experience with git,
don’t worry. Each chapter clearly demonstrates the git commands
you’ll need to run to navigate between changes. git is installed
differently depending on your system.

Mac
Windows
Linux

NodeJS

node is a JavaScript runtime built from V8 JavaScript engine.


Whereas JavaScript is usually run in a web browser, node runs
server-side. node is traditionally used for back-end services, but it’s
also used to code tooling for JavaScript projects. npm is a package
manager for node. npm packages can be installed in any node
project, allowing you to reuse code published on the npm registry in
a local development environment.

This book requires node 16 and above installed on your machine. It


is highly recommended to install node and npm with nvm, the Node
Version Manager. nvm allows you to install multiple versions of node
locally, switching between them for each project on your system.
Installation instructions for nvm can be found here.

JavaScript IDE

To actually code the various components and application in this book


you’ll need an IDE (integrated development environment). There are
many free IDE, so don’t feel like you need to spend a ton of money
on one. A few popular IDE are listed below. Download and install
your preferred application for JavaScript development.

Visual Studio Code (MacOS, Windows, Linux)


Nova (MacOS)
WebStorm (MacOS, Windows, Linux)
Atom (MacOS, Windows, Linux)

Once you have all of the above tools installed on your system, you’re
ready to clone the git repository, install project dependencies, and
run the development server.

GitHub

The repository for this book is found on GitHub. If you don’t already
have a GitHub account, signup for a new account. If you’ve never
used GitHub before on your machine, you’ll need to setup your
username locally. More information about setting up GitHub locally is
found in the Set up Git Guide.

After you’ve properly setup git locally, fork the repository on Github,
then clone your fork of the repository via the Terminal, making sure
you run the command in a directory where code is usually stored on
your system. If you don’t already have any code projects on your
computer, make a new directory to store this book’s codebase, then
run the following command, inserting your Github username in lieu
of {username}.
1 git clone https://github.com/{username}/fullstack-web-com\
2 ponents.git

Change directory into the project root directory.


1 cd fullstack-web-components

There are times you may need to update your local repository from
the upstream repository, mainly to uptake dependency upgrades or
new content. Further instructions for maintaining your local fork of
the repository are found in the README.md.

Yarn

This repository uses yarn to install npm dependencies and run node
scripts.
1 npm install --global yarn

Once yarn is installed you can install project dependencies with the
yarn command.

1 yarn

Storybook

After project dependencies are installed with yarn, run the storybook
script to start up the local Storybook development environment.
1 yarn storybook

If Storybook appears in the default browser on your computer, you


have correctly setup the development environment for this book.

Summary
Through the practical exercises in this book, you’ll learn how to code
user interfaces that are interoperable, reusable, accessible, portable
and require zero dependencies. The goal is to mirror best practices
at enterprise corporations that you can bring into your own
professional development.
Part One Specification

In the first part of this book, you’re going to take a deep dive into
the Web Components specification by developing the UI components
that comprise a login form. Through developing with the different
types of custom elements and several other parts of the Web
Components specification, you’ll learn:

How to encapsulate template and styling with Shadow DOM


How to provide dynamic templates for a UI component
The lifecycle of a custom element
Event handling and delegation
How to make custom elements accessible
How to architect complex form validations

Part Two UI library

In the second part of this book, we focus on developing Web


Components in a UI library.

We’ll use TypeScript to bring a Decorator pattern to enhance


component development, simplifying common tasks with a
standardized, opinionated interface.
Event handling is taken to a whole new level when we develop a
table component with custom elements.
We’ll focus on the benefit of reusable HTML templates when
developing a panel component.
Later, we’ll implement a theme across the UI library using CSS
Shadow Parts.
Finally, we’ll optimize the UI library for distribution by bundling
every component with Rollup.
Part Three Application

In the third part of the book, we take a look at how Web


Components are used in the context of a web application. Lerna is
introduced to the development environment to coordinate
development of several packages in a monorepo.

First we’ll code an application shell with custom elements


Then we’ll handle routing different views in our application
We will follow that with a lesson about server-side rendering
custom elements with Declarative Shadow DOM.

In the final chapter of this book, we’ll summarize what was learned
and look to the future of Web Component development.

In the next chapter Getting To Know Custom Elements, you will


learn the complete development lifecycle of an autonomous custom
element.
Part One
Part One

Specification
In Part One of this book we’ll explore several Web Components
specifications by developing the UI components that make up a login
form. This login user interface will be used in Part Three so users
can authenticate with the application.

What you will learn


While developing the login use interface with Web Components,
you’ll explore the following concepts:

How to encapsulate template and styling with Shadow DOM


How to provide dynamic templates for a UI component
The lifecycle of a custom element
Event handling and delegation
How to make custom elements accessible
How to architect complex form validations
The differences between autonomous, customized built-in, and
form-associated custom elements

Developing in Part One


You’ll use Storybook as the primary development environment
throughout Part One. For each chapter, run yarn storybook in the
Terminal. Every change made to the codebase will be reflected in the
Storybook UI while Storybook is running in Terminal. When you are
finished developing, cancel the server by holding down Ctrl on the
keyboard and pressing C.
Getting to Know Web Components
Chapter One

Introduction
You can make completely customized HTML elements with
autonomous custom elements, so it can be daunting to know where
to start. In this exercise, autonomous custom elements are
highlighted for what they do best: provide a means to bind template
encapsulation provided by Shadow DOM with a unique HTML tag
and then reuse the custom element throughout DOM.

Autonomous custom elements are the most ubiquitous of the three


types of custom elements due to their compatibility in all major
evergreen browsers including Apple Safari, Google Chrome,
Microsoft Edge, and Mozilla Firefox. When building out a UI library,
you’ll possibly find yourself coding with autonomous custom
elements the most because of their utility.

In addition to autonomous custom elements and Shadow DOM, we’ll


make use of HTML templates and CSS variables in this chapter.

What you will build


In this chapter, you’ll code a reusable container called the Card
component. This component can contain a lot of different templates,
from user profile metadata to a sign-up form, so the template has to
be flexible enough to accept virtually any content, but rigid enough
so that layouts adhere to design guidelines found in the design
system.
What you will learn
What is an autonomous custom element?
What is Shadow DOM and why should I use it?
What is HTMLTemplate and why should I use it?
What are template slots?
What are CSS variables?
How do I use design tokens to style a custom element?
How do I style slotted components?
How do I include a dynamic template in a custom element?
How do I configure controls for a story in Storybook?
How do I define a story in Storybook?
How do I write integration tests for autonomous custom
elements with Cypress?
How do I make snapshots of autonomous custom elements with
Storyshots?

Acceptance criteria
A class called CardComponent is exported from
packages/component/src/card/Card.ts
CardComponent can accept dynamic images, paragraphs, links,
and headlines in the template
CardComponent is styled per the mockup in Figma
CardComponent is configurable via Storybook Controls
Integration tests are found in cypress/integration/Card.spec.js
Snapshot tests validate the design implementation of
CardComponent

Getting started
Navigate to the project directory. The default name of the directory
is fullstack-web-components from when you cloned the git
repository.
1 cd fullstack-web-components

Checkout a new branch named chapter-1. You’ll want to keep the


master branch clean in case any updates trickle in from the main
repository.
1 git checkout -b chapter-1

Run Storybook:
1 yarn storybook
Scaffolding CardComponent
In this first section, you’ll code an autonomous custom element from
scratch. You’ll use Storybook as a development environment. If you
haven’t already, navigate to the project directory and run yarn
storybook. Have no fear if you’ve never coded a custom element
before because this book walks you through each exercise step by
step.

Generate the card component

In the root directory of the project, make a new directory at


src/component/card. mkdir is a good command line utility for this. To
run other commands in your Terminal while Storybook is running,
you’ll need to open another Terminal window or tab and navigate to
the project directory.
1 mkdir -p packages/component/src/card

In the card directory, make a new file and name it Card.ts.

1 touch packages/component/src/card/Card.ts

Here we’re borrowing from a convention of the React style guide,


preferring to name the component files with an uppercase first letter.
This is how files throughout this book will be named; however, you
may name components using whatever convention you desire.

If you haven’t already, now is a good time to open the new Card.js
file in your favorite IDE.

In Card.jsexport a class called CardComponent that extends from


HTMLElement. We need to export this class so we can use it in
Storybook later. All autonomous custom elements extend from the
same base class: HTMLElement, and must include a constructor that
calls super() first, in order to establish the proper prototypical chain.
1 export class CardComponent extends HTMLElement {
2 constructor() {
3 super();
4 }
5 }

Following the call to super(), define the template for the Card.
Instantiate a Shadow DOM template for this component by creating
a const called shadowRoot and making it equal to
this.attachShadow({ mode: 'open' }).

1 const shadowRoot = this.attachShadow({ mode: 'open' }\


2 );

This establishes a Shadow Root for this component, which


encapsulates any DOM nodes inside the ShadowDOM tree from the
rest of the DOM. We can call attachShadow because it exists as a
method on the HTMLElement class, available because we extended
from HTMLElement. attachShadow is also available on any HTML
element that acts as a container like <article>, <div>, <header>,
<h1>, and even <p>. We’re going to define our own HTML tag though
later in this section.

attachShadow takes an argument which is an Object that configures


how ShadowDOM behaves. By setting the property mode to 'open',
we’re allowing access to the Shadow Root via JavaScript and
because of this setting when we reference element.shadowRoot, it
will return an Object. If mode is set to 'closed', element.shadowRoot
will return null. We’ll explore use cases for closing the Shadow DOM
later, but for now it’s safe to keep the ShadowDOM tree open.

Now that we’ve established this custom element should use Shadow
DOM, let’s give it a template using HTMLTemplateElement. In the
constructor, following the shadowRoot, add the following lines of
code:
1 const template = document.createElement('template');
2 template.innerHTML = `
3 <span>Hello World</span>
4 `;
5 shadowRoot.appendChild(template.content.cloneNode(tru\
6 e));

HTML templates are reusable DOM trees that are not parsed until
they are instantiated. In this case, the HTML template will be
instantiated when an instance of the Card component is rendered
and a clone of the template node is appended tp the Shadow Root
appendChild exists on the Shadow Root, which behaves similarly to
any other DOM node.

To verify the component is working initially, include a simple “Hello


World” in the template. The CardComponent class should look like this
when you are finished.
1 export class CardComponent extends HTMLElement {
2 constructor() {
3 super();
4 const shadowRoot = this.attachShadow({ mode: 'open' }\
5 );
6 const template = document.createElement('template');
7 template.innerHTML = `
8 <span>Hello World</span>
9 `;
10 shadowRoot.appendChild(template.content.cloneNode(tru\
11 e));
12 }
13 }

Finally, establish the tag name for the custom element by registering
the class you just defined with the CustomElementRegistry.
1 customElements.define('in-card', CardComponent);

This last step is significant because without it, the browser can’t
interpret CardComponent as the class associated with the HTML tag
<in-card>. We prefixed the tag name with in- because that is the
name of the application we’re coding: In. The tag name for custom
elements is limited to kebab case and can contain at least one dash.
Prefixing the component differentiates it from components from
other design systems that may exist on the same website, so
naming the components is something we want to get right fairly
early on.

Define the story

To visualize the Card component in Storybook, we need to define a


story in a new file.

In the card directory, make a new file and name it Card.stories.js.

1 touch packages/component/src/card/Card.stories.js

In this file, import the CardComponent.

1 import { CardComponent } from "./Card";

Next we should configure where the stories defined here will be


displayed in the Storybook UI.
1 export default {
2 title: "Components/Card",
3 };

Storybook expects any file matching *.stories.js to export a


configuration Object known as Component Story Format as the
default export. At the very least, this configuration includes a title
property with the name of the directory as it should be displayed in
the Storybook sidebar. Categorize stories further with slashes. The
above example configures Storybook to display a collapsible
directory called Components, with a nested directory called Card in
the Storybook sidebar. At least, Storybook will display this directory
once we’ve defined some stories.

Define a template for Storybook. Templates in Storybook are


functions that return a template. In our case, we want to define a
const called PrimaryTemplate and return <in-card></in-card> from
Discovering Diverse Content Through
Random Scribd Documents
Kokoonnuimme pöydän ääreen ja Madrasia alkoi hääräillä
teekannun ja kuppien kimpussa. Pikku seikoista keskusteleminen oli
aivan hyödytöntä, koska Murthwaiten vierailu kiinnosti mieltämme
äärettömästi, ja hän olikin niin älykäs, ettei antanut meidän odottaa
pitkää aikaa uutisiaan.

"Kerron teille nyt lyhyesti saapumiseni syyn", sanoi hän juotuaan


ensimmäisen kupin. "Tänään noin puolenpäivän aikaan tuli luokseni
eräs Charles Sperrigoe niminen herra, joka esitettyään itsensä
kaukaiselta seudulta kotoisin olevaksi virkatoverikseni, kertoi minulle
saaneensa juuri kaupungissa kuulla, että minä olen Kelpieshawin
omistajan, herra James Parslewen asianajaja, ja ilmoitti samalla, että
oli käynyt Kelpieshawissa tapaamassa herra Parsleweä saamatta
häntä kuitenkaan käsiinsä. Sitten hän kertoi minulle erään
ihmeellisen tarinan, jonka kerron teillekin piakkoin. Mutta aluksi
haluan kuulla herra Crayeltä erään seikan, jonka hän luullakseni voi
kertoa. Herra Charles luulee, että herra Craye on eilen illalla kertonut
herra Parslewelle jotakin sellaista, mikä lähetti hänet matkalle päätä
pahkaa. Haluaisin kuulla tuon jutun ja sitten kerron teille, mitä herra
Charles Sperrigoe uskoi minulle."

"Minun on kai parasta kertoa kaikki tätä asiaa koskeva erään


Pawley-nimisen miehen vierailusta teidän tuloonne saakka", sanoin.
"Silloin saatte yhtä täydelliset tiedot koko asiasta kuin minäkin.
Kuulkaa siis."

Hän kuunteli tarkkaavaisesti hörppien teetään ja syöden


paahdettua leipää, ja minä kerroin kaikki yksityiskohdat. Madrasia
korjasi selostustani hieman tahi kuiskasi minulle jotakin silloin tällöin,
ja yhteisvoimin selostimme hänelle ilmeisimmät tosiseikat ja
yksityiskohdat Weechin vierailuun ja viimeisen sähkösanoman
saapumiseen saakka. Madrasia sanoi lopuksi:

"Ja sitten te tulitte; herra Murthwaite. Ja jos vain voitte kertoa


meille, mitä tämä kaikki tarkoittaa, siunaamme teitä."

Mutta Murthwaite pudisti jyrkästi päätään.

"En", vastasi hän. "Kaikki tuntuu minusta vieläkin yhtä


salaperäiseltä kuin ennenkin, vaikka luulenkin näkeväni heikon
valonpilkahduksen — tosin hyvin heikon vain. Voin vain toistaa teille,
mitä Sperrigoe kertoi minulle tänä aamuna. Jos vain saan toisen
kupillisen mainiota teetänne ja savukkeen sen höysteeksi, niin —"

Hän odotti hetkisen kooten ajatuksiaan ja selosti sitten meille


asiaa nojautuen taaksepäin tuolissaan ja viitaten silloin tällöin
savukkeellaan korostaakseen huomautuksiaan, melkein kuin
olisimme muodostaneet jonkinlaisen valamiehistön.

"Toimisto, jonka vanhin osakas herra Charles Sperrigoe on", sanoi


hän, "on jo useita vuosia toiminut erään hyvin vanhan sisämaan
suvun, Palkeneyn kartanon omistajain laillisena neuvonantajana. Te
näette suvun vaakunan täydellisenä kummallisine lauselmineen tuon
kuuluisaksi tulleen kuparilippaan laidassa tuolla pöydällä. Palkeneyt
ovat asuneet Palkeneyssä Tudorien ajoilta saakka — todellisuudessa
sen aikakauden varhaisimmilta vaiheilta asti. Perhe on
ymmärtääkseni hyvin varakas, mutta sellainen, joka on vähitellen
kuollut sukupuuttoon.

"Ja siirtyäksemme melkein nykyaikoihin, muutamia vuosia sitten


tapahtuneisiin seikkoihin, kerron teille, että Palkeneyn kartanossa
asui siihen aikaan muudan vanha herrasmies, herra Matthew
Palkeney, jota luultiin viimeiseksi Palkeneyksi. Hän oli jo hyvin vanha,
melkein yhdeksänkymmenen vuoden ikäinen ukko. Kerran
nuoruudessaan oli hänellä ollut nuorempikin veli, John Palkeney,
mutta hän oli jo nuorenamiehenä ottanut perintöosansa ja
matkustanut pois isiltä peritystä kodistaan palaamatta sinne enää
milloinkaan takaisin. Viimeiset tiedot hänestä oli saatu Etelä-
Amerikasta noin kuusi- tai seitsemänkymmentä vuotta sitten, jolloin
hän oli ollut lähdössä johonkin siihen saakka tuntemattomaan
maahan, missä hänen luullaan menettäneen henkensä. Ja sen vuoksi
tunsikin Matthew Palkeney, koska hän oli viimeinen suvustaan,
itsensä vanhoilla päivillään hyvin yksinäiseksi. Ja eräänä päivänä
saattoi hänen sairautensa hänet vuoteenomaksi, ja muutamien
tuntien kuluttua Sperrigoe, lääkäri, taloudenhoitaja ja
sairaanhoitajatar, jotka olivat kokoontuneet hänen kuolinvuoteensa
ääreen, hämmentyivät ja hämmästyivät melkoisesti kuullessaan
vanhuksen toistelevan eräitä sanoja. Ne olivat ainoat hänen
mumisemansa sanat sairautensa aikana, ja hän toisteli niitä
toistelemistaan ennen kuolemaansa. Ne kuuluivat:

"Kuparilipas — eräs Palkeney, eräs Palkeney — kuparilipas!"

Hän keskeytti pannen arvoa kertomuksensa dramaattiselle


vaikutukselle ja katsoi meihin. Madrasiaa värisytti hieman.

"Kaameaa!" mumisi hän.

"Niin juuri", myönsi Murthwaite. "No niin, kukaan ei ymmärtänyt


vanhuksen tarkoitusta, ja oli aivan hyödytöntä koettaakaan taivuttaa
häntä selittämään. Mutta hänen kuoltuaan vanha taloudenhoitaja
vaivattuaan aivojaan niin paljon kuin suinkin muisti, että kirjaston
muutamassa nurkassa sijaitsevassa kaapissa oli eräs pieni taottu
kuparilipas, jota hän oli nähnyt Matthew Palkeneyn kiilloittavan omin
käsin viime vuosina. Hän meni Sperrigoen kanssa hakemaan sitä,
mutta se oli hävinnyt sieltä. Sperrigoe antoi tarkastaa rakennuksen
perin pohjin ylhäältä alas asti löytämättä sitä sittenkään. Kuparilipas
oli varastettu ja tuossa se nyt on Parslewen tarjoilupöydällä Pohjois-
Humberlandissa. Sitä ei voida kieltää, ei ollenkaan!"

Hän keskeytti taasen ja me vaikenimme, kunnes hän suvaitsi


jälleen jatkaa:

"Kuinka se on tullut tänne, tahi sanokaamme pikemminkin, kuinka


Sperrigoe sai selville sen, että se on täällä? Herra Craye on juuri
kertonut minulle toisen puolen siitä, ja minä voin kertoa toisen. Kun
Sperrigoe sai selville, että kuparilipas epäilemättä oli varastettu, pani
hän toimeen tarkan tutkimuksen koko kirjastossa, jolloin löytyi
painettu luettelo kaikista kirjoista. Nyt hän huomasi, että useita
vanhoja ja harvinaisia teoksia oli kadonnut kuparilippaan mukana.
Silloin hän ilmoitti sanomalehdissä. Tiedätte lopun. Parslewe oli
vienyt kuparilippaan Bickerdalelle, Bickerdale oli huomannut
Sperrigoen ilmoituksen ja niin edespäin. Ja nyt, kun Pawley
Sperrigoen valtuuttamana ja sitten Sperrigoe itse saapuvat tänne
kysymään suoraan, kuinka hän on saanut kuparilippaan haltuunsa,
matkustaa hän pois. Mutta miksi?"

"Koska satun tuntemaan hänet", sanoi Madrasia äkkiä, "voin


vastata kysymykseenne. Omista pätevistä ja kunniallisista syistään."

"Ja hänen ystävänään ja neuvonantajanaan", huomautti


Murthwaite, "voin sanoa amenen siihen. Mutta miksi hän ei antanut
minkäänlaista selitystä?"

Nyt oli minun vuoroni sekautua asiaan.


"Herra Murthwaite", sanoin, "ei Pawley eikä herra Charles
Sperrigoekaan pyytäneet minkäänlaista selitystä. Sperrigoe ei tietysti
tavannut herra Parsleweä, ja Pawley tuli tänne vain vakoilemaan —"

"Niin, niin", keskeytti hän. "Tarkoitan todellisuudessa vain sitä, että


miksi herra Parslewe ei antanut teille minkäänlaista selitystä?"

"Minulleko?" huudahdin. "Miksi juuri minulle?"

"Koska te olitte ainoa henkilö, joka tiesitte — sanoisimmeko asian


välittömät vaiheet. Hän luottaa teihin epäilemättä, herra Craye,
vaikka olettekin tunteneet toisenne vasta muutamia päiviä. Miksi hän
ei selittänyt teille lyhyesti tätä näennäistä salaisuutta öisen
poislivahtamisen sijaan? Miksi?"

"Huomautinhan jo", huudahti Madrasia, "että hän on tehnyt sen


omista pätevistä syistään."

Murthwaite rummutti sormillaan pöytää katsoen meihin tarkasti.

"Ettekö nyt ymmärrä?" sanoi hän äkkiä. "Ettekö nyt voi käsittää
sitä, millaisen epäluulon alaiseksi hän on saattanut itsensä, koska
herra Charles Sperrigoe ei tunne häntä?"

"En ole niinkään varma siitä", sanoin yhtä nopeasti. "Olen joka
tapauksessa aivan varma, että Parslewe tuntee tahi on ainakin
tuntenut Sperrigoen kerran maailmassa. Teen tämän varman
päätelmäni eräästä huomautuksesta, jonka hän teki kertoessani
hänelle Sperrigoesta."

"Mitä?" huudahti Murthwaite. "Mistä huomautuksesta?"


Kerroin sen hänelle. Hän nousi äkkiä tuoliltaan kuin jotakin olisi
pälkähtänyt hänen päähänsä ja käveli sitten pari minuuttia
edestakaisin huoneessa miettien. Sitten hän tuli jälleen takaisin
pöydän luo, istuutui paikoilleen ja kääntyi meidän molempien
puoleen viitaten noihin pariin sähkösanomaan, jotka vieläkin olivat
siinä, mihin hän oli ne laskenut kädestään.

"Ruvetaan nyt puhumaan asiallisesti", hän sanoi. "Otaksun teidän


molempien aikovan tavata Parslewen Newcastlessa huomenaamulla
näiden sähkösanomain johdosta?"

"Varmasti!" vastasi Madrasia. "Ja aiomme ottaa kuparilippaan


mukaamme."

"Oikein", jatkoi hän. "Sitten haluan teidän suorittavan kolme asiaa.


Ensiksikin teidän pitää kertoa Parslewelle kaikki, mitä olen kertonut
teille tästä Palkeneyn jutusta. Toiseksi, sanokaa hänelle, että minä
omalla vastuullani hänen ystävänään ja asianajajanaan olen antanut
herra Charles Sperrigoelle sellaisen lupauksen — oikeastaan takuun
— että Parslewe niin pian kuin suinkin antaa hänelle täydellisen
selostuksen siitä, kuinka lipas ja kirjat ovat joutuneet hänen
haltuunsa, niin että niiden vaellus Palkeneyn kartanosta
Kelpieshawiin saadaan täydellisesti selville, koska tietenkin on aivan
käsittämätöntä, että herra Parslewe olisi saanut ne haltuunsa jollakin
epärehellisellä tavalla. Kolmanneksi olen taivuttanut herra Charlesin
matkustamaan kotiinsa, missä hän odottaa herra Parslewen
lähettämiä tietoja."

"Mutta onkohan hän matkustanut?" sanoi Madrasia.

"Hän matkusti etelään ensimmäisessä junassa keskusteltuaan


kanssani", vastasi Murthwaite.
"Saatettuaan Woolerin poliisikomissaarin siihen uskoon, että
holhoojani on ehkä varas, vai mitä?" vihjaisi Madrasia.

"Ei mitään sellaista", Murthwaite vastasi. "No, no, malttakaahan


nyt, hyvä nuori neiti, asiat eivät ole lainkaan siten. Sperrigoe teki
siellä vain muutamia varovaisia kysymyksiä saadakseen tietää,
millainen Parslewen asema on naapuristossa. Poliisi ei tietenkään
aavista mitään."

Nyt seurasi lyhyt vaitiolo, jonka Madrasia vihdoin rikkoi.

"Viemme tietysti holhoojalleni teidän viestinne. Jokaisen sanan.


Mutta, herra Murthwaite, eikö teillä ole minkäänlaista vihiäkään siitä,
mitä tämä kaikki tarkoittaa? Kaikki tämä hälinä, salaperäisyys ja
maakunnan halki matkusteleminen yhden ainoan kuparilippaan jälkiä
seuratessa?"

Murthwaite nauroi ja kääntyen tarjoilupöytään päin otti lippaan


käteensä.

"Minulla on yhtä vähän keinoja salaisuuden ratkaisemiseksi kuin


teilläkin", hän sanoi. "Tämä esine on varmasti harvinaisuus jo
muutenkin. Se on hienoa vanhaa taottua kuparia, kaunista tekoa ja
kauniisti kaiverrettu. Mutta sitä en ymmärrä, miksi se on aiheuttanut
sellaisen hälinän, kuten te sanoitte. Kuitenkin, kun kuoleva mies
mumisee sellaista, mitä vanha Matthew Palkeneykin, niin haluaa
hänen laillinen neuvonantajansa tietenkin saada jotakin selvyyttä
asiaan. Mielipiteeni on, ettei tässä ole oikeastaan kysymys
kuparilippaasta, vaan siitä, mitä siinä mahdollisesti on ollut. Ei
lippaasta, sen sisällöstä vain, ymmärrätte kai sen?"
"Te luulette siis, että siinä on säilytetty jotakin Palkeneyn
kartanossa?" vihjaisin.

"Ehkä. Sitä minä juuri ajattelen."

"Ja otaksutte alkuperäisen varkaan anastaneen sen huolimatta sen


laadusta?"

"Aivan niin. Lipas on voinut kulkea monien käsien kautta ennen


joutumistaan Parslewen haltuun. Parslewe löysi epäilemättä tämän
kapineen jostakin harvinaisten esineiden kaupasta ja kirjat myös."

"Voivatko Palkeneyn kartanon asukkaat ollenkaan aavistaa, kuinka


varkaus on tapahtunut?" kysyin.

"Eivät. Sperrigoe ainakin väitti niin. Mutta Palkeneyn kartano on


ymmärtääkseni jonkinlainen näyttelypaikka; minä tarkoitan, että
siellä on sellaisia huoneita, joita näytetään yleisölle, ja niihin kuuluu
kirjastokin. Shillingin suuruinen sisäänpääsymaksu kannetaan
muutamina aamuina viikossa ja tulot luovutetaan paikallisiin
armeliaisuustarkoituksiin. Ja Sperrigoe ajattelee tietysti, että joku
vieras varasti tämän lippaan ja kirjat juuri vähää ennen vanhan
Matthew Palkeneyn kuolemaa. Niin pitkälle olemme päässeet, eikä
tässä enää kaivata muuta kuin muutamia sanoja Parsleweltä."

Hän sanoi sitten lähtevänsä, ja hetkisen kuluttua laskeuduimme


kaikki portaita alas pihalle. Vanha Edie toi hevosen tallista ja ottaen
suitset käteensä Murthwaite kääntyi Madrasian puoleen.

"Koettakaa nyt taivuttaa herra Parslewe palaamaan heti takaisin


tänne ja kertokaa sitten minulle kaikki, että voisin kirjoittaa
Sperrigoelle salaisuuden ratkaisun", hän sanoi. "Kertokaa hänelle
kaikki puheeni ja pyytäkää häntä palaamaan heti takaisin."

Mutta Madrasia alkoi käydä hieman kapinalliseksi.

"Kerromme kyllä hänelle kaiken Sperrigoen käynnistä ja Weechin


vierailun myös", hän vastasi. "Mutta herra Murthwaite, jätätte
kokonaan huomioon ottamatta erään asian, niin asianajaja kuin
olettekin."

"Minkä sitten?" kysyi Murthwaite nauraen iloisesti.

"Sen, ettei holhoojani milloinkaan olisi matkustanut pois, ei ikinä


kutsunut sähköteitse minua ja herra Crayea luokseen eikä kuunaan
pyytänyt, että kuparilipas tuotaisiin hänelle, ellei hänellä olisi siihen
hyvin pätevät syyt. Luuletteko hänen kujeilevan? Lorua! Koko asia on
paljon vakavampi."

Murthwaite siirsi katseensa tytöstä minuun.

"Onko teidänkin mielipiteenne sama, herra Craye?" kysyi hän.

"Kyllä", vastasin. "Ehdottomasti!"

Hän sanoi meille hyvästit ja hyppäsi satulaan kumartuen sitten


sanomaan viimeiset sanansa.

"Ei mikään asia elämässäni ole milloinkaan kiinnittänyt mieltäni


näin.
Mutta kai tällekin on olemassa ratkaisu."

Sitten hän ratsasti nummen poikki ja hävisi näkyvistämme.


Seuraavana aamuna Madrasia ja minä matkustimme Newcastleen,
hän kantoi kuparilipasta, joka oli kääritty sievään kääryyn ja
sinetöity. Junamme saapui sinne juuri silloin, kun meidän oli määrätä
tavata Parslewe. Mutta emme nähneet häntä asemalla. Seisoimme
tuijottaen ympärillemme, kunnes muudan hotellin vahtimestarin
virkapukuun pukeutunut mies lähestyi meitä, katseli meitä tarkasti ja
pysähtyi viereeni.

"Pyydän anteeksi, herra, mutta oletteko herra Craye? Juuri niin,


herra, minä tuon teille herra Parslewen terveiset, että te ja tämä
nuori neiti tulisitte hänen luokseen hotelliin syömään välipalaa. Tätä
tietä, olkaa hyvät."
VIII

MINUUTTI JÄLKEEN PUOLENYÖN

Seurasimme Parslewen lähettiä laiturin poikki hotelliin


vastustelematta ja ääneti, koska olimme mukautuneet silloin, kuten
Madrasia jälkeenpäin huomautti, kaikkeen, mitä Parslewe tulisi
tekemään tahi käskemään. Mutta luullakseni nälälläkin oli osansa
nöyryydessämme; olimme syöneet aamiaisemme varhain saamatta
sitten palaakaan suuhumme, ja ainakin mitä minuun tuli, ei hotelli
eikä sen mainio ruoka, johon jo olin tutustunut, herättäneet minussa
minkäänlaisia vastenmielisiä tunteita. Saapuessamme sinne käännyin
vaistomaisesti kahvioon päin odottaen jo ennakolta enemmän sen
suomaa nautintoa kuin herra Parslewen kohtaamista. Mutta
oppaamme vei meidät sen sivu; hän ohjasi meidät yläkertaan ja
sitten pitkin käytäviä ja välikköjä, kunnes vihdoin avasi erään oven.
Siitä päästiin yksityiseen arkihuoneeseen, katettu ruokapöytä odotti
meitä ja takkamatolla lämmitellen valkean ääressä seisoi Parslewe
kasvot synkkinä, ja hymy oli kyynillisempi kuin milloinkaan ennen.

Hän tervehti meitä yhtä kylmästi ja tyynesti kuin olisimme tulleet


hänen omaan arkihuoneeseensa Kelpieshawissa syömään aamiaista.
Itse asiassa hän teki tuskin muuta kuin soi meille huolettoman
tervehdyksen, koska hänen päähuomionsa näytti keskittyvän
ovenvartijaan ennen kuin mies pääsi poistumaan.

"Käskekää tarjoilijaa tuomaan ruoat sisään, niin olette kelpo mies.


No niin", jatkoi hän katsellen meitä miettiväisesti miehen poistuessa,
"olette luullakseni nälissänne?"

"Kovasti", sanoin minä.

"Aivan nääntymäisillämme", selitti Madrasia.

Parslewe katseli häntä arvostelevasti, hieroi leukaansa ja viittasi


sitten sivupöytään päin.

"Riisu päällysvaatteesi ja heitä ne tuonne, kultaseni", hän sanoi.


"Voit viedä ne sitten jälkeenpäin huoneeseesi."

Madrasia kääntyi hänen puoleensa.

"Huoneeseeniko?" huudahti hän.

"Numero 186 on varattu sinulle", vastasi Parslewe tyynesti. "Ja te,


Craye, saatte tyytyä 95:teen, joka on minun huoneeni vieressä.
Älkää nyt unohtako numeroitanne, mutta jos niin kävisikin, saatte ne
kyllä selville konttorista. Ne on tilattu teidän omilla nimillänne."

"Tarkoitatko, että meidän on viivyttävä yökin täällä?" kysyi


Madrasia.

"Kyllä", vastasi Parslewe lyhimmällä tavallaan. "Ehkä parikin."

"En tiennyt matkustaessani tänne valmistautua viettämään täällä


ainoatakaan yötä", sanoi Madrasia. "En ottanut edes hammasharjaa
mukaani."
"Osta sitten", vastasi Parslewe. "Täällä on hyvinvarustettuja
kauppoja, kultaseni."

Madrasia tuijotti häneen tiukemmin kuin milloinkaan ennen.

"Tapasi komennella toisia henkilöitä alkaa käydä hyvin erikoiseksi,


Jimmie!" huudahti hän vihdoin. "Mistä kaikki nämä vaatimukset
johtuvatkaan?"

"Hädästä, koska paholainen ahdistaa", vastasi Parslewe


kyynillisesti nauraen.

"Oletko sinä tuo paholainen?" kysyi Madrasia.

"En tiedä oikein, mikä olen, kultaseni", vastasi hän käyden jälleen
lempeämmäksi, "mutta toivon saavani sen selville piakkoin. Ja sitä
odottaessamme eläkäämme mukavasti, koska tuolla tuodaan jo
meille ruokaa ja juomaa."

Pari tarjoilijaa toi huoneeseen kuumia ruokia, ja istuuduimme


pöydän ääreen. En tiedä, oliko Parslewe otaksunut meidän olevan
tavattomasti nälissämme, mutta hän oli varmasti nähnyt paljon
vaivaa tilatessaan tällaisen herkullisen aterian ja sitä paitsi hän
osoitti omaavansa hyvän ja arvostelevan maun samppanjaan
nähden. Ja tarjoilijain oli viivyttävä huoneessa koko aika meidän
syödessämme, missä isäntämme mielestäni menetteli hyvin ovelasti,
koska Madrasia muuten olisi heti alkanut puhua aiheesta, joka oli
ylinnä ajatuksissamme. Hän puheli kyllä itse hyvin vapaasti, mutta
koko ajan vain eräästä näytelmästä, jota hän oli ollut katsomassa
Kuninkaallisessa Teatterissa edellisenä iltana ja johon hän oli
äärettömästi ihastunut.
"Mutta saat nähdä sen itse tänä iltana", lopetti hän. "Olen tilannut
pari paikkaa, ja Craye saa viedä sinut sinne."

"Entä sinä?" kysyi Madrasia. "Eikö sitä kannattaisi katsella parikin


kertaa peräkkäin?"

"Minulla on muita hommia", vastasi Parslewe. "Olen kaupungilla


teidän palatessanne, ja mehän voimme verrata huomioitamme
aamulla."

Näin, että Madrasia olisi hyvin mielellään kysynyt häneltä hänen


tehtävänsä laatua, mutta tarjoilijat olivat vielä huoneessa. Vasta
sitten kun he olivat tarjonneet meille kahvia ja poistuneet lopullisesti,
kohdisti Parslewe huomiomme siihen, mikä meistä molemmista
tuntui todellakin tärkeältä. Ojennettuaan minulle sikarin ja
sytytettyään itsekin sellaisen hän käänsi tuolinsa takkaan päin, siirtyi
mukavaan asentoon laskien toisen kyynärpäänsä pöydälle ja katsahti
meihin olkansa yli. "Kas niin!" hän sanoi. "Mitä siellä kotona on
tapahtunut minun poissaollessani? Koska ette molemmat voi puhua
samalla kertaa, päättäkää keskenänne, kumpi teistä saa aloittaa.
Mutta ensiksikin, missä on lipas?"

Koska aamu oli ollut kylmä, oli Madrasia pukeutunut turkiksiin, ja


niiden joukossa oli suuri käsipuuhka, jonka sisässä hän oli kantanut
lipasta. Hän nousi, haki sen esille piilopaikasta, laski sen Parslewen
viereen pöydälle ja viittasi sitten minuun sormellaan.

"Kertokoon hän. Korjaan, jos hän erehtyy."

"Aloittakaa siis, Craye", käski Parslewe. "Kertokaa perusteellisesti!"


Kerroin hänelle kaiken, mitä oli tapahtunut Kelpieshawissa hänen
oman salaperäisen poistumisensa jälkeen, ja katselin puhuessani
tarkkaavaisesti häntä. Hän kuunteli vaiti ja kylmästi, keskeyttäen
minut vain kerran pyytääkseen tarkempaa kuvausta herra Augustus
Weechistä. Hän näytti vaipuvan syviin ajatuksiin kuultuaan sen,
mutta salli minun kuitenkin jatkaa loppuun sen enempää
kyselemättä. Hän kuunteli Murthwaiten viestiäkin yhtä tyynesti kuin
kaikkea muutakin. Ehdottomassa tutkimattomuudessaan Parslewe
olisi tällä erikoisella tuulella ollessaan voinut vetää vertoja
sfinksillekin.

"Ja siinä kaikki", lopetin. "Koko juttu."

"Niin, kaikki", toisti Madrasia, "paitsi se, minkä nyt toistan tarkasti
Murthwaiten sanoilla. Sinun on palattava Wooleriin, puhuteltava
häntä
ja kerrottava hänelle kaikki, että hän voisi täyttää herra Charles
Sperrigoelle antamansa lupauksen. Ja parasta kai se onkin."

Parslewen ohuet huulet jännittyivät tuoksi suoraksi jäykäksi


viiruksi, jonka olin jo oppinut tuntemaan yhtä hyvin kuin oman
kuvani kuvastimessa. Kun hän antoi niiden höltyä, tapahtui se vain
siksi, että hän tahtoi päästää kuuluville ivallisen naurunsa, joka
päättyi hymyyn, kuten tavallisestikin hänen kääntyessään
holhokkinsa puoleen, kuten nytkin.

"Vai olisi se parasta sinun mielestäsi, kultaseni", hän sanoi


lempeästi. "Mutta sepä ei olekaan. En aio lainkaan matkustaa
takaisin Wooleriin, ennen kuin minua huvittaa. En aio ollenkaan
tyydyttää Charles Sperrigoen enkä Jackie Murthwaiten
mukavuudenhalua, ennen kuin minua huvittaa. Vannon tietäväni
omat hommani yhtä hyvin kuin joku toinenkin ja aion panna ne
täytäntöönkin, kuten minua huvittaa. Ja jos haluatte taivuttaa minut
puhumaan selvää kieltä, niin nyt sitä kuulitte."

"Ja kaikki tuo merkitsee, että sinä tiedät paljon enemmän asiasta,
kuin olet meille ilmaissut!" huudahti Madrasia.

Kuultuaan tämän häneltä pääsi jälleen ivallinen naurahdus.

"En tiedä vielä ilmaisseeni teille mitään erityistä, kultaseni", vastasi


hän. "Enkä aiokaan tehdä sitä, ennen kuin —"

"Ennen kuin sinua huvittaa!" sanoi Madrasia. "Aivan niin! Vielä


enemmän salaperäisyyttä! Todellakin, Jimmie, ollaksesi
kunnioitettava vanha herrasmies —"

Parslewe nauroi jälleen kohottaen päätään kuin hänestä olisi ollut


hauskaa kuulla moitteita, nousi sitten tuoliltaan ja seisoen
takkamatolla kädet taskuissaan katsoi vuorotellen meihin
kumpaankin, kuin häntä olisi huvittanut meidän ihmettelymme. Äkkiä
hän veti toisen kätensä esille, ja se oli täynnä rahaa. Noina aikoina
oli paljon kultaa liikkeellä, hyvin paljon, ja Parslewen koura oli sitä
täynnä. Hän ojensi rahat Madrasialle.

"Mene ostamaan itsellesi hammasharja", hän sanoi. "Sinähän


tunnet kaupungin ja voit siis lähteä hieman ostoksille. Parasta on,
että hankit kaikkea sellaista, mitä luulet tarvitsevasi, sillä
muistaakseni puhuin jotakin parista yöstä. Mene nyt huvittelemaan,
kultaseni, äläkä välitä kuparilippaasta. Siihen ei liity minkäänlaisia
salaisuuksia, ei ainakaan minun tietääkseni." Hän ojensi rahat tytölle,
seisoi hymyillen vieressä hänen pukiessaan turkiksia ylleen ja kääntyi
sitten nauraen minun puoleeni hänen mentyään.
"Uskokaa vain, Craye, että salaisuus muodostuu vaikka miksi
naisen käsissä", hän sanoi. "Ellei sellaista ole olemassa, keksii hän
jonkin."

"Eikö tässä asiassa sitten ole jotakin salaperäistä?" kysyin.


"Minusta näyttää aivan siltä kuin siinä olisi paljonkin. Mutta
nähtävästi ei teille, koska olette jo selvillä asioista, herra Parslewe."

"Niin, ehkäpä. Luulen näkeväni asian loiselta kannalta. Voin


kuitenkin ymmärtää, että se, mikä on minusta aivan selvää, ehkä ei
olekaan niin selvää toisille henkilöille, ja minä aionkin nyt uskoa teille
muutamia seikkoja. Tulkaa alakertaan tupakkahuoneeseen, niin
annamme avata tämän huoneen ikkunat, koska ilma täällä on niin
ummehtunutta."

Hän soitti ja antoi muutamia määräyksiä huoneen tuulettamisesta


ja kevyestä illallisesta, jonka piti olla valmiiksi katettuna siellä kello
yhdentoista ajaksi illalla (valmiiksi meille palatessamme teatterista,
sanoi hän syrjässä minulle) ja opasti minut sitten tupakkahuoneen
rauhalliseen nurkkaukseen.

Sytytettyään siellä ensin toisen sikarin hän alkoi purkaa lipasta


niistä sievistä kääreistä, joissa Madrasia oli tuonut sen mukanaan
Kelpieshawista. Hän laski sen eteemme pienelle pöydälle, ja
molemmat tuijotimme siihen. Hän erittäinkin tuijotti siihen niin
tiukasti, että aloin luulla kapineen paljaan muodon hypnotisoineen
hänet. Äkkiä hän hätkähti ja alkoi kaivella liivinsä taskuja.

"Niin!" mutisi hän enemmän itsekseen kuin minulle. "En ihmettelisi


ollenkaan, vaikka asia olisikin niin."
Sanottuaan sen hän otti liivinsä taskusta ohuen norsunluisen
kokoontaitettavan mitan ja avattuaan lippaan mittasi sen korkeuden
sisäpuolelta. Sitten hän mittasi saman ulkopuolelta ja kääntyi
puoleeni vaarallisine, miellyttävine hymyineen.

"Hemmetti sentään!" hän huudahti. "Craye, tässä lippaassa on


kaksi pohjaa. Olen epäillyt sitä viime puolen tunnin kuluessa, ja
kaiken olevaisen nimessä, se on kuin onkin totta!"

Minäkin aloin kiihottua ja tuijotin nyt lippaaseen yhtä tiukasti kuin


hänkin.

"Saitteko sen selville mitoista?" kysyin.

"Kyllä. Sisäisen ja ulkonaisen korkeuden välillä on


neljännestuuman ero", vastasi hän. "Se merkitsee, että siellä on
hyvin matala ontelo, mutta kuitenkin tarpeeksi suuri piilottamaan —
mitä?"

"Ei mitään erityistä, luullakseni."

"Eikö? Mutta minä olen kuullut pieneen kompassiinkin sopivan


hyvin tärkeitä ja kohtalokkaita esineitä", huomautti hän. "Siinä on
nyt kaikissa tapauksissa sellainen, koska emme voi väittää
mittasuhteita vääriksi. Lippaassa on ontelo! Ja se voidaan
varmaankin avata jollakin tempulla täältä pohjasta, luultavasti
vääntämällä noita jalkoja."

Hän viittasi niihin neljään pyöreään nuppiin, joilla lipas lepäsi,


yrittämättä kuitenkaan koskea niihin, koska hänen ajatuksensa
näyttivät suuntautuneen muualle. Ja mietittyään hetkisen hän
kääntyi luottavaisesti puoleeni.
"Lupasin kertoa teille jotakin", sanoi hän. "Te olette luotettava
mies, Craye, ja minä osoitinkin sen teille jättämällä tytön teidän
haltuunne. Hänkin pitää teistä, ja luulen teidän molempien nuorten
rakastuvan toisiinne, ellette jo olekin, ja jos te olette, niin hyvä
niinkin, poikaseni. Te voitatte vielä itsellenne kuuluisan nimen
taiteellanne, mutta viis siitä, minä kerron nyt teille hieman tästä
lippaasta. En kuitenkaan ilmaise vielä sitä, kuinka olen saanut sen
haltuuni, koska se olisi liian aikaista. Mutta saadessani sen se oli
lukossa eikä minulla ollut avainta siihen enkä minä milloinkaan
vaivautunut hakemaan enkä teettämään siihen sellaista. Kun se
kerran hieman vahingoittui, toin sen Bickerdalelle tänne kaupunkiin
ja pyysin häntä korjaamaan sen. Hän epäröi hieman ottaessaan sen
vastaan, mutta sanoi sentään tietävänsä miehen, joka kyllä osaisi
korjata sen, minkä vuoksi jätin sen hänelle ja käskin samalla
aukaista sen. Ja nyt, Craye, ajattelen, että silloin kun lipas oli
Bickerdalen tahi tuon toisen miehen käsissä, vietiin jotakin tuosta
lippaasta, jotakin sellaista, jota en ollut aavistanutkaan siellä olevan.
Se vietiin luultavasti silloin, ellei —"

Hän keskeytti irvistäen kummallisen miettiväisesti.

"Ellei, mitä?" kysyin minä.

Hän nojautui lähemmäksi olkapäätäni ja hiljensi ääntään, vaikka


läheisyydessämme ei ollutkaan ketään.

"Ellei tuo Weech ottanut sitä sieltä eilen Kelpieshawissa", vastasi


hän. "Weech, Augustus. Millainen nimi!"

"Weechkö?" huudahdin minä. "Hänkö? Mahdotonta!"


"Miksi se olisi ollut niin mahdotonta, hyvä mies? Siinä ei ole mitään
mahdotonta. Tehän kerroitte minulle juuri äsken tuolla yläkerrassa
selostaessanne tapahtumia, että menitte Madrasian kanssa
kirjastooni verrataksenne Timesin ilmoituksessa mainittujen kirjojen
nimiä muutamien erityisten hallussani olevien kirjojen nimiin ja
jätitte herra Augustus Weechin yksikseen huoneeseen, missä
kuparilipas oli aivan hänen edessään. Tietysti —"

"Taivas varjelkoon!" huudahdin. "En tullut sitä lainkaan


ajatelleeksi!"

"Epäilemättä ette", hän huomautti kylmästi. "Mutta minäpä


ajattelin. Siirrytään nyt erääseen toiseen seikkaan, joka kuitenkin
liittyy pääasiaan. Minulla on sellaisia hommia tänä iltana, jotka
toivoakseni ilmaisevat minulle, onko lippaassa ollut jotakin, ja minä
haluan, että tekisitte minulle pari kolme palvelusta pääasiallisesti
siten, että pidätte huolta Madrasiasta. Ensiksikin, syömme varhaisen
päivällisen. Sitten voitte mennä hänen kanssaan teatteriin — tässä
ovat liput, annan ne nyt muistaessani teille. Kun tulette takaisin, on
teille katettu kevyt illallinen yksityiseen arkihuoneeseeni. Ennen kuin
menette, ilmoitan Madrasialle, että mahdollisesti viivyn hyvin
myöhäiseen kaupungilla, minkä vuoksi hänen on illallisen jälkeen
mentävä nukkumaan. Nyt seuraa eräs tehtävä teillekin. Haluan, että
odotatte tuossa arkihuoneessa kello kahteentoista saakka yöllä. Ellen
minä saavu sinne täsmälleen silloin" — tässä hän keskeytti ottaen
taskustaan suljetun kirjekuoren ja ojentaen sen minulle — "pukekaa
päällystakki yllenne, viekää itse tämä poliisiasemalle — se on tässä
aivan lähellä — pyytäkää, että saisitte puhutella komissaaria, ja
antakaa tämä hänelle. Oletteko ymmärtänyt?"
"Jokaisen sanan", vastasin minä. "Mutta miksi kääntyä poliisin
puoleen?
Luuletteko ehkä joutuvanne johonkin vaaraan?"

"En niin paljon vaaraankaan kuin vaikeuksiin, vaikka en tahdokaan


kieltää, että voin joutua vaaraankin", vastasi hän. "Mutta seuratkaa
ohjeitani. Siellä on joku komissaari öisinkin. Hän tuntee kyllä nimeni
luettuaan kirjeeni, koska minä olen piirikunnan viranomainen. Jos
hän tekee teille muutamia kysymyksiä, vastatkaa niihin. Ja jos teitä
haluttaa, lähtekää hänen mukaansa, jos hän lähtee itse tahi lähettää
jonkun puolestaan. Oletteko nyt selvillä, mitä teidän on tehtävä
keskiyöllä?"

"Olen täydellisesti", vastasin minä työntäen suljetun kuoren


taskuuni. "Ja minä lupaan toimittaa sen. Mutta toivoakseni ette
joudu henkilökohtaiseen vaaraan, herra Parslewe."

Hänen huulensa jännittyivät ja hän katsoi syrjään kuin


vihjaistakseen minulle, ettei hän halunnut keskustella siitä asiasta, ja
hetkisen kuluttua hän alkoikin puhua aivan muista seikoista. Halusin
kysyä häneltä, mitä minun pitää tehdä siinä tapauksessa, että
hänelle tapahtuu jotakin, mutta en uskaltanut, koska näin aivan
selvästi hänen käsitelleen loppuun sen asian tällä haavaa, ja
ymmärsin, ettei tässä ollut muuta tehtävää kuin toteuttaa hänen
ohjeensa.

Söimme tyynesti päivällisemme alakerrassa puoli seitsemän


aikaan, ja kun Madrasia ja minä melkein tuntia myöhemmin ajoimme
teatteriin, jäi Parslewe tyynesti juttelemaan erään vanhan
herrasmiehen kanssa. Hän heilutti meille sikariaan kulkiessamme
hänen ohitseen, mutta kutsuikin sitten Madrasian luokseen.
"Tyttöseni, sinun pitää mennä heti vuoteeseen tultuasi kotiin",
sanoi hän. "Ainakin sitten kun olet syönyt hieman illallista. Älä odota
minua, sillä voin viipyä kaupungilla pikkutunneille saakka."

Sitten hän viittasi tyttöä menemään. Madrasia oli hieman


kiihkoissaan ajatellessaan kappaletta ja minä tavattoman
levottomana ja huolissani, koska niitä tilanteen mahdollisuuksia,
jotka voivat esiintyä keskiyöllä, ei ollut lainkaan hauska ajatella, ja
kuta enemmän niitä mietin sitä vähemmän niistä pidin. Oli
hyödytöntä kieltää, että Parslewe oli erikoinen, jopa kummallinenkin
mies, joka menetteli kaikessa omalla tavallaan, ja minä olin tarpeeksi
perillä maailman tavoista, vaikka olinkin vielä nuori, tietääkseni, että
sellaiset miehet joutuvat aina vaaraan. Minne hän aikoi mennä tänä
iltana ja mitä varten? Selvästi toimittamaan jotakin sellaista, missä
hän ehkä tarvitsi poliisin apua. Mutta jos nyt otaksutaan tämän avun
tulevan liian myöhään niin mitä minun silloin oli tehtävä? Huolimatta
siitä, mitä hän oli sanonut Madrasiasta ja minusta kevyellä tavallaan,
olin melkein vieras hänelle ja tytölle, ja aavistin vaikeuksia, jos
jotakin vakavaa sattuisi tapahtumaan. En pitänyt Parslewestä juuri
ollenkaan sinä iltana, koska hänen mielestäni olisi pitänyt uskoa
minulle enemmän. Mutta sille ei voitu enää mitään, ja tuossa istui
Madrasia. Ja tavattuaan holhoojansa näytti Madrasia melkoisesti
tyyntyneen; hän luotti nähtävästi suuresti Parslewen vaikutusvaltaan.

"Kertoiko hän teille mitään iltapäivällä minun ollessani ostoksilla?"


kysyi hän äkkiä ajaessamme Grey-katua pitkin. "Olen varma, että
olette keskustelleet jostakin."

"Kyllä hieman", vastasin minä. "Hän otaksuu lippaassa olevan


kaksi pohjaa, joiden välissä on kapea ontelo, missä hän luulee olleen
piilossa jotakin, joka on sieltä varastettu; ja ystävämme Weech on
mahdollisesti syyllinen."

"Weechkö?" hän huudahti. "Milloin hän olisi voinut tehdä sen?"

"Kun me mennessämme kirjastoon jätimme hänet yksikseen


katselemaan lipasta. Sellainen otaksuma on luonnollisesti
mahdollinen, jos Weech tunsi salaisuuden."

Tämä näytti antavan Madrasialle uusia aatteita.

"Ihmettelenpä todellakin", sanoi hän mumisten. "Ja senkö vuoksi


hän on tullut tänne Newcastleen, että hän saisi siitä selvän?"

"Jotakin sinnepäin", myönsin minä. "Luulen ainakin niin. Mutta


tehän tiedätte paremmin kuin minä, millainen hän on."

Hän istui hetkisen vaiti — oikeastaan aina teatterin edustalle


saakka.

"Jimmien suhteen voimme olla varmat ainakin yhdestä seikasta",


hän huomautti vakuuttavasti, "nimittäin siitä, ettei kukaan voi voittaa
häntä. Antakaa hänen sen vuoksi selvittää rauhassa asiat."

Minä en ilmaissut, ettei minulla ollut mitään valitsemisen varaa.


Katselimme kappaletta, jota Parslewe oli ylistänyt niin suuresti,
palasimme sitten takaisin hotelliin ja söimme yhteisen illallisen,
minkä jälkeen Madrasia meni huoneeseensa. Kello oli silloin
kaksikymmentä minuuttia vaille kaksitoista ja minä istuin paikoillani
kaikki nuo minuutit odottaen, pitäen silmällä ovea ja kuunnellen
askelia käytävästä, mutta Parsleweä ei kuulunut tulevaksi.
Ja minuuttia yli kahdentoista sieppasin päällystakkini ja lakkini ja
poistuin huoneesta.
IX

PELTISEPÄN ARKIHUONE

Hotellin suuressa lämpiössä oli vain muutamia henkilöitä, mutta


heidän joukossaan oli ensimmäinen ovenvartija, joka minun
tullessani sinne näytti juuri olevan luovuttamaisillaan virkansa hoidon
sijaiselleen yöksi. Mieleeni juolahti jotakin ja minä menin hänen
luokseen vieden hänet syrjään.

"Tunnette kai herra Parslewen?" kysyin minä.

"Herra Parslewenkö? kyllä, herra", vastasi hän.

"Oletteko nähnyt hänen menevän kaupungille tänä iltana?"

"Kyllä, herra. Herra Parslewe poistui hotellista noin yhdentoista


aikaan, vain muutamia minuutteja ennen teidän palaamistanne
nuoren neidin kanssa."

"Ette siis ole nähnyt hänen tulevan takaisin?"

"En vielä, herra. Hän ei ole käynyt hotellissa sen jälkeen."


Nyökäytin päätäni ja menin kadulle. Siis Parslewen asian
järjestäminen, millainen se sitten lienee ollutkin, oli määrätty
tapahtuvaksi vasta kello yhdentoista jälkeen, siis hyvin myöhäiseen.
Hän olisi siinä tapauksessa voinut tulla kanssamme teatteriin, mutta
ehkä hänellä oli ollut toisenlaisia tehtäviä hotellissa, kuten voidaan
olettaa. Näiden asioiden miettiminen oli kuitenkin aivan hyödytöntä,
koska minun oli vain täytettävä hänen pyyntönsä. Eikä ollut
minkäänlaista pelkuruutta minun puoleltani, että sydämestäni
inhosin sen täyttämistä. Minulla ei ollut aavistustakaan, missä päin
poliisiasema sijaitsi. Parslewe oli sanonut sen olevan jossakin
läheisyydessä, mutta en tiennyt, millä suunnalla. Olisin kyllä voinut
kysyä sitä hotellissa, mutta en halunnut hotellin palveluskunnan
saavan tietää, että aiomme turvautua poliisin apuun. Ja sehän olisi
sitä paitsi voinut joutua Madrasian tietoon ennen minun paluutani.
Kaduilla oli vielä ihmisiä, minähän voin kysyä heiltä. Ja juuri silloin
tuli eräs poliisi esille nurkan takaa, mitä minun olisi pitänyt osata
odottaakin, ja neuvoi minulle kysyttyäni tien. Parslewe oli ollut aivan
oikeassa, asema oli likellä.

Menin sisään ihmetellen, koska en milloinkaan ennen ollut käynyt


sellaisessa rakennuksessa enkä tiennyt, mitä minun piti odottaa.
Minulla oli yhtä vähän aavistusta, millaiselta poliisin pääasema
näyttää, kuin jonkin itämaisen palatsin sisustuksesta, ehkä vielä
vähemmänkin. Mutta kun tulin sinne, näytti siellä kaikki hyvin
tavalliselta. Siellä oli hyvin valaistu konttori pöytineen ja
pulpetteineen, joiden ääressä joko istui tahi seisoi muutamia poliiseja
kirjoittaen tahi tarkastellen papereita. Muudan heistä, nähdessään
minun lähestyvän tiskiä ja huomaten ehkä epäröivän nulikkamaisen
käytökseni, nousi tuoliltaan, pisti kynän korvansa taakse ja tuli
vastaan melkein isällisen huolestunut ilme punakoissa kasvoissaan.
"Saanko puhutella jotakin korkeampaa virkamiestä", kysyin.

Hän kääntyi puoleksi viitaten erääseen mieheen, jonka huolellisesti


napitetussa takissa oli nyörikoristeita ja joka istui pulpettinsa ääressä
eräässä nurkassa.

"Tuolla on komissaari, herra", hän sanoi. "Puhutelkaa häntä."

Hän kohotti tiskin saranoilla varustettua ovea ja minä menin


huoneen poikki kysymyksessä olevan miehen luo. Hän kohotti
katsettaan minun tullessani lähemmäksi ja mittaili minut nopeasti
päästä jalkoihin asti. Mieleni täytti epämääräinen kiitollisuudentunne
siitä, että olin hyvin puettu.

"Asianne?" sanoi hän.

Menin aivan hänen viereensä. Ehkä minä näytin hyvinkin


salaperäiseltä — ainakin minusta tuntui niin.

"Tehän tunnette Kelpieshawin omistajan herra James Parslewen?"


kysyin minä.

"Kyllä."

"Herra Parslewe on kaupungissa ja asuu North Eastern Station


Hotellissa. Minäkin asun siellä hänen kanssaan. Hän pyysi minua
siinä tapauksessa, että muudan edellytys mahdollisesti toteutuu —"

Hän keskeytti minut melkein huomaamattomasti hymyillen —


häntä huvitti nähtävästi täsmällinen puheeni.

"Millainen edellytys?"
"Siinä tapauksessa, ettei hän palaa hotelliin ennen puoltayötä, piti
minun tuoda teille tämä kirje häneltä", vastasin laskien kirjeen
pulpetille. "Hän ei tullut, ja sen vuoksi tulin suoraan luoksenne."

Hän otti kirjeen, aukaisi sen ja alkoi lukea. Paikaltani voin nähdä,
että kirjoitus täytti kolme sivua hotellin postipaperiarkista. Miehen
kasvot eivät hänen lukiessaan ilmaisseet mitään — eivät
hämmästystä, neuvottomuutta eivätkä kummastusta — ja hän luki
kirjeen vain kerran läpi. Sitten hän taittoi sen kokoon, pisti
pulpettiinsa ja kääntyi puoleeni.

"Oletteko herra Alvery Craye?" kysyi hän.

"Kyllä", vastasin.

"Tiedättekö, mitä tässä kirjeessä on, herra Craye?" jatkoi hän.


"Ilmaisiko herra Parslewe teille sen sisällön?"

"Ei. Mutta hän pyysi minua vastaamaan kaikkiin teidän tekemiinne


kysymyksiin ja käski minun seurata teitä, jos te kirjeen johdosta
lähtisitte jonnekin."

"Haluan tietää vain yhden seikan", huomautti hän. "Tiedättekö,


milloin herra Parslewe poistui hotellista?"

"Kyllä. Otin selon siitä. Hän oli poistunut noin yhdentoista aikaan
— muutamia minuutteja ennen. Sain sen tietää ovenvartijalta."

Hän nyökäytti päätään, lukitsi pulpettinsa, pisti avaimen


taskuunsa, nousi ja pyydettyään minua istuutumaan hetkiseksi
poistui eräästä ovesta. Parin minuutin kuluttua hän palasi takaisin
erään siviilipukuisen miehen seurassa; hän oli itse pukeutunut
mantteliin ja pannut päähänsä virkalakin. Kuiskattuaan jotakin
eräälle kersantille, joka kirjoitti ahkerasti huoneen keskellä
sijaitsevan pöydän ääressä, hän viittasi minulle ja me lähdimme
kolmisin öiselle retkellemme.

Sillä hetkellä ei minulla ollut pienintäkään aavistusta


päämäärästämme. Mielessäni oli epämääräinen tunne, hyvin hämärä
aavistus, että ehkä olimme menossa johonkin synkkään ja
vastenmieliseen kaupungin kortteliin. Olin käynyt Newcastlessa pari
kolme kertaa ennenkin ja olin silloin kävellessäni siellä todennut, että
siellä oli muutamia köyhälistönkortteleita, jotka olivat yhtä huonossa
maineessa kuin Liverpoolin ja Cardiffin samanlaiset kaupunginosat.
Mutta toverini kääntyivätkin kaupungin keskustaa kohti suunnaten
kulkunsa sen parhaiten rakennettuja osia kohti. Noilla tilavilla ja
komeilla kaduilla oli hyvin rauhallista, ja meidän askeltemme kaiku
kuulosti kamalalta hiljaisuudessa. Ei kukaan puhunut mitään, ennen
kuin olimme kävelleet jonkin matkaa, mutta sitten kääntyi komissaari
puoleeni.

"Puhuiko herra Parslewe teille jostakin mahdollisesta vaarasta,


herra
Craye, johon hän ehkä voi joutua toimittaessaan asiaansa?"

"Kerron teille tarkasti, mitä hän sanoi", vastasin. "Hän sanoi: 'Ei
niin paljon vaaraa kuin vaikeuksia, vaikka en tahdo kieltää sitäkään,
että voin ehkä joutua vaaraankin.' Niin juuri hän sanoi."

"Aivan niin", huomautti komissaari. "Kertoiko hän teille jotakin


muutakin?"

"Hän ei kertonut minulle mitään, paitsi sen, että toivoo saavansa


haltuunsa ehkä jotakin", vastasin. "Jos tunnette herra Parslewen,
tiedätte varmaankin, että hän muutamissa tilaisuuksissa, milloin se
häntä miellyttää, voi olla epämääräinen ja epäselvä."

"Minä tunnen kyllä herra Parslewen tarpeeksi hyvin", vastasi hän


veitikkamaisesti naurahtaen. "Hyvin kummallinen herrasmies,
samainen Parslewe, ja tavattoman halukas seuraamaan omaa
mieltään, kulkemaan omaa tietään ja toimimaan omalla tavallaan
kaikissa asioissa. Koko Northumberlandissa ei ole ainoatakaan hänen
virkaveljeään, joka ei tietäisi sitä, herra Craye. Te ette siis aavista
lainkaan, minne nyt olemme menossa?"

"En ollenkaan!"

"No niin, koska hän on luvannut teidän tulla mukaamme, voin sen
vallan hyvin kertoakin teille", sanoi hän nauraen jälleen. "Olemme
menossa erään Bickerdale-nimisen läkki- ja kuparisepän taloon ja
työpajaan, jotka sijaitsevat erään sivukadun varrella tässä
läheisyydessä. Sinne juuri on herra Parslewe mennyt."

Minun olisi tietysti pitänyt arvata se. Tunsin itseni hyvin tyhmäksi,
kun en ollut osannut ajatella sitä ennen. Mutta säpsähdin kuitenkin
tahtomattani.

"Te näytätte tuntevan tuon nimen", sanoi komissaari.

"Niin, minä tunnen sen", myönsin. "Olen käynyt tuossa kaupassa.


Vai sinne hän onkin mennyt."

"Sieltä pitää meidän häntä joka tapauksessa hakea", vastasi hän.


"Mutta en tiedä, löydämmekö häntä sieltä tahi jos löydämme, niin
millaisissa olosuhteissa. Noudatamme nyt kuitenkin hänen
määräyksiään, ja tässä on tuon sivukadun kulma."
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebooknice.com

You might also like