Components are the building blocks of Ink files. Documents
and page level markup are written in
.ink files. Components
and templates are written in
.ink files. In both
cases, the code is written in a superset of HTML.
The four sections that make up a ink file — imports,
script, styles and markup — are all optional and can be
used in any order.
<!-- imports go here -->
<style>
/* styles go here */
</style>
<script>
// logic goes here
</script>
<!-- HTML goes here -->
Imports
Imports are used to include additional components, templates
and stylesheets in the current component. Components can
be imported as a template or
component type.
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/prism.min.css" />
<link rel="stylesheet" type="text/css" href="/styles/layout.css" />
<link rel="import" type="template" href="@/components/html-head.ink" />
<link rel="import" type="component" href="@/components/i18n/translate.ink" name="i18n-translate" />
<style>
/* styles go here */
</style>
<script>
// logic goes here
</script>
<!-- HTML goes here -->
The rel attribute
specifies the relationship between the current document and
the linked resource.
rel="import" denotes
that the imported resource is a component or template.
The type
attribute specifies the type of the linked resource.
type="component"
imports a web component that can be used as regular markup
with attributes and children.
type="template"
imports a template partial that can be included in the current
markup. Template partials do not process attributes or children
if given.
The
href attribute specifies
the URL of the linked resource. The
name
attribute specifies the tag name of the imported component or template.
Styles
CSS styles inside a <style>
block enables the native shadow DOM and will be scoped only to that component.
Additionally styles defined outside of the component such as
global styles will not affect the component.
External stylesheets can be imported using the
<link> tag or using
@import() CSS directive.
You can use host selectors to style an element from within
a component. The :host
pseudo-class always applies styles to the root element of the
web component.
<style>
:host {
display: block;
}
</style>
You can also add conditional styles using the
:host selector function.
This can be used to style the host so long as it matches the
given selector. For example, it can be used to select for
hosts that have a given attribute or class.
<style>
:host([active]) {
background-color: #333;
color: #FFF;
}
:host(.active) {
background-color: #333;
color: #FFF;
}
</style>
Scripts
The <script> block is used
to write TypeScript logic for the component. The script block
can be used to define variables, functions, and event listeners.
Variables declared (or imported) at the top level are
'visible' from the component's markup.
<script>
const title = 'Hello World';
</script>
<h1>{title}</h1>
The <script> block can also
be used to import variables from other components to be used
in the markup.
<script>
import getTitle from './getTitle';
const title = getTitle();
</script>
<h1 title={title}>{title}</h1>
You can use @/ to prefix the
current working directory. This is useful when importing
files completely in a separate directory in your project
<script>
import getTitle from '@/data/getTitle';
const title = getTitle();
</script>
<h1 title={title}>{title}</h1>
Markup
In order to be closer to the native, Ink follows the same
standards and conventions as HTML5 web components. Ink
components are compiled to native web components that possibly
can be used in other projects any modern browser.
Tag Names
For web components it's recommended that tag names must have
at least one dash (-) in them. As such you probably want to
name your element with two distinct words like
i18n-translate. You can
use as many dashes as you want, you're not limited to one.
Some specific rules to follow in order to make a valid tag
name:
It must use all lowercase characters of the alphabet (a-z).
It must contain at least one dash (-). Ink will
auto prefix component names based on your configuration.
It must not be an already reserved tag name including
annotation-xml,
color-profile,
font-face,
font-face-src,
font-face-uri,
font-face-format,
font-face-name, and
missing-glyph.
It must not contain symbols, like =, @, $.
It can contain underscores, and numbers.
It can contain characters from different alphabets,
such as é, ð, ö, 爱.
Additionally, Ink works best with correct markup. The
following standards should be followed:
Self closing tags like
<img />,
<link />,
<meta />,
<input />
must have a slash before the closing.
When using tables, rows should be wrapped in a
<tbody> tag and cells
should be wrapped in a <tr>
tag. ie. <table><tbody><tr><td>
When using lists, items should be wrapped in a
<ul> or
<ol> tags.
ie. <ul><li>
Warning: Any markup auto corrected by browser will cause data syncing
issues with Ink.
Ink components can loosely be self closing
<i18n-translate />
or expressed as a block
<i18n-translate></i18n-translate>.
Attributes
<a title={title} {href} {...attributes}>
{title}
</a>
<i18n-translate title=title>
{detail}
</i18n-translate>
Attributes can be bound to expressions using the
{} syntax.
Expressions can be variables, functions, or any valid
JavaScript expression. By default, attributes work exactly
like their HTML counterparts.
<button type="button" disabled>Submit</button>
Traditional HTML attributes can be assigned string values or
no value evaluates as true.
<a title={title}>Click</a>
Attributes can be assigned variable names.
<a title=title>Click</a>
Variable names do not need to be wrapped in curly braces
{}.
<a {title}>Click</a>
Attributes with the same name as a variable can be assigned
by just wrapping curly braces. ie.
{title}.
You can assign any valid JavaScript expression to an attribute.
Conditionals
<if true={count > 10}>
<p>Count is greater than 10</p>
<elif true={count < 5} />
<p>Count is less than 5</p>
<else />
<p>Count is between 5 and 10</p>
</if>
Conditionals can be used to show or hide elements based on
the value of a variable.
<if true={count > 10}>
<p>Count is greater than 10</p>
</if>
The basic syntax for an if statement looks like this and can be
truesy or
falsey.
<if false={count > 10}>
<p>Count is not greater than 10</p>
</if>
You can also use the false
attribute to negate the condition.
<if true={count > 10}>
<p>Count is greater than 10</p>
<else />
<p>Count is less than or equal to 10</p>
</if>
You can use the else block to
show content when the condition is false.
<if true={count > 10}>
<p>Count is greater than 10</p>
<elif true={count < 5} />
<p>Count is less than 5</p>
</if>
You can use the elif block to
show content when the previous condition is false.
Iterations
<each key=index value=article from=articles>
<h1>#{index + 1} {article.title}</h1>
<p>{article.body}</p>
</each>
The <each> block can be used
to iterate over an array of items or objects.
The from attribute value is
required and can be an array, object or JavaScript expression
that evaluates to an array or object. Both the
key and
value attributes are optional.
The value of value, in this
case article can be used
only with in the block. This can be any valid JavaScript
variable name.
<each key={index} from={[1, 2, 3]}>
<h1>#{index} ???</h1>
</each>
The value of key, in this
case index can be used
only with in the block. This can be any valid JavaScript
variable name.
Try/Catch
<try>
<p>{mayCauseError()}</p>
<catch error={e} />
<p>Error: {e.message}</p>
</try>
The <try><catch> block can
be used to catch errors that occur in the block. The
<catch> block is required and
can be used to handle the error.
The value of error, in the
<catch> block in this case
e is an
Error object
that can only be used with in the block.