3176 lines
115 KiB
HTML
3176 lines
115 KiB
HTML
<!doctype html><html lang="en">
|
||
<head>
|
||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||
<title>Web Environment Integrity</title>
|
||
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
|
||
<style data-fill-with="stylesheet">/******************************************************************************
|
||
* Style sheet for the W3C specifications *
|
||
*
|
||
* Special classes handled by this style sheet include:
|
||
*
|
||
* Indices
|
||
* - .toc for the Table of Contents (<ol class="toc">)
|
||
* + <span class="secno"> for the section numbers
|
||
* - #toc for the Table of Contents (<nav id="toc">)
|
||
* - ul.index for Indices (<a href="#ref">term</a><span>, in § N.M</span>)
|
||
* - table.index for Index Tables (e.g. for properties or elements)
|
||
*
|
||
* Structural Markup
|
||
* - table.data for general data tables
|
||
* -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
|
||
* -> use <table class='complex data'> for extra-complex tables
|
||
* -> use <td class='long'> for paragraph-length cell content
|
||
* -> use <td class='pre'> when manual line breaks/indentation would help readability
|
||
* - dl.switch for switch statements
|
||
* - ol.algorithm for algorithms (helps to visualize nesting)
|
||
* - .figure and .caption (HTML4) and figure and figcaption (HTML5)
|
||
* -> .sidefigure for right-floated figures
|
||
* - ins/del
|
||
* -> ins/del.c### for candidate and proposed changes (amendments)
|
||
*
|
||
* Code
|
||
* - pre and code
|
||
*
|
||
* Special Sections
|
||
* - .note for informative notes (div, p, span, aside, details)
|
||
* - .example for informative examples (div, p, pre, span)
|
||
* - .issue for issues (div, p, span)
|
||
* - .advisement for loud normative statements (div, p, strong)
|
||
* - .annoying-warning for spec obsoletion notices (div, aside, details)
|
||
* - .correction for "candidate corrections" (div, aside, details, section)
|
||
* - .addition for "candidate additions" (div, aside, details, section)
|
||
* - .correction.proposed for "proposed corrections" (div, aside, details, section)
|
||
* - .addition.proposed for "proposed additions" (div, aside, details, section)
|
||
*
|
||
* Definition Boxes
|
||
* - pre.def for WebIDL definitions
|
||
* - table.def for tables that define other entities (e.g. CSS properties)
|
||
* - dl.def for definition lists that define other entitles (e.g. HTML elements)
|
||
*
|
||
* Numbering
|
||
* - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
|
||
* - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
|
||
* - ::before styled for CSS-generated issue/example/figure numbers:
|
||
* -> Documents wishing to use this only need to add
|
||
* figcaption::before,
|
||
* .caption::before { content: "Figure " counter(figure) " "; }
|
||
* .example::before { content: "Example " counter(example) " "; }
|
||
* .issue::before { content: "Issue " counter(issue) " "; }
|
||
*
|
||
* Header Stuff (ignore, just don't conflict with these classes)
|
||
* - .head for the header
|
||
* - .copyright for the copyright
|
||
*
|
||
* Outdated warning for old specs
|
||
*
|
||
* Miscellaneous
|
||
* - .overlarge for things that should be as wide as possible, even if
|
||
* that overflows the body text area. This can be used on an item or
|
||
* on its container, depending on the effect desired.
|
||
* Note that this styling basically doesn't help at all when printing,
|
||
* since A4 paper isn't much wider than the max-width here.
|
||
* It's better to design things to fit into a narrower measure if possible.
|
||
*
|
||
* - js-added ToC jump links (see fixup.js)
|
||
*
|
||
******************************************************************************/
|
||
|
||
/* color variables included separately for reliability */
|
||
|
||
/******************************************************************************/
|
||
/* Body */
|
||
/******************************************************************************/
|
||
|
||
html {
|
||
}
|
||
|
||
body {
|
||
counter-reset: example figure issue;
|
||
|
||
/* Layout */
|
||
max-width: 50em; /* limit line length to 50em for readability */
|
||
margin: 0 auto; /* center text within page */
|
||
padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
|
||
padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag */
|
||
|
||
/* Typography */
|
||
line-height: 1.5;
|
||
font-family: sans-serif;
|
||
widows: 2;
|
||
orphans: 2;
|
||
word-wrap: break-word;
|
||
overflow-wrap: break-word;
|
||
hyphens: auto;
|
||
|
||
color: black;
|
||
color: var(--text);
|
||
background: white top left fixed no-repeat;
|
||
background: var(--bg) top left fixed no-repeat;
|
||
background-size: 25px auto;
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
/* Front Matter & Navigation */
|
||
/******************************************************************************/
|
||
|
||
/** Header ********************************************************************/
|
||
|
||
div.head { margin-bottom: 1em; }
|
||
div.head hr { border-style: solid; }
|
||
|
||
div.head h1 {
|
||
font-weight: bold;
|
||
margin: 0 0 .1em;
|
||
font-size: 220%;
|
||
}
|
||
|
||
div.head h2 { margin-bottom: 1.5em;}
|
||
|
||
/** W3C Logo ******************************************************************/
|
||
|
||
.head .logo {
|
||
float: right;
|
||
margin: 0.4rem 0 0.2rem .4rem;
|
||
}
|
||
|
||
.head img[src*="logos/W3C"] {
|
||
display: block;
|
||
border: solid #1a5e9a;
|
||
border: solid var(--logo-bg);
|
||
border-width: .65rem .7rem .6rem;
|
||
border-radius: .4rem;
|
||
background: #1a5e9a;
|
||
background: var(--logo-bg);
|
||
color: white;
|
||
color: var(--logo-text);
|
||
font-weight: bold;
|
||
}
|
||
|
||
.head a:hover > img[src*="logos/W3C"],
|
||
.head a:focus > img[src*="logos/W3C"] {
|
||
opacity: .8;
|
||
}
|
||
|
||
.head a:active > img[src*="logos/W3C"] {
|
||
background: #c00;
|
||
background: var(--logo-active-bg);
|
||
border-color: #c00;
|
||
border-color: var(--logo-active-bg);
|
||
}
|
||
|
||
/* see also additional rules in Link Styling section */
|
||
|
||
/** Copyright *****************************************************************/
|
||
|
||
p.copyright,
|
||
p.copyright small { font-size: small; }
|
||
|
||
/** Back to Top / ToC Toggle **************************************************/
|
||
|
||
@media print {
|
||
#toc-nav {
|
||
display: none;
|
||
}
|
||
}
|
||
@media not print {
|
||
#toc-nav {
|
||
position: fixed;
|
||
z-index: 3;
|
||
bottom: 0; left: 0;
|
||
margin: 0;
|
||
min-width: 1.33em;
|
||
border-top-right-radius: 2rem;
|
||
box-shadow: 0 0 2px;
|
||
font-size: 1.5em;
|
||
}
|
||
#toc-nav > a {
|
||
display: block;
|
||
white-space: nowrap;
|
||
|
||
height: 1.33em;
|
||
padding: .1em 0.3em;
|
||
margin: 0;
|
||
|
||
box-shadow: 0 0 2px;
|
||
border: none;
|
||
border-top-right-radius: 1.33em;
|
||
|
||
color: #707070;
|
||
color: var(--tocnav-normal-text);
|
||
background: white;
|
||
background: var(--tocnav-normal-bg);
|
||
}
|
||
#toc-nav > a:hover,
|
||
#toc-nav > a:focus {
|
||
color: black;
|
||
color: var(--tocnav-hover-text);
|
||
background: #f8f8f8;
|
||
background: var(--tocnav-hover-bg);
|
||
}
|
||
#toc-nav > a:active {
|
||
color: #c00;
|
||
color: var(--tocnav-active-text);
|
||
background: white;
|
||
background: var(--tocnav-active-bg);
|
||
}
|
||
|
||
#toc-nav > #toc-jump {
|
||
padding-bottom: 2em;
|
||
margin-bottom: -1.9em;
|
||
}
|
||
|
||
/* statusbar gets in the way on keyboard focus; remove once browsers fix */
|
||
#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
|
||
padding-bottom: 1.5rem;
|
||
}
|
||
|
||
#toc-nav:not(:hover) > a:not(:focus) > span + span {
|
||
/* Ideally this uses :focus-within on #toc-nav */
|
||
display: none;
|
||
}
|
||
#toc-nav > a > span + span {
|
||
padding-right: 0.2em;
|
||
}
|
||
}
|
||
|
||
/** ToC Sidebar ***************************************************************/
|
||
|
||
/* Floating sidebar */
|
||
@media screen {
|
||
body.toc-sidebar #toc {
|
||
position: fixed;
|
||
top: 0; bottom: 0;
|
||
left: 0;
|
||
width: 23.5em;
|
||
max-width: 80%;
|
||
max-width: calc(100% - 2em - 26px);
|
||
overflow: auto;
|
||
padding: 0 1em;
|
||
padding-left: 42px;
|
||
padding-left: calc(1em + 26px);
|
||
color: black;
|
||
color: var(--tocsidebar-text);
|
||
background: inherit;
|
||
background-color: #f7f8f9;
|
||
background-color: var(--tocsidebar-bg);
|
||
z-index: 1;
|
||
box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
|
||
box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
|
||
}
|
||
body.toc-sidebar #toc h2 {
|
||
margin-top: .8rem;
|
||
font-variant: small-caps;
|
||
font-variant: all-small-caps;
|
||
text-transform: lowercase;
|
||
font-weight: bold;
|
||
color: gray;
|
||
color: hsla(203,20%,40%,.7);
|
||
color: var(--tocsidebar-heading-text);
|
||
}
|
||
body.toc-sidebar #toc-jump:not(:focus) {
|
||
width: 0;
|
||
height: 0;
|
||
padding: 0;
|
||
position: absolute;
|
||
overflow: hidden;
|
||
}
|
||
}
|
||
/* Hide main scroller when only the ToC is visible anyway */
|
||
@media screen and (max-width: 28em) {
|
||
body.toc-sidebar {
|
||
overflow: hidden;
|
||
}
|
||
}
|
||
|
||
/* Sidebar with its own space */
|
||
@media screen and (min-width: 78em) {
|
||
body:not(.toc-inline) #toc {
|
||
position: fixed;
|
||
top: 0; bottom: 0;
|
||
left: 0;
|
||
width: 23.5em;
|
||
overflow: auto;
|
||
padding: 0 1em;
|
||
padding-left: 42px;
|
||
padding-left: calc(1em + 26px);
|
||
color: black;
|
||
color: var(--tocsidebar-text);
|
||
background: inherit;
|
||
background-color: #f7f8f9;
|
||
background-color: var(--tocsidebar-bg);
|
||
z-index: 1;
|
||
box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
|
||
box-shadow: -.1em 0 .25em var(--tocsidebar-shadow) inset;
|
||
}
|
||
body:not(.toc-inline) #toc h2 {
|
||
margin-top: .8rem;
|
||
font-variant: small-caps;
|
||
font-variant: all-small-caps;
|
||
text-transform: lowercase;
|
||
font-weight: bold;
|
||
color: gray;
|
||
color: hsla(203,20%,40%,.7);
|
||
color: var(--tocsidebar-heading-text);
|
||
}
|
||
|
||
body:not(.toc-inline) {
|
||
padding-left: 29em;
|
||
}
|
||
/* See also Overflow section at the bottom */
|
||
|
||
body:not(.toc-inline) #toc-jump:not(:focus) {
|
||
width: 0;
|
||
height: 0;
|
||
padding: 0;
|
||
position: absolute;
|
||
overflow: hidden;
|
||
}
|
||
}
|
||
@media screen and (min-width: 90em) {
|
||
body:not(.toc-inline) {
|
||
margin: 0 4em;
|
||
}
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/* Sectioning */
|
||
/******************************************************************************/
|
||
|
||
/** Headings ******************************************************************/
|
||
|
||
h1, h2, h3, h4, h5, h6, dt {
|
||
page-break-after: avoid;
|
||
page-break-inside: avoid;
|
||
font: 100% sans-serif; /* Reset all font styling to clear out UA styles */
|
||
font-family: inherit; /* Inherit the font family. */
|
||
line-height: 1.2; /* Keep wrapped headings compact */
|
||
hyphens: manual; /* Hyphenated headings look weird */
|
||
}
|
||
|
||
h2, h3, h4, h5, h6 {
|
||
margin-top: 3rem;
|
||
}
|
||
|
||
h1, h2, h3 {
|
||
color: #005A9C;
|
||
color: var(--heading-text);
|
||
}
|
||
|
||
h1 { font-size: 170%; }
|
||
h2 { font-size: 140%; }
|
||
h3 { font-size: 120%; }
|
||
h4 { font-weight: bold; }
|
||
h5 { font-style: italic; }
|
||
h6 { font-variant: small-caps; }
|
||
dt { font-weight: bold; }
|
||
|
||
/** Subheadings ***************************************************************/
|
||
|
||
h1 + h2,
|
||
#profile-and-date {
|
||
/* #profile-and-date is a subtitle in an H2 under the H1 */
|
||
margin-top: 0;
|
||
}
|
||
h2 + h3,
|
||
h3 + h4,
|
||
h4 + h5,
|
||
h5 + h6 {
|
||
margin-top: 1.2em; /* = 1 x line-height */
|
||
}
|
||
|
||
/** Section divider ***********************************************************/
|
||
|
||
:not(.head) > :not(.head) + hr {
|
||
font-size: 1.5em;
|
||
text-align: center;
|
||
margin: 1em auto;
|
||
height: auto;
|
||
color: black;
|
||
color: var(--hr-text);
|
||
border: transparent solid 0;
|
||
background: transparent;
|
||
}
|
||
:not(.head) > hr::before {
|
||
content: "\2727\2003\2003\2727\2003\2003\2727";
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/* Paragraphs and Lists */
|
||
/******************************************************************************/
|
||
|
||
p {
|
||
margin: 1em 0;
|
||
}
|
||
|
||
dd > p:first-child,
|
||
li > p:first-child {
|
||
margin-top: 0;
|
||
}
|
||
|
||
ul, ol {
|
||
margin-left: 0;
|
||
padding-left: 2em;
|
||
}
|
||
|
||
li {
|
||
margin: 0.25em 0 0.5em;
|
||
padding: 0;
|
||
}
|
||
|
||
dl dd {
|
||
margin: 0 0 .5em 2em;
|
||
}
|
||
|
||
.head dd + dd { /* compact for header */
|
||
margin-top: -.5em;
|
||
}
|
||
|
||
/* Style for algorithms */
|
||
ol.algorithm ol:not(.algorithm),
|
||
.algorithm > ol ol:not(.algorithm) {
|
||
border-left: 0.5em solid #DEF;
|
||
border-left: 0.5em solid var(--algo-border);
|
||
}
|
||
|
||
/* Put nice boxes around each algorithm. */
|
||
[data-algorithm]:not(.heading) {
|
||
padding: .5em;
|
||
border: thin solid #ddd;
|
||
border: thin solid var(--algo-border);
|
||
border-radius: .5em;
|
||
margin: .5em calc(-0.5em - 1px);
|
||
}
|
||
[data-algorithm]:not(.heading) > :first-child {
|
||
margin-top: 0;
|
||
}
|
||
[data-algorithm]:not(.heading) > :last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
/* Style for switch/case <dl>s */
|
||
dl.switch > dd > ol.only,
|
||
dl.switch > dd > .only > ol {
|
||
margin-left: 0;
|
||
}
|
||
dl.switch > dd > ol.algorithm,
|
||
dl.switch > dd > .algorithm > ol {
|
||
margin-left: -2em;
|
||
}
|
||
dl.switch {
|
||
padding-left: 2em;
|
||
}
|
||
dl.switch > dt {
|
||
text-indent: -1.5em;
|
||
margin-top: 1em;
|
||
}
|
||
dl.switch > dt + dt {
|
||
margin-top: 0;
|
||
}
|
||
dl.switch > dt::before {
|
||
content: '\21AA';
|
||
padding: 0 0.5em 0 0;
|
||
display: inline-block;
|
||
width: 1em;
|
||
text-align: right;
|
||
line-height: 0.5em;
|
||
}
|
||
|
||
/** Terminology Markup ********************************************************/
|
||
|
||
|
||
/******************************************************************************/
|
||
/* Inline Markup */
|
||
/******************************************************************************/
|
||
|
||
/** Terminology Markup ********************************************************/
|
||
dfn { /* Defining instance */
|
||
font-weight: bolder;
|
||
}
|
||
a > i { /* Instance of term */
|
||
font-style: normal;
|
||
}
|
||
dt dfn code, code.idl {
|
||
font-size: inherit;
|
||
}
|
||
dfn var {
|
||
font-style: normal;
|
||
}
|
||
|
||
/** Change Marking ************************************************************/
|
||
|
||
del {
|
||
color: #aa0000;
|
||
color: var(--del-text);
|
||
background: transparent;
|
||
background: var(--del-bg);
|
||
text-decoration: line-through;
|
||
}
|
||
ins {
|
||
color: #006100;
|
||
color: var(--ins-text);
|
||
background: transparent;
|
||
background: var(--ins-bg);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
/* for amendments (candidate/proposed changes) */
|
||
|
||
.amendment ins, .correction ins, .addition ins,
|
||
ins[class^=c] {
|
||
text-decoration-style: dotted;
|
||
}
|
||
.amendment del, .correction del, .addition del,
|
||
del[class^=c] {
|
||
text-decoration-style: dotted;
|
||
}
|
||
.amendment.proposed ins, .correction.proposed ins, .addition.proposed ins,
|
||
ins[class^=c].proposed {
|
||
text-decoration-style: double;
|
||
}
|
||
.amendment.proposed del, .correction.proposed del, .addition.proposed del,
|
||
del[class^=c].proposed {
|
||
text-decoration-style: double;
|
||
}
|
||
|
||
/** Miscellaneous improvements to inline formatting ***************************/
|
||
|
||
sup {
|
||
vertical-align: super;
|
||
font-size: 80%
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/* Code */
|
||
/******************************************************************************/
|
||
|
||
/** General monospace/pre rules ***********************************************/
|
||
|
||
pre, code, samp {
|
||
font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
|
||
font-size: .9em;
|
||
hyphens: none;
|
||
text-transform: none;
|
||
text-align: left;
|
||
text-align: start;
|
||
font-variant: normal;
|
||
orphans: 3;
|
||
widows: 3;
|
||
page-break-before: avoid;
|
||
}
|
||
pre code,
|
||
code code {
|
||
font-size: 100%;
|
||
}
|
||
|
||
pre {
|
||
margin-top: 1em;
|
||
margin-bottom: 1em;
|
||
overflow: auto;
|
||
}
|
||
|
||
/** Inline Code fragments *****************************************************/
|
||
|
||
/* Do something nice. */
|
||
|
||
/******************************************************************************/
|
||
/* Links */
|
||
/******************************************************************************/
|
||
|
||
/** General Hyperlinks ********************************************************/
|
||
|
||
/* We hyperlink a lot, so make it less intrusive */
|
||
a[href] {
|
||
color: #034575;
|
||
color: var(--a-normal-text);
|
||
text-decoration: underline #707070;
|
||
text-decoration: underline var(--a-normal-underline);
|
||
text-decoration-skip-ink: none;
|
||
}
|
||
a:visited {
|
||
color: #034575;
|
||
color: var(--a-visited-text);
|
||
text-decoration-color: #bbb;
|
||
text-decoration-color: var(--a-visited-underline);
|
||
}
|
||
|
||
/* Indicate interaction with the link */
|
||
a[href]:focus,
|
||
a[href]:hover {
|
||
text-decoration-thickness: 2px;
|
||
}
|
||
a[href]:active {
|
||
color: #c00;
|
||
color: var(--a-active-text);
|
||
text-decoration-color: #c00;
|
||
text-decoration-color: var(--a-active-underline);
|
||
}
|
||
|
||
/* Backout above styling for W3C logo */
|
||
.head .logo,
|
||
.head .logo a {
|
||
border: none;
|
||
text-decoration: none;
|
||
background: transparent;
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/* Images */
|
||
/******************************************************************************/
|
||
|
||
img {
|
||
border-style: none;
|
||
}
|
||
|
||
img, svg {
|
||
/* Intentionally not color-scheme aware. */
|
||
background: white;
|
||
}
|
||
|
||
/* For autogen numbers, add
|
||
.caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
|
||
*/
|
||
|
||
figure, .figure, .sidefigure {
|
||
page-break-inside: avoid;
|
||
text-align: center;
|
||
margin: 2.5em 0;
|
||
}
|
||
.figure img, .sidefigure img, figure img,
|
||
.figure object, .sidefigure object, figure object {
|
||
max-width: 100%;
|
||
margin: auto;
|
||
height: auto;
|
||
}
|
||
.figure pre, .sidefigure pre, figure pre {
|
||
text-align: left;
|
||
display: table;
|
||
margin: 1em auto;
|
||
}
|
||
.figure table, figure table {
|
||
margin: auto;
|
||
}
|
||
@media screen and (min-width: 20em) {
|
||
.sidefigure {
|
||
float: right;
|
||
width: 50%;
|
||
margin: 0 0 0.5em 0.5em;
|
||
}
|
||
}
|
||
.caption, figcaption, caption {
|
||
font-style: italic;
|
||
font-size: 90%;
|
||
}
|
||
.caption::before, figcaption::before, figcaption > .marker {
|
||
font-weight: bold;
|
||
}
|
||
.caption, figcaption {
|
||
counter-increment: figure;
|
||
}
|
||
|
||
/* DL list is indented 2em, but figure inside it is not */
|
||
dd > .figure, dd > figure { margin-left: -2em; }
|
||
|
||
/******************************************************************************/
|
||
/* Colored Boxes */
|
||
/******************************************************************************/
|
||
|
||
.issue, .note, .example, .assertion, .advisement, blockquote,
|
||
.amendment, .correction, .addition {
|
||
margin: 1em auto;
|
||
padding: .5em;
|
||
border: .5em;
|
||
border-left-style: solid;
|
||
page-break-inside: avoid;
|
||
}
|
||
span.issue, span.note {
|
||
padding: .1em .5em .15em;
|
||
border-right-style: solid;
|
||
}
|
||
|
||
blockquote > :first-child,
|
||
.note > p:first-child,
|
||
.issue > p:first-child,
|
||
.amendment > p:first-child,
|
||
.correction > p:first-child,
|
||
.addition > p:first-child {
|
||
margin-top: 0;
|
||
}
|
||
blockquote > :last-child,
|
||
.note > p:last-child,
|
||
.issue > p:last-child,
|
||
.amendment > p:last-child,
|
||
.correction > p:last-child,
|
||
.addition > p:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
|
||
.issue::before, .issue > .marker,
|
||
.example::before, .example > .marker,
|
||
.note::before, .note > .marker,
|
||
details.note > summary > .marker,
|
||
.amendment::before, .amendment > .marker,
|
||
details.amendment > summary > .marker,
|
||
.addition::before, .addition > .marker,
|
||
addition.amendment > summary > .marker,
|
||
.correction::before, .correction > .marker,
|
||
correction.amendment > summary > .marker
|
||
{
|
||
text-transform: uppercase;
|
||
padding-right: 1em;
|
||
}
|
||
|
||
.example::before, .example > .marker {
|
||
display: block;
|
||
padding-right: 0em;
|
||
}
|
||
|
||
/** Blockquotes ***************************************************************/
|
||
|
||
blockquote {
|
||
border-color: silver;
|
||
border-color: var(--blockquote-border);
|
||
background: transparent;
|
||
background: var(--blockquote-bg);
|
||
color: currentcolor;
|
||
color: var(--blockquote-text);
|
||
}
|
||
|
||
/** Open issue ****************************************************************/
|
||
|
||
.issue {
|
||
border-color: #e05252;
|
||
border-color: var(--issue-border);
|
||
background: #fbe9e9;
|
||
background: var(--issue-bg);
|
||
color: black;
|
||
color: var(--issue-text);
|
||
counter-increment: issue;
|
||
overflow: auto;
|
||
}
|
||
.issue::before, .issue > .marker {
|
||
color: #831616;
|
||
color: var(--issueheading-text);
|
||
}
|
||
/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
|
||
or use class="marker" to mark up the issue number in source. */
|
||
|
||
/** Example *******************************************************************/
|
||
|
||
.example {
|
||
border-color: #e0cb52;
|
||
border-color: var(--example-border);
|
||
background: #fcfaee;
|
||
background: var(--example-bg);
|
||
color: black;
|
||
color: var(--example-text);
|
||
counter-increment: example;
|
||
overflow: auto;
|
||
clear: both;
|
||
}
|
||
.example::before, .example > .marker {
|
||
color: #574b0f;
|
||
color: var(--exampleheading-text);
|
||
}
|
||
/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
|
||
or use class="marker" to mark up the example number in source. */
|
||
|
||
/** Non-normative Note ********************************************************/
|
||
|
||
.note {
|
||
border-color: #52e052;
|
||
border-color: var(--note-border);
|
||
background: #e9fbe9;
|
||
background: var(--note-bg);
|
||
color: black;
|
||
color: var(--note-text);
|
||
overflow: auto;
|
||
}
|
||
|
||
.note::before, .note > .marker,
|
||
details.note > summary {
|
||
color: hsl(120, 70%, 30%);
|
||
color: var(--noteheading-text);
|
||
}
|
||
/* Add .note::before { content: "Note "; } for autogen label,
|
||
or use class="marker" to mark up the label in source. */
|
||
|
||
details.note[open] > summary {
|
||
border-bottom: 1px silver solid;
|
||
border-bottom: 1px var(--notesummary-underline) solid;
|
||
}
|
||
|
||
/** Assertion Box *************************************************************/
|
||
/* for assertions in algorithms */
|
||
|
||
.assertion {
|
||
border-color: #AAA;
|
||
border-color: var(--assertion-border);
|
||
background: #EEE;
|
||
background: var(--assertion-bg);
|
||
color: black;
|
||
color: var(--assertion-text);
|
||
}
|
||
|
||
/** Advisement Box ************************************************************/
|
||
/* for attention-grabbing normative statements */
|
||
|
||
.advisement {
|
||
border-color: orange;
|
||
border-color: var(--advisement-border);
|
||
border-style: none solid;
|
||
background: #fec;
|
||
background: var(--advisement-bg);
|
||
color: black;
|
||
color: var(--advisement-text);
|
||
}
|
||
strong.advisement {
|
||
display: block;
|
||
text-align: center;
|
||
}
|
||
.advisement::before, .advisement > .marker {
|
||
color: #b35f00;
|
||
color: var(--advisementheading-text);
|
||
}
|
||
|
||
/** Amendment Box *************************************************************/
|
||
|
||
.amendment, .correction, .addition {
|
||
border-color: #330099;
|
||
border-color: var(--amendment-border);
|
||
background: #F5F0FF;
|
||
background: var(--amendment-bg);
|
||
color: black;
|
||
color: var(--amendment-text);
|
||
}
|
||
.amendment.proposed, .correction.proposed, .addition.proposed {
|
||
border-style: solid;
|
||
border-block-width: 0.25em;
|
||
}
|
||
.amendment::before, .amendment > .marker,
|
||
details.amendment > summary::before, details.amendment > summary > .marker,
|
||
.correction::before, .correction > .marker,
|
||
details.correction > summary::before, details.correction > summary > .marker,
|
||
.addition::before, .addition > .marker,
|
||
details.addition > summary::before, details.addition > summary > .marker {
|
||
color: #220066;
|
||
color: var(--amendmentheading-text);
|
||
}
|
||
.amendment.proposed::before, .amendment.proposed > .marker,
|
||
details.amendment.proposed > summary::before, details.amendment.proposed > summary > .marker,
|
||
.correction.proposed::before, .correction.proposed > .marker,
|
||
details.correction.proposed > summary::before, details.correction.proposed > summary > .marker,
|
||
.addition.proposed::before, .addition.proposed > .marker,
|
||
details.addition.proposed > summary::before, details.addition.proposed > summary > .marker {
|
||
font-weight: bold;
|
||
}
|
||
|
||
/** Spec Obsoletion Notice ****************************************************/
|
||
/* obnoxious obsoletion notice for older/abandoned specs. */
|
||
|
||
details {
|
||
display: block;
|
||
}
|
||
summary {
|
||
font-weight: bolder;
|
||
}
|
||
|
||
.annoying-warning:not(details),
|
||
details.annoying-warning:not([open]) > summary,
|
||
details.annoying-warning[open] {
|
||
background: hsla(40,100%,50%,0.95);
|
||
background: var(--warning-bg);
|
||
color: black;
|
||
color: var(--warning-text);
|
||
padding: .75em 1em;
|
||
border: red;
|
||
border: var(--warning-border);
|
||
border-style: solid none;
|
||
box-shadow: 0 2px 8px black;
|
||
text-align: center;
|
||
}
|
||
.annoying-warning :last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
@media not print {
|
||
details.annoying-warning[open] {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 2em;
|
||
z-index: 1000;
|
||
}
|
||
}
|
||
|
||
details.annoying-warning:not([open]) > summary {
|
||
text-align: center;
|
||
}
|
||
|
||
/** Entity Definition Boxes ***************************************************/
|
||
|
||
.def {
|
||
padding: .5em 1em;
|
||
background: #def;
|
||
background: var(--def-bg);
|
||
margin: 1.2em 0;
|
||
border-left: 0.5em solid #8ccbf2;
|
||
border-left: 0.5em solid var(--def-border);
|
||
color: black;
|
||
color: var(--def-text);
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/* Tables */
|
||
/******************************************************************************/
|
||
|
||
th, td {
|
||
text-align: left;
|
||
text-align: start;
|
||
}
|
||
|
||
/** Property/Descriptor Definition Tables *************************************/
|
||
|
||
table.def {
|
||
/* inherits .def box styling, see above */
|
||
width: 100%;
|
||
border-spacing: 0;
|
||
}
|
||
|
||
table.def td,
|
||
table.def th {
|
||
padding: 0.5em;
|
||
vertical-align: baseline;
|
||
border-bottom: 1px solid #bbd7e9;
|
||
border-bottom: 1px solid var(--defrow-border);
|
||
}
|
||
|
||
table.def > tbody > tr:last-child th,
|
||
table.def > tbody > tr:last-child td {
|
||
border-bottom: 0;
|
||
}
|
||
|
||
table.def th {
|
||
font-style: italic;
|
||
font-weight: normal;
|
||
padding-left: 1em;
|
||
width: 3em;
|
||
}
|
||
|
||
/* For when values are extra-complex and need formatting for readability */
|
||
table td.pre {
|
||
white-space: pre-wrap;
|
||
}
|
||
|
||
/* A footnote at the bottom of a def table */
|
||
table.def td.footnote {
|
||
padding-top: 0.6em;
|
||
}
|
||
table.def td.footnote::before {
|
||
content: " ";
|
||
display: block;
|
||
height: 0.6em;
|
||
width: 4em;
|
||
border-top: thin solid;
|
||
}
|
||
|
||
/** Data tables (and properly marked-up index tables) *************************/
|
||
/*
|
||
<table class="data"> highlights structural relationships in a table
|
||
when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)
|
||
|
||
Use class="complex data" for particularly complicated tables --
|
||
(This will draw more lines: busier, but clearer.)
|
||
|
||
Use class="long" on table cells with paragraph-like contents
|
||
(This will adjust text alignment accordingly.)
|
||
Alternately use class="longlastcol" on tables, to have the last column assume "long".
|
||
*/
|
||
|
||
table {
|
||
word-wrap: normal;
|
||
overflow-wrap: normal;
|
||
hyphens: manual;
|
||
}
|
||
|
||
table.data,
|
||
table.index {
|
||
margin: 1em auto;
|
||
border-collapse: collapse;
|
||
border: hidden;
|
||
width: 100%;
|
||
}
|
||
table.data caption,
|
||
table.index caption {
|
||
max-width: 50em;
|
||
margin: 0 auto 1em;
|
||
}
|
||
|
||
table.data td, table.data th,
|
||
table.index td, table.index th {
|
||
padding: 0.5em 1em;
|
||
border-width: 1px;
|
||
border-color: silver;
|
||
border-color: var(--datacell-border);
|
||
border-top-style: solid;
|
||
}
|
||
|
||
table.data thead td:empty {
|
||
padding: 0;
|
||
border: 0;
|
||
}
|
||
|
||
table.data thead,
|
||
table.index thead,
|
||
table.data tbody,
|
||
table.index tbody {
|
||
border-bottom: 2px solid;
|
||
}
|
||
|
||
table.data colgroup,
|
||
table.index colgroup {
|
||
border-left: 2px solid;
|
||
}
|
||
|
||
table.data tbody th:first-child,
|
||
table.index tbody th:first-child {
|
||
border-right: 2px solid;
|
||
border-top: 1px solid silver;
|
||
border-top: 1px solid var(--datacell-border);
|
||
padding-right: 1em;
|
||
}
|
||
|
||
table.data th[colspan],
|
||
table.data td[colspan] {
|
||
text-align: center;
|
||
}
|
||
|
||
table.complex.data th,
|
||
table.complex.data td {
|
||
border: 1px solid silver;
|
||
border: 1px solid var(--datacell-border);
|
||
text-align: center;
|
||
}
|
||
|
||
table.data.longlastcol td:last-child,
|
||
table.data td.long {
|
||
vertical-align: baseline;
|
||
text-align: left;
|
||
}
|
||
|
||
table.data img {
|
||
vertical-align: middle;
|
||
}
|
||
|
||
|
||
/*
|
||
Alternate table alignment rules
|
||
|
||
table.data,
|
||
table.index {
|
||
text-align: center;
|
||
}
|
||
|
||
table.data thead th[scope="row"],
|
||
table.index thead th[scope="row"] {
|
||
text-align: right;
|
||
}
|
||
|
||
table.data tbody th:first-child,
|
||
table.index tbody th:first-child {
|
||
text-align: right;
|
||
}
|
||
|
||
Possible extra rowspan handling
|
||
|
||
table.data tbody th[rowspan]:not([rowspan='1']),
|
||
table.index tbody th[rowspan]:not([rowspan='1']),
|
||
table.data tbody td[rowspan]:not([rowspan='1']),
|
||
table.index tbody td[rowspan]:not([rowspan='1']) {
|
||
border-left: 1px solid silver;
|
||
}
|
||
|
||
table.data tbody th[rowspan]:first-child,
|
||
table.index tbody th[rowspan]:first-child,
|
||
table.data tbody td[rowspan]:first-child,
|
||
table.index tbody td[rowspan]:first-child{
|
||
border-left: 0;
|
||
border-right: 1px solid silver;
|
||
}
|
||
*/
|
||
|
||
/******************************************************************************/
|
||
/* Indices */
|
||
/******************************************************************************/
|
||
|
||
|
||
/** Table of Contents *********************************************************/
|
||
|
||
.toc a {
|
||
/* More spacing; use padding to make it part of the click target. */
|
||
padding: 0.1rem 1px 0;
|
||
/* Larger, more consistently-sized click target */
|
||
display: block;
|
||
/* Switch to using border-bottom for underlines */
|
||
text-decoration: none;
|
||
border-bottom: 1px solid;
|
||
/* Reverse color scheme */
|
||
color: black;
|
||
color: var(--toclink-text);
|
||
border-color: #3980b5;
|
||
border-color: var(--toclink-underline);
|
||
}
|
||
.toc a:visited {
|
||
color: black;
|
||
color: var(--toclink-visited-text);
|
||
border-color: #054572;
|
||
border-color: var(--toclink-visited-underline);
|
||
}
|
||
.toc a:focus,
|
||
.toc a:hover {
|
||
background: rgba(75%, 75%, 75%, .25);
|
||
background: var(--a-hover-bg);
|
||
border-bottom-width: 3px;
|
||
margin-bottom: -2px;
|
||
}
|
||
.toc a:not(:focus):not(:hover) {
|
||
/* Allow colors to cascade through from link styling */
|
||
border-bottom-color: transparent;
|
||
}
|
||
|
||
.toc, .toc ol, .toc ul, .toc li {
|
||
list-style: none; /* Numbers must be inlined into source */
|
||
/* because generated content isn't search/selectable and markers can't do multilevel yet */
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
.toc {
|
||
line-height: 1.1em;
|
||
}
|
||
|
||
/* ToC not indented until third level, but font style & margins show hierarchy */
|
||
.toc > li { font-weight: bold; }
|
||
.toc > li li { font-weight: normal; }
|
||
.toc > li li li { font-size: 95%; }
|
||
.toc > li li li li { font-size: 90%; }
|
||
.toc > li li li li li { font-size: 85%; }
|
||
|
||
/* @supports not (display:grid) { */
|
||
.toc > li { margin: 1.5rem 0; }
|
||
.toc > li li { margin: 0.3rem 0; }
|
||
.toc > li li li { margin-left: 2rem; }
|
||
|
||
/* Section numbers in a column of their own */
|
||
.toc .secno {
|
||
float: left;
|
||
width: 4rem;
|
||
white-space: nowrap;
|
||
}
|
||
.toc > li li li li .secno { font-size: 85%; }
|
||
.toc > li li li li li .secno { font-size: 100%; }
|
||
|
||
.toc li {
|
||
clear: both;
|
||
}
|
||
|
||
:not(li) > .toc { margin-left: 5rem; }
|
||
.toc .secno { margin-left: -5rem; }
|
||
.toc > li li li .secno { margin-left: -7rem; }
|
||
.toc > li li li li .secno { margin-left: -9rem; }
|
||
.toc > li li li li li .secno { margin-left: -11rem; }
|
||
|
||
/* Tighten up indentation in narrow ToCs */
|
||
@media (max-width: 30em) {
|
||
:not(li) > .toc { margin-left: 4rem; }
|
||
.toc .secno { margin-left: -4rem; }
|
||
.toc > li li li { margin-left: 1rem; }
|
||
.toc > li li li .secno { margin-left: -5rem; }
|
||
.toc > li li li li .secno { margin-left: -6rem; }
|
||
.toc > li li li li li .secno { margin-left: -7rem; }
|
||
}
|
||
/* Loosen it on wide screens */
|
||
@media screen and (min-width: 78em) {
|
||
body:not(.toc-inline) :not(li) > .toc { margin-left: 4rem; }
|
||
body:not(.toc-inline) .toc .secno { margin-left: -4rem; }
|
||
body:not(.toc-inline) .toc > li li li { margin-left: 1rem; }
|
||
body:not(.toc-inline) .toc > li li li .secno { margin-left: -5rem; }
|
||
body:not(.toc-inline) .toc > li li li li .secno { margin-left: -6rem; }
|
||
body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
|
||
}
|
||
/* } */
|
||
|
||
@supports (display:grid) and (display:contents) {
|
||
/* Use #toc over .toc to override non-@supports rules. */
|
||
#toc {
|
||
display: grid;
|
||
align-content: start;
|
||
grid-template-columns: auto 1fr;
|
||
grid-column-gap: 1rem;
|
||
column-gap: 1rem;
|
||
grid-row-gap: .6rem;
|
||
row-gap: .6rem;
|
||
}
|
||
#toc h2 {
|
||
grid-column: 1 / -1;
|
||
margin-bottom: 0;
|
||
}
|
||
#toc ol,
|
||
#toc li,
|
||
#toc a {
|
||
display: contents;
|
||
/* Switch <a> to subgrid when supported */
|
||
}
|
||
#toc span {
|
||
margin: 0;
|
||
}
|
||
#toc > .toc > li > a > span {
|
||
/* The spans of the top-level list,
|
||
comprising the first items of each top-level section. */
|
||
margin-top: 1.1rem;
|
||
}
|
||
#toc#toc .secno { /* Ugh, need more specificity to override base.css */
|
||
grid-column: 1;
|
||
width: auto;
|
||
margin-left: 0;
|
||
}
|
||
#toc .content {
|
||
grid-column: 2;
|
||
width: auto;
|
||
margin-right: 1rem;
|
||
}
|
||
#toc .content:hover,
|
||
#toc .content:focus {
|
||
background: rgba(75%, 75%, 75%, .25);
|
||
background: var(--a-hover-bg);
|
||
border-bottom: 3px solid #054572;
|
||
border-bottom: 3px solid var(--toclink-underline);
|
||
margin-bottom: -3px;
|
||
}
|
||
#toc li li li .content {
|
||
margin-left: 1rem;
|
||
}
|
||
#toc li li li li .content {
|
||
margin-left: 2rem;
|
||
}
|
||
}
|
||
|
||
|
||
/** Index *********************************************************************/
|
||
|
||
/* Index Lists: Layout */
|
||
ul.index { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
|
||
ul.index li { margin-left: 0; list-style: none; break-inside: avoid; }
|
||
ul.index li li { margin-left: 1em; }
|
||
ul.index dl { margin-top: 0; }
|
||
ul.index dt { margin: .2em 0 .2em 20px;}
|
||
ul.index dd { margin: .2em 0 .2em 40px;}
|
||
/* Index Lists: Typography */
|
||
ul.index ul,
|
||
ul.index dl { font-size: smaller; }
|
||
@media not print {
|
||
ul.index li a + span {
|
||
white-space: nowrap;
|
||
color: transparent; }
|
||
ul.index li a:hover + span,
|
||
ul.index li a:focus + span {
|
||
color: #707070;
|
||
color: var(--indexinfo-text);
|
||
}
|
||
}
|
||
|
||
/** Index Tables *****************************************************/
|
||
/* See also the data table styling section, which this effectively subclasses */
|
||
|
||
table.index {
|
||
font-size: small;
|
||
border-collapse: collapse;
|
||
border-spacing: 0;
|
||
text-align: left;
|
||
margin: 1em 0;
|
||
}
|
||
|
||
table.index td,
|
||
table.index th {
|
||
padding: 0.4em;
|
||
}
|
||
|
||
table.index tr:hover td:not([rowspan]),
|
||
table.index tr:hover th:not([rowspan]) {
|
||
color: black;
|
||
color: var(--indextable-hover-text);
|
||
background: #f7f8f9;
|
||
background: var(--indextable-hover-bg);
|
||
}
|
||
|
||
/* The link in the first column in the property table (formerly a TD) */
|
||
table.index th:first-child a {
|
||
font-weight: bold;
|
||
}
|
||
|
||
/** Outdated warning **********************************************************/
|
||
|
||
.outdated-spec {
|
||
color: black;
|
||
color: var(--outdatedspec-text);
|
||
background-color: rgba(0,0,0,0.5);
|
||
background-color: var(--outdatedspec-bg);
|
||
}
|
||
|
||
.outdated-warning {
|
||
position: fixed;
|
||
bottom: 50%;
|
||
left: 0;
|
||
right: 0;
|
||
margin: 0 auto;
|
||
width: 50%;
|
||
background: maroon;
|
||
background: var(--outdated-bg);
|
||
color: white;
|
||
color: var(--outdated-text);
|
||
border-radius: 1em;
|
||
box-shadow: 0 0 1em red;
|
||
box-shadow: 0 0 1em var(--outdated-shadow);
|
||
padding: 2em;
|
||
text-align: center;
|
||
z-index: 2;
|
||
}
|
||
|
||
.outdated-warning a {
|
||
color: currentcolor;
|
||
background: transparent;
|
||
}
|
||
|
||
.edited-rec-warning {
|
||
background: darkorange;
|
||
background: var(--editedrec-bg);
|
||
box-shadow: 0 0 1em;
|
||
}
|
||
|
||
.outdated-warning button {
|
||
color: var(--outdated-text);
|
||
border-radius: 1em;
|
||
box-shadow: 0 0 1em red;
|
||
box-shadow: 0 0 1em var(--outdated-shadow);
|
||
padding: 2em;
|
||
text-align: center;
|
||
z-index: 2;
|
||
}
|
||
|
||
.outdated-warning a {
|
||
color: currentcolor;
|
||
background: transparent;
|
||
}
|
||
|
||
.edited-rec-warning {
|
||
background: darkorange;
|
||
background: var(--editedrec-bg);
|
||
box-shadow: 0 0 1em;
|
||
}
|
||
|
||
.outdated-warning button {
|
||
position: absolute;
|
||
top: 0;
|
||
right:0;
|
||
margin: 0;
|
||
border: 0;
|
||
padding: 0.25em 0.5em;
|
||
background: transparent;
|
||
color: white;
|
||
color: var(--outdated-text);
|
||
font:1em sans-serif;
|
||
text-align:center;
|
||
}
|
||
|
||
.outdated-warning span {
|
||
display: block;
|
||
}
|
||
|
||
.outdated-collapsed {
|
||
bottom: 0;
|
||
border-radius: 0;
|
||
width: 100%;
|
||
padding: 0;
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/* Print */
|
||
/******************************************************************************/
|
||
|
||
@media print {
|
||
/* Pages have their own margins. */
|
||
html {
|
||
margin: 0;
|
||
}
|
||
/* Serif for print. */
|
||
body {
|
||
font-family: serif;
|
||
}
|
||
|
||
.outdated-warning {
|
||
position: absolute;
|
||
border-style: solid;
|
||
border-color: red;
|
||
}
|
||
|
||
.outdated-warning input {
|
||
display: none;
|
||
}
|
||
}
|
||
@page {
|
||
margin: 1.5cm 1.1cm;
|
||
}
|
||
|
||
|
||
|
||
/******************************************************************************/
|
||
/* Overflow Control */
|
||
/******************************************************************************/
|
||
|
||
.figure .caption, .sidefigure .caption, figcaption {
|
||
/* in case figure is overlarge, limit caption to 50em */
|
||
max-width: 50rem;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
.overlarge {
|
||
/* Magic to create good item positioning:
|
||
"content column" is 50ems wide at max; less on smaller screens.
|
||
Extra space (after ToC + content) is empty on the right.
|
||
|
||
1. When item < content column, centers item in column.
|
||
2. When content < item < available, left-aligns.
|
||
3. When item > available, fills available + scroll bar.
|
||
*/
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 50em);
|
||
}
|
||
.overlarge > table {
|
||
/* limit preferred width of table */
|
||
max-width: 50em;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
|
||
@media (min-width: 55em) {
|
||
.overlarge {
|
||
margin-right: calc(13px + 26.5rem - 50vw);
|
||
max-width: none;
|
||
}
|
||
}
|
||
@media screen and (min-width: 78em) {
|
||
body:not(.toc-inline) .overlarge {
|
||
/* 30.5em body padding 50em content area */
|
||
margin-right: calc(40em - 50vw) !important;
|
||
}
|
||
}
|
||
@media screen and (min-width: 90em) {
|
||
body:not(.toc-inline) .overlarge {
|
||
/* 4em html margin 30.5em body padding 50em content area */
|
||
margin-right: calc(84.5em - 100vw) !important;
|
||
}
|
||
}
|
||
|
||
@media not print {
|
||
.overlarge {
|
||
overflow-x: auto;
|
||
/* See Lea Verou's explanation background-attachment:
|
||
* http://lea.verou.me/2012/04/background-attachment-local/
|
||
*
|
||
background: top left / 4em 100% linear-gradient(to right, #ffffff, rgba(255, 255, 255, 0)) local,
|
||
top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
|
||
top left / 1em 100% linear-gradient(to right, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
|
||
top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
|
||
white;
|
||
background-repeat: no-repeat;
|
||
*/
|
||
}
|
||
}
|
||
</style>
|
||
<meta content="Bikeshed version 5fcd28d6d, updated Tue May 30 13:12:11 2023 -0700" name="generator">
|
||
<meta content="2ec2dd7752939adf032c92c0ed97d7908b381965" name="document-revision">
|
||
<style>/* Boilerplate: style-autolinks */
|
||
.css.css, .property.property, .descriptor.descriptor {
|
||
color: var(--a-normal-text);
|
||
font-size: inherit;
|
||
font-family: inherit;
|
||
}
|
||
.css::before, .property::before, .descriptor::before {
|
||
content: "‘";
|
||
}
|
||
.css::after, .property::after, .descriptor::after {
|
||
content: "’";
|
||
}
|
||
.property, .descriptor {
|
||
/* Don't wrap property and descriptor names */
|
||
white-space: nowrap;
|
||
}
|
||
.type { /* CSS value <type> */
|
||
font-style: italic;
|
||
}
|
||
pre .property::before, pre .property::after {
|
||
content: "";
|
||
}
|
||
[data-link-type="property"]::before,
|
||
[data-link-type="propdesc"]::before,
|
||
[data-link-type="descriptor"]::before,
|
||
[data-link-type="value"]::before,
|
||
[data-link-type="function"]::before,
|
||
[data-link-type="at-rule"]::before,
|
||
[data-link-type="selector"]::before,
|
||
[data-link-type="maybe"]::before {
|
||
content: "‘";
|
||
}
|
||
[data-link-type="property"]::after,
|
||
[data-link-type="propdesc"]::after,
|
||
[data-link-type="descriptor"]::after,
|
||
[data-link-type="value"]::after,
|
||
[data-link-type="function"]::after,
|
||
[data-link-type="at-rule"]::after,
|
||
[data-link-type="selector"]::after,
|
||
[data-link-type="maybe"]::after {
|
||
content: "’";
|
||
}
|
||
|
||
[data-link-type].production::before,
|
||
[data-link-type].production::after,
|
||
.prod [data-link-type]::before,
|
||
.prod [data-link-type]::after {
|
||
content: "";
|
||
}
|
||
|
||
[data-link-type=element],
|
||
[data-link-type=element-attr] {
|
||
font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
|
||
font-size: .9em;
|
||
}
|
||
[data-link-type=element]::before { content: "<" }
|
||
[data-link-type=element]::after { content: ">" }
|
||
|
||
[data-link-type=biblio] {
|
||
white-space: pre;
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--selflink-text: black;
|
||
--selflink-bg: silver;
|
||
--selflink-hover-text: white;
|
||
}
|
||
}
|
||
</style>
|
||
<style>/* Boilerplate: style-colors */
|
||
|
||
/* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */
|
||
:root {
|
||
color-scheme: light dark;
|
||
|
||
--text: black;
|
||
--bg: white;
|
||
|
||
--unofficial-watermark: url(https://www.w3.org/StyleSheets/TR/2016/logos/UD-watermark);
|
||
|
||
--logo-bg: #1a5e9a;
|
||
--logo-active-bg: #c00;
|
||
--logo-text: white;
|
||
|
||
--tocnav-normal-text: #707070;
|
||
--tocnav-normal-bg: var(--bg);
|
||
--tocnav-hover-text: var(--tocnav-normal-text);
|
||
--tocnav-hover-bg: #f8f8f8;
|
||
--tocnav-active-text: #c00;
|
||
--tocnav-active-bg: var(--tocnav-normal-bg);
|
||
|
||
--tocsidebar-text: var(--text);
|
||
--tocsidebar-bg: #f7f8f9;
|
||
--tocsidebar-shadow: rgba(0,0,0,.1);
|
||
--tocsidebar-heading-text: hsla(203,20%,40%,.7);
|
||
|
||
--toclink-text: var(--text);
|
||
--toclink-underline: #3980b5;
|
||
--toclink-visited-text: var(--toclink-text);
|
||
--toclink-visited-underline: #054572;
|
||
|
||
--heading-text: #005a9c;
|
||
|
||
--hr-text: var(--text);
|
||
|
||
--algo-border: #def;
|
||
|
||
--del-text: red;
|
||
--del-bg: transparent;
|
||
--ins-text: #080;
|
||
--ins-bg: transparent;
|
||
|
||
--a-normal-text: #034575;
|
||
--a-normal-underline: #bbb;
|
||
--a-visited-text: var(--a-normal-text);
|
||
--a-visited-underline: #707070;
|
||
--a-hover-bg: rgba(75%, 75%, 75%, .25);
|
||
--a-active-text: #c00;
|
||
--a-active-underline: #c00;
|
||
|
||
--blockquote-border: silver;
|
||
--blockquote-bg: transparent;
|
||
--blockquote-text: currentcolor;
|
||
|
||
--issue-border: #e05252;
|
||
--issue-bg: #fbe9e9;
|
||
--issue-text: var(--text);
|
||
--issueheading-text: #831616;
|
||
|
||
--example-border: #e0cb52;
|
||
--example-bg: #fcfaee;
|
||
--example-text: var(--text);
|
||
--exampleheading-text: #574b0f;
|
||
|
||
--note-border: #52e052;
|
||
--note-bg: #e9fbe9;
|
||
--note-text: var(--text);
|
||
--noteheading-text: hsl(120, 70%, 30%);
|
||
--notesummary-underline: silver;
|
||
|
||
--assertion-border: #aaa;
|
||
--assertion-bg: #eee;
|
||
--assertion-text: black;
|
||
|
||
--advisement-border: orange;
|
||
--advisement-bg: #fec;
|
||
--advisement-text: var(--text);
|
||
--advisementheading-text: #b35f00;
|
||
|
||
--warning-border: red;
|
||
--warning-bg: hsla(40,100%,50%,0.95);
|
||
--warning-text: var(--text);
|
||
|
||
--amendment-border: #330099;
|
||
--amendment-bg: #F5F0FF;
|
||
--amendment-text: var(--text);
|
||
--amendmentheading-text: #220066;
|
||
|
||
--def-border: #8ccbf2;
|
||
--def-bg: #def;
|
||
--def-text: var(--text);
|
||
--defrow-border: #bbd7e9;
|
||
|
||
--datacell-border: silver;
|
||
|
||
--indexinfo-text: #707070;
|
||
|
||
--indextable-hover-text: black;
|
||
--indextable-hover-bg: #f7f8f9;
|
||
|
||
--outdatedspec-bg: rgba(0, 0, 0, .5);
|
||
--outdatedspec-text: black;
|
||
--outdated-bg: maroon;
|
||
--outdated-text: white;
|
||
--outdated-shadow: red;
|
||
|
||
--editedrec-bg: darkorange;
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--text: #ddd;
|
||
--bg: black;
|
||
|
||
--unofficial-watermark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cg fill='%23100808' transform='translate(200 200) rotate(-45) translate(-200 -200)' stroke='%23100808' stroke-width='3'%3E%3Ctext x='50%25' y='220' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EUNOFFICIAL%3C/text%3E%3Ctext x='50%25' y='305' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EDRAFT%3C/text%3E%3C/g%3E%3C/svg%3E");
|
||
|
||
--logo-bg: #1a5e9a;
|
||
--logo-active-bg: #c00;
|
||
--logo-text: white;
|
||
|
||
--tocnav-normal-text: #999;
|
||
--tocnav-normal-bg: var(--bg);
|
||
--tocnav-hover-text: var(--tocnav-normal-text);
|
||
--tocnav-hover-bg: #080808;
|
||
--tocnav-active-text: #f44;
|
||
--tocnav-active-bg: var(--tocnav-normal-bg);
|
||
|
||
--tocsidebar-text: var(--text);
|
||
--tocsidebar-bg: #080808;
|
||
--tocsidebar-shadow: rgba(255,255,255,.1);
|
||
--tocsidebar-heading-text: hsla(203,20%,40%,.7);
|
||
|
||
--toclink-text: var(--text);
|
||
--toclink-underline: #6af;
|
||
--toclink-visited-text: var(--toclink-text);
|
||
--toclink-visited-underline: #054572;
|
||
|
||
--heading-text: #8af;
|
||
|
||
--hr-text: var(--text);
|
||
|
||
--algo-border: #456;
|
||
|
||
--del-text: #f44;
|
||
--del-bg: transparent;
|
||
--ins-text: #4a4;
|
||
--ins-bg: transparent;
|
||
|
||
--a-normal-text: #6af;
|
||
--a-normal-underline: #555;
|
||
--a-visited-text: var(--a-normal-text);
|
||
--a-visited-underline: var(--a-normal-underline);
|
||
--a-hover-bg: rgba(25%, 25%, 25%, .2);
|
||
--a-active-text: #f44;
|
||
--a-active-underline: var(--a-active-text);
|
||
|
||
--borderedblock-bg: rgba(255, 255, 255, .05);
|
||
|
||
--blockquote-border: silver;
|
||
--blockquote-bg: var(--borderedblock-bg);
|
||
--blockquote-text: currentcolor;
|
||
|
||
--issue-border: #e05252;
|
||
--issue-bg: var(--borderedblock-bg);
|
||
--issue-text: var(--text);
|
||
--issueheading-text: hsl(0deg, 70%, 70%);
|
||
|
||
--example-border: hsl(50deg, 90%, 60%);
|
||
--example-bg: var(--borderedblock-bg);
|
||
--example-text: var(--text);
|
||
--exampleheading-text: hsl(50deg, 70%, 70%);
|
||
|
||
--note-border: hsl(120deg, 100%, 35%);
|
||
--note-bg: var(--borderedblock-bg);
|
||
--note-text: var(--text);
|
||
--noteheading-text: hsl(120, 70%, 70%);
|
||
--notesummary-underline: silver;
|
||
|
||
--assertion-border: #444;
|
||
--assertion-bg: var(--borderedblock-bg);
|
||
--assertion-text: var(--text);
|
||
|
||
--advisement-border: orange;
|
||
--advisement-bg: #222218;
|
||
--advisement-text: var(--text);
|
||
--advisementheading-text: #f84;
|
||
|
||
--warning-border: red;
|
||
--warning-bg: hsla(40,100%,20%,0.95);
|
||
--warning-text: var(--text);
|
||
|
||
--amendment-border: #330099;
|
||
--amendment-bg: #080010;
|
||
--amendment-text: var(--text);
|
||
--amendmentheading-text: #cc00ff;
|
||
|
||
--def-border: #8ccbf2;
|
||
--def-bg: #080818;
|
||
--def-text: var(--text);
|
||
--defrow-border: #136;
|
||
|
||
--datacell-border: silver;
|
||
|
||
--indexinfo-text: #aaa;
|
||
|
||
--indextable-hover-text: var(--text);
|
||
--indextable-hover-bg: #181818;
|
||
|
||
--outdatedspec-bg: rgba(255, 255, 255, .5);
|
||
--outdatedspec-text: black;
|
||
--outdated-bg: maroon;
|
||
--outdated-text: white;
|
||
--outdated-shadow: red;
|
||
|
||
--editedrec-bg: darkorange;
|
||
}
|
||
/* In case a transparent-bg image doesn't expect to be on a dark bg,
|
||
which is quite common in practice... */
|
||
img { background: white; }
|
||
}
|
||
</style>
|
||
<style>/* Boilerplate: style-counters */
|
||
body {
|
||
counter-reset: example figure issue;
|
||
}
|
||
.issue {
|
||
counter-increment: issue;
|
||
}
|
||
.issue:not(.no-marker)::before {
|
||
content: "Issue " counter(issue);
|
||
}
|
||
|
||
.example {
|
||
counter-increment: example;
|
||
}
|
||
.example:not(.no-marker)::before {
|
||
content: "Example " counter(example);
|
||
}
|
||
.invalid.example:not(.no-marker)::before,
|
||
.illegal.example:not(.no-marker)::before {
|
||
content: "Invalid Example" counter(example);
|
||
}
|
||
|
||
figcaption {
|
||
counter-increment: figure;
|
||
}
|
||
figcaption:not(.no-marker)::before {
|
||
content: "Figure " counter(figure) " ";
|
||
}
|
||
</style>
|
||
<style>/* Boilerplate: style-dfn-panel */
|
||
:root {
|
||
--dfnpanel-bg: #ddd;
|
||
--dfnpanel-text: var(--text);
|
||
}
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--dfnpanel-bg: #222;
|
||
--dfnpanel-text: var(--text);
|
||
}
|
||
}
|
||
.dfn-panel {
|
||
position: absolute;
|
||
z-index: 35;
|
||
width: 20em;
|
||
width: 300px;
|
||
height: auto;
|
||
max-height: 500px;
|
||
overflow: auto;
|
||
padding: 0.5em 0.75em;
|
||
font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
|
||
background: var(--dfnpanel-bg);
|
||
color: var(--dfnpanel-text);
|
||
border: outset 0.2em;
|
||
white-space: normal; /* in case it's moved into a pre */
|
||
}
|
||
.dfn-panel:not(.on) { display: none; }
|
||
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
|
||
.dfn-panel > b { display: block; }
|
||
.dfn-panel a { color: var(--dfnpanel-text); }
|
||
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
|
||
.dfn-panel > b + b { margin-top: 0.25em; }
|
||
.dfn-panel ul { padding: 0 0 0 1em; list-style: none; }
|
||
.dfn-panel li a {
|
||
white-space: pre;
|
||
display: inline-block;
|
||
max-width: calc(300px - 1.5em - 1em);
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.dfn-panel.activated {
|
||
display: inline-block;
|
||
position: fixed;
|
||
left: .5em;
|
||
bottom: 2em;
|
||
margin: 0 auto;
|
||
max-width: calc(100vw - 1.5em - .4em - .5em);
|
||
max-height: 30vh;
|
||
}
|
||
|
||
.dfn-paneled[role="button"] { cursor: pointer; }
|
||
</style>
|
||
<style>/* Boilerplate: style-dfn-panel */
|
||
:root {
|
||
--dfnpanel-bg: #ddd;
|
||
--dfnpanel-text: var(--text);
|
||
}
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--dfnpanel-bg: #222;
|
||
--dfnpanel-text: var(--text);
|
||
}
|
||
}
|
||
.dfn-panel {
|
||
position: absolute;
|
||
z-index: 35;
|
||
width: 20em;
|
||
width: 300px;
|
||
height: auto;
|
||
max-height: 500px;
|
||
overflow: auto;
|
||
padding: 0.5em 0.75em;
|
||
font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
|
||
background: var(--dfnpanel-bg);
|
||
color: var(--dfnpanel-text);
|
||
border: outset 0.2em;
|
||
white-space: normal; /* in case it's moved into a pre */
|
||
}
|
||
.dfn-panel:not(.on) { display: none; }
|
||
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
|
||
.dfn-panel > b { display: block; }
|
||
.dfn-panel a { color: var(--dfnpanel-text); }
|
||
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
|
||
.dfn-panel > b + b { margin-top: 0.25em; }
|
||
.dfn-panel ul { padding: 0 0 0 1em; list-style: none; }
|
||
.dfn-panel li a {
|
||
white-space: pre;
|
||
display: inline-block;
|
||
max-width: calc(300px - 1.5em - 1em);
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.dfn-panel.activated {
|
||
display: inline-block;
|
||
position: fixed;
|
||
left: .5em;
|
||
bottom: 2em;
|
||
margin: 0 auto;
|
||
max-width: calc(100vw - 1.5em - .4em - .5em);
|
||
max-height: 30vh;
|
||
}
|
||
|
||
.dfn-paneled[role="button"] { cursor: pointer; }
|
||
</style>
|
||
<style>/* Boilerplate: style-issues */
|
||
a[href].issue-return {
|
||
float: right;
|
||
float: inline-end;
|
||
color: var(--issueheading-text);
|
||
font-weight: bold;
|
||
text-decoration: none;
|
||
}
|
||
</style>
|
||
<style>/* Boilerplate: style-md-lists */
|
||
/* This is a weird hack for me not yet following the commonmark spec
|
||
regarding paragraph and lists. */
|
||
[data-md] > :first-child {
|
||
margin-top: 0;
|
||
}
|
||
[data-md] > :last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
</style>
|
||
<style>/* Boilerplate: style-selflinks */
|
||
|
||
:root {
|
||
--selflink-text: white;
|
||
--selflink-bg: gray;
|
||
--selflink-hover-text: black;
|
||
}
|
||
.heading, .issue, .note, .example, li, dt {
|
||
position: relative;
|
||
}
|
||
a.self-link {
|
||
position: absolute;
|
||
top: 0;
|
||
left: calc(-1 * (3.5rem - 26px));
|
||
width: calc(3.5rem - 26px);
|
||
height: 2em;
|
||
text-align: center;
|
||
border: none;
|
||
transition: opacity .2s;
|
||
opacity: .5;
|
||
}
|
||
a.self-link:hover {
|
||
opacity: 1;
|
||
}
|
||
.heading > a.self-link {
|
||
font-size: 83%;
|
||
}
|
||
.example > a.self-link,
|
||
.note > a.self-link,
|
||
.issue > a.self-link {
|
||
/* These blocks are overflow:auto, so positioning outside
|
||
doesn't work. */
|
||
left: auto;
|
||
right: 0;
|
||
}
|
||
li > a.self-link {
|
||
left: calc(-1 * (3.5rem - 26px) - 2em);
|
||
}
|
||
dfn > a.self-link {
|
||
top: auto;
|
||
left: auto;
|
||
opacity: 0;
|
||
width: 1.5em;
|
||
height: 1.5em;
|
||
background: var(--selflink-bg);
|
||
color: var(--selflink-text);
|
||
font-style: normal;
|
||
transition: opacity .2s, background-color .2s, color .2s;
|
||
}
|
||
dfn:hover > a.self-link {
|
||
opacity: 1;
|
||
}
|
||
dfn > a.self-link:hover {
|
||
color: var(--selflink-hover-text);
|
||
}
|
||
|
||
a.self-link::before { content: "¶"; }
|
||
.heading > a.self-link::before { content: "§"; }
|
||
dfn > a.self-link::before { content: "#"; }
|
||
</style>
|
||
<style>/* Boilerplate: style-style-syntax-highlighting */
|
||
|
||
pre.idl.highlight {
|
||
background: var(--borderedblock-bg, var(--def-bg));
|
||
}
|
||
|
||
</style>
|
||
<style>/* Boilerplate: style-style-var-click-highlighting */
|
||
/*
|
||
Colors were chosen in Lab using https://nixsensor.com/free-color-converter/
|
||
D50 2deg illuminant, L in [0,100], a and b in [-128, 128]
|
||
0 = lab(85,0,85)
|
||
1 = lab(85,80,30)
|
||
2 = lab(85,-40,40)
|
||
3 = lab(85,-50,0)
|
||
4 = lab(85,5,15)
|
||
5 = lab(85,-10,-50)
|
||
6 = lab(85,35,-15)
|
||
*/
|
||
var { cursor: pointer; }
|
||
var.selected0 { background-color: #F4D200; box-shadow: 0 0 0 2px #F4D200; }
|
||
var.selected1 { background-color: #FF87A2; box-shadow: 0 0 0 2px #FF87A2; }
|
||
var.selected2 { background-color: #96E885; box-shadow: 0 0 0 2px #96E885; }
|
||
var.selected3 { background-color: #3EEED2; box-shadow: 0 0 0 2px #3EEED2; }
|
||
var.selected4 { background-color: #EACFB6; box-shadow: 0 0 0 2px #EACFB6; }
|
||
var.selected5 { background-color: #82DDFF; box-shadow: 0 0 0 2px #82DDFF; }
|
||
var.selected6 { background-color: #FFBCF2; box-shadow: 0 0 0 2px #FFBCF2; }
|
||
</style>
|
||
<style>/* Boilerplate: style-syntax-highlighting */
|
||
|
||
code.highlight { padding: .1em; border-radius: .3em; }
|
||
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
|
||
|
||
.highlight:not(.idl) { background: rgba(0, 0, 0, .03); }
|
||
c-[a] { color: #990055 } /* Keyword.Declaration */
|
||
c-[b] { color: #990055 } /* Keyword.Type */
|
||
c-[c] { color: #708090 } /* Comment */
|
||
c-[d] { color: #708090 } /* Comment.Multiline */
|
||
c-[e] { color: #0077aa } /* Name.Attribute */
|
||
c-[f] { color: #669900 } /* Name.Tag */
|
||
c-[g] { color: #222222 } /* Name.Variable */
|
||
c-[k] { color: #990055 } /* Keyword */
|
||
c-[l] { color: #000000 } /* Literal */
|
||
c-[m] { color: #000000 } /* Literal.Number */
|
||
c-[n] { color: #0077aa } /* Name */
|
||
c-[o] { color: #999999 } /* Operator */
|
||
c-[p] { color: #999999 } /* Punctuation */
|
||
c-[s] { color: #a67f59 } /* Literal.String */
|
||
c-[t] { color: #a67f59 } /* Literal.String.Single */
|
||
c-[u] { color: #a67f59 } /* Literal.String.Double */
|
||
c-[cp] { color: #708090 } /* Comment.Preproc */
|
||
c-[c1] { color: #708090 } /* Comment.Single */
|
||
c-[cs] { color: #708090 } /* Comment.Special */
|
||
c-[kc] { color: #990055 } /* Keyword.Constant */
|
||
c-[kn] { color: #990055 } /* Keyword.Namespace */
|
||
c-[kp] { color: #990055 } /* Keyword.Pseudo */
|
||
c-[kr] { color: #990055 } /* Keyword.Reserved */
|
||
c-[ld] { color: #000000 } /* Literal.Date */
|
||
c-[nc] { color: #0077aa } /* Name.Class */
|
||
c-[no] { color: #0077aa } /* Name.Constant */
|
||
c-[nd] { color: #0077aa } /* Name.Decorator */
|
||
c-[ni] { color: #0077aa } /* Name.Entity */
|
||
c-[ne] { color: #0077aa } /* Name.Exception */
|
||
c-[nf] { color: #0077aa } /* Name.Function */
|
||
c-[nl] { color: #0077aa } /* Name.Label */
|
||
c-[nn] { color: #0077aa } /* Name.Namespace */
|
||
c-[py] { color: #0077aa } /* Name.Property */
|
||
c-[ow] { color: #999999 } /* Operator.Word */
|
||
c-[mb] { color: #000000 } /* Literal.Number.Bin */
|
||
c-[mf] { color: #000000 } /* Literal.Number.Float */
|
||
c-[mh] { color: #000000 } /* Literal.Number.Hex */
|
||
c-[mi] { color: #000000 } /* Literal.Number.Integer */
|
||
c-[mo] { color: #000000 } /* Literal.Number.Oct */
|
||
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
|
||
c-[sc] { color: #a67f59 } /* Literal.String.Char */
|
||
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
|
||
c-[se] { color: #a67f59 } /* Literal.String.Escape */
|
||
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
|
||
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
|
||
c-[sx] { color: #a67f59 } /* Literal.String.Other */
|
||
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
|
||
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
|
||
c-[vc] { color: #0077aa } /* Name.Variable.Class */
|
||
c-[vg] { color: #0077aa } /* Name.Variable.Global */
|
||
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
|
||
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
|
||
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.highlight:not(.idl) { background: rgba(255, 255, 255, .05); }
|
||
|
||
c-[a] { color: #d33682 } /* Keyword.Declaration */
|
||
c-[b] { color: #d33682 } /* Keyword.Type */
|
||
c-[c] { color: #2aa198 } /* Comment */
|
||
c-[d] { color: #2aa198 } /* Comment.Multiline */
|
||
c-[e] { color: #268bd2 } /* Name.Attribute */
|
||
c-[f] { color: #b58900 } /* Name.Tag */
|
||
c-[g] { color: #cb4b16 } /* Name.Variable */
|
||
c-[k] { color: #d33682 } /* Keyword */
|
||
c-[l] { color: #657b83 } /* Literal */
|
||
c-[m] { color: #657b83 } /* Literal.Number */
|
||
c-[n] { color: #268bd2 } /* Name */
|
||
c-[o] { color: #657b83 } /* Operator */
|
||
c-[p] { color: #657b83 } /* Punctuation */
|
||
c-[s] { color: #6c71c4 } /* Literal.String */
|
||
c-[t] { color: #6c71c4 } /* Literal.String.Single */
|
||
c-[u] { color: #6c71c4 } /* Literal.String.Double */
|
||
c-[ch] { color: #2aa198 } /* Comment.Hashbang */
|
||
c-[cp] { color: #2aa198 } /* Comment.Preproc */
|
||
c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */
|
||
c-[c1] { color: #2aa198 } /* Comment.Single */
|
||
c-[cs] { color: #2aa198 } /* Comment.Special */
|
||
c-[kc] { color: #d33682 } /* Keyword.Constant */
|
||
c-[kn] { color: #d33682 } /* Keyword.Namespace */
|
||
c-[kp] { color: #d33682 } /* Keyword.Pseudo */
|
||
c-[kr] { color: #d33682 } /* Keyword.Reserved */
|
||
c-[ld] { color: #657b83 } /* Literal.Date */
|
||
c-[nc] { color: #268bd2 } /* Name.Class */
|
||
c-[no] { color: #268bd2 } /* Name.Constant */
|
||
c-[nd] { color: #268bd2 } /* Name.Decorator */
|
||
c-[ni] { color: #268bd2 } /* Name.Entity */
|
||
c-[ne] { color: #268bd2 } /* Name.Exception */
|
||
c-[nf] { color: #268bd2 } /* Name.Function */
|
||
c-[nl] { color: #268bd2 } /* Name.Label */
|
||
c-[nn] { color: #268bd2 } /* Name.Namespace */
|
||
c-[py] { color: #268bd2 } /* Name.Property */
|
||
c-[ow] { color: #657b83 } /* Operator.Word */
|
||
c-[mb] { color: #657b83 } /* Literal.Number.Bin */
|
||
c-[mf] { color: #657b83 } /* Literal.Number.Float */
|
||
c-[mh] { color: #657b83 } /* Literal.Number.Hex */
|
||
c-[mi] { color: #657b83 } /* Literal.Number.Integer */
|
||
c-[mo] { color: #657b83 } /* Literal.Number.Oct */
|
||
c-[sa] { color: #6c71c4 } /* Literal.String.Affix */
|
||
c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */
|
||
c-[sc] { color: #6c71c4 } /* Literal.String.Char */
|
||
c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */
|
||
c-[sd] { color: #6c71c4 } /* Literal.String.Doc */
|
||
c-[se] { color: #6c71c4 } /* Literal.String.Escape */
|
||
c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */
|
||
c-[si] { color: #6c71c4 } /* Literal.String.Interpol */
|
||
c-[sx] { color: #6c71c4 } /* Literal.String.Other */
|
||
c-[sr] { color: #6c71c4 } /* Literal.String.Regex */
|
||
c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */
|
||
c-[fm] { color: #268bd2 } /* Name.Function.Magic */
|
||
c-[vc] { color: #cb4b16 } /* Name.Variable.Class */
|
||
c-[vg] { color: #cb4b16 } /* Name.Variable.Global */
|
||
c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */
|
||
c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */
|
||
c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */
|
||
}
|
||
</style>
|
||
<body class="h-entry">
|
||
<div class="head">
|
||
<p data-fill-with="logo"></p>
|
||
<h1 class="p-name no-ref" id="title">Web Environment Integrity</h1>
|
||
<h2 class="no-num no-toc no-ref heading settled" id="profile-and-date"><span class="content">A Collection of Interesting Ideas, <time class="dt-updated" datetime="2023-06-16">16 June 2023</time></span></h2>
|
||
<div data-fill-with="spec-metadata">
|
||
<dl>
|
||
<dt>Issue Tracking:
|
||
<dd><a href="https://github.com/RupertBenWiser/Web-Environment-Integrity/issues/">GitHub</a>
|
||
<dt class="editor">Editor:
|
||
<dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:bewise@chromium.org">Ben Wiser</a> (<span class="p-org org">Google</span>)
|
||
</dl>
|
||
</div>
|
||
<div data-fill-with="warning"></div>
|
||
<p class="copyright" data-fill-with="copyright"><a href="http://creativecommons.org/publicdomain/zero/1.0/" rel="license"><img alt="CC0" height="15" src="https://licensebuttons.net/p/zero/1.0/80x15.png" width="80"></a> To the extent possible under law, the editors have waived all copyright
|
||
and related or neighboring rights to this work.
|
||
In addition, as of 16 June 2023,
|
||
the editors have made this specification available under the <a href="http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0" rel="license">Open Web Foundation Agreement Version 1.0</a>,
|
||
which is available at http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
|
||
Parts of this work may be from another specification document. If so, those parts are instead covered by the license of that specification document. </p>
|
||
<hr title="Separator for header">
|
||
</div>
|
||
<div class="p-summary" data-fill-with="abstract">
|
||
<h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
|
||
<p>An API used to integrity check the environment a web page runs on. This check is performed
|
||
|
||
by trusted attesters.</p>
|
||
</div>
|
||
<div data-fill-with="at-risk"></div>
|
||
<nav data-fill-with="table-of-contents" id="toc">
|
||
<h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
|
||
<ol class="toc" role="directory">
|
||
<li>
|
||
<a href="#introduction"><span class="secno">1</span> <span class="content">Introduction</span></a>
|
||
<ol class="toc">
|
||
<li><a href="#motivations"><span class="secno">1.1</span> <span class="content">Motivations</span></a>
|
||
<li><a href="#examples"><span class="secno">1.2</span> <span class="content">Examples</span></a>
|
||
</ol>
|
||
<li><a href="#key-terms"><span class="secno">2</span> <span class="content">Key terms</span></a>
|
||
<li>
|
||
<a href="#attester"><span class="secno">3</span> <span class="content">Attesters</span></a>
|
||
<ol class="toc">
|
||
<li><a href="#attester-tokens"><span class="secno">3.1</span> <span class="content">Token Format</span></a>
|
||
<li><a href="#attester-browser-requirements"><span class="secno">3.2</span> <span class="content">Browser Acceptance Requirements</span></a>
|
||
<li><a href="#attester-connection"><span class="secno">3.3</span> <span class="content"><code class="idl"><span>AttesterConnection</span></code></span></a>
|
||
</ol>
|
||
<li>
|
||
<a href="#api"><span class="secno">4</span> <span class="content">Web Environment Integrity API</span></a>
|
||
<ol class="toc">
|
||
<li>
|
||
<a href="#extensions-to-navigator"><span class="secno">4.1</span> <span class="content">Extensions to <code class="idl"><span>Navigator</span></code></span></a>
|
||
<ol class="toc">
|
||
<li><a href="#navigator-getenvironmentintegrity"><span class="secno">4.1.1</span> <span class="content"><code class="idl"><span>getEnvironmentIntegrity()</span></code></span></a>
|
||
</ol>
|
||
<li><a href="#environment-integrity"><span class="secno">4.2</span> <span class="content"><code class="idl"><span>EnvironmentIntegrity</span></code></span></a>
|
||
</ol>
|
||
<li>
|
||
<a href="#security-and-privacy"><span class="secno">5</span> <span class="content">Security and privacy considerations</span></a>
|
||
<ol class="toc">
|
||
<li><a href="#security"><span class="secno">5.1</span> <span class="content">Security considerations</span></a>
|
||
<li><a href="#privacy"><span class="secno">5.2</span> <span class="content">Privacy considerations</span></a>
|
||
</ol>
|
||
<li><a href="#conformance"><span class="secno"></span> <span class="content"> Conformance</span></a>
|
||
<li>
|
||
<a href="#index"><span class="secno"></span> <span class="content">Index</span></a>
|
||
<ol class="toc">
|
||
<li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
|
||
<li><a href="#index-defined-elsewhere"><span class="secno"></span> <span class="content">Terms defined by reference</span></a>
|
||
</ol>
|
||
<li>
|
||
<a href="#references"><span class="secno"></span> <span class="content">References</span></a>
|
||
<ol class="toc">
|
||
<li><a href="#normative"><span class="secno"></span> <span class="content">Normative References</span></a>
|
||
</ol>
|
||
<li><a href="#idl-index"><span class="secno"></span> <span class="content">IDL Index</span></a>
|
||
</ol>
|
||
</nav>
|
||
<main>
|
||
<h2 class="heading settled" data-level="1" id="introduction"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#introduction"></a></h2>
|
||
<p><i>Todo</i></p>
|
||
<h3 class="heading settled" data-level="1.1" id="motivations"><span class="secno">1.1. </span><span class="content">Motivations</span><a class="self-link" href="#motivations"></a></h3>
|
||
<p><i>Todo</i></p>
|
||
<h3 class="heading settled" data-level="1.2" id="examples"><span class="secno">1.2. </span><span class="content">Examples</span><a class="self-link" href="#examples"></a></h3>
|
||
<div class="example" id="client-integrity-request">
|
||
<a class="self-link" href="#client-integrity-request"></a> Requesting environment integrity attestation.
|
||
<pre class="lang-js highlight"><c- c1>// getEnvironmentIntegrity expects a "content binding" of the request you are</c->
|
||
<c- c1>// about to make. The content binding protects against this information being</c->
|
||
<c- c1>// used for a different request.</c->
|
||
<c- c1>// The contentBinding will be concatenated with top-level domain name and hashed</c->
|
||
<c- c1>// before it is sent to the attester.</c->
|
||
|
||
<c- a>const</c-> contentBinding <c- o>=</c-> <c- u>"/someRequestPath?requestID=xxxx"</c-> <c- o>+</c->
|
||
<c- u>"Any other data needed for a request-specific contentBinding..."</c-><c- p>;</c->
|
||
|
||
<c- a>const</c-> attestation <c- o>=</c-> <c- k>await</c-> navigator<c- p>.</c->getEnvironmentIntegrity<c- p>(</c->contentBinding<c- p>);</c->
|
||
|
||
console<c- p>.</c->log<c- p>(</c->attestation<c- p>.</c->encode<c- p>());</c->
|
||
<c- u>"base-64 encoding of the attestation payload and signature approx 500 bytes; see below for details"</c->
|
||
|
||
<c- c1>// More on attestation validation below</c->
|
||
<c- a>const</c-> response <c- o>=</c-> <c- k>await</c-> fetch<c- p>(</c-><c- sb>`/someRequest?requestID=xxxx&attested=</c-><c- si>${</c->attestation<c- p>.</c->encode<c- p>()</c-><c- si>}</c-><c- sb>`</c-><c- p>);</c->
|
||
<c- c1>// Do something with this ...</c->
|
||
</pre>
|
||
</div>
|
||
<h2 class="heading settled" data-level="2" id="key-terms"><span class="secno">2. </span><span class="content">Key terms</span><a class="self-link" href="#key-terms"></a></h2>
|
||
<p>The <dfn class="dfn-paneled" data-dfn-for="web environment" data-dfn-type="dfn" data-noexport id="web-environment-web-environment">web environment</dfn> is defined as <i>TODO</i></p>
|
||
<h2 class="heading settled" data-level="3" id="attester"><span class="secno">3. </span><span class="content">Attesters</span><a class="self-link" href="#attester"></a></h2>
|
||
<p>The term <dfn class="dfn-paneled" data-dfn-for="attester" data-dfn-type="dfn" data-noexport id="attester-attester">attester</dfn> refers to a third party capable of returning an <a data-link-type="dfn" href="#integrity-verdict-integrity-verdict" id="ref-for-integrity-verdict-integrity-verdict">Integrity verdict</a>. A <dfn class="dfn-paneled" data-dfn-for="Integrity verdict" data-dfn-type="dfn" data-noexport id="integrity-verdict-integrity-verdict">Integrity verdict</dfn> refers
|
||
to a response that confirms if the <a data-link-type="dfn" href="#attester-attester" id="ref-for-attester-attester">attester</a> trusts the <a data-link-type="dfn" href="#web-environment-web-environment" id="ref-for-web-environment-web-environment">web environment</a> the <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#user-agent" id="ref-for-user-agent">user agent</a> is
|
||
executing in.</p>
|
||
<p>The <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#user-agent" id="ref-for-user-agent①">user agent</a> connects to the <a data-link-type="dfn" href="#attester-attester" id="ref-for-attester-attester①">attester</a> through an <code class="idl"><a data-link-type="idl" href="#attesterconnection" id="ref-for-attesterconnection">AttesterConnection</a></code>.</p>
|
||
<p>The <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#user-agent" id="ref-for-user-agent②">user agent</a> SHOULD use separate <code class="idl"><a data-link-type="idl" href="#attesterconnection" id="ref-for-attesterconnection①">AttesterConnection</a></code>s if the <code class="idl"><a data-link-type="idl" href="#attesterconnection" id="ref-for-attesterconnection②">AttesterConnection</a></code> stores state in the <a data-link-type="dfn" href="#integrity-verdict-integrity-verdict" id="ref-for-integrity-verdict-integrity-verdict①">Integrity verdict</a> that can be used for cross site tracking.</p>
|
||
<h3 class="heading settled" data-level="3.1" id="attester-tokens"><span class="secno">3.1. </span><span class="content">Token Format</span><a class="self-link" href="#attester-tokens"></a></h3>
|
||
<p><i>Todo</i></p>
|
||
<h3 class="heading settled" data-level="3.2" id="attester-browser-requirements"><span class="secno">3.2. </span><span class="content">Browser Acceptance Requirements</span><a class="self-link" href="#attester-browser-requirements"></a></h3>
|
||
<p><i>Todo</i></p>
|
||
<h3 class="heading settled" data-level="3.3" id="attester-connection"><span class="secno">3.3. </span><span class="content"><code class="idl"><a data-link-type="idl" href="#attesterconnection" id="ref-for-attesterconnection③">AttesterConnection</a></code></span><a class="self-link" href="#attester-connection"></a></h3>
|
||
<pre class="idl highlight def"><c- b>interface</c-> <dfn class="dfn-paneled idl-code" data-dfn-type="interface" data-export id="attesterconnection"><code><c- g>AttesterConnection</c-></code></dfn> {
|
||
<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-ArrayBuffer" id="ref-for-idl-ArrayBuffer"><c- b>ArrayBuffer</c-></a> <dfn class="dfn-paneled idl-code" data-dfn-for="AttesterConnection" data-dfn-type="method" data-export data-lt="getAttestation(contentBinding)" id="dom-attesterconnection-getattestation"><code><c- g>getAttestation</c-></code></dfn>(<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-DOMString" id="ref-for-idl-DOMString"><c- b>DOMString</c-></a> <dfn class="idl-code" data-dfn-for="AttesterConnection/getAttestation(contentBinding)" data-dfn-type="argument" data-export id="dom-attesterconnection-getattestation-contentbinding-contentbinding"><code><c- g>contentBinding</c-></code><a class="self-link" href="#dom-attesterconnection-getattestation-contentbinding-contentbinding"></a></dfn>);
|
||
};
|
||
</pre>
|
||
<dl>
|
||
<dt data-md>getAttestation
|
||
<dd data-md>
|
||
<p>Returns a COSE signed CBOR object as an ArrayBuffer from the <a data-link-type="dfn" href="#attester-attester" id="ref-for-attester-attester②">attester</a> that contains the <a data-link-type="dfn" href="#integrity-verdict-integrity-verdict" id="ref-for-integrity-verdict-integrity-verdict②">Integrity verdict</a>.</p>
|
||
</dl>
|
||
<h2 class="heading settled" data-level="4" id="api"><span class="secno">4. </span><span class="content">Web Environment Integrity API</span><a class="self-link" href="#api"></a></h2>
|
||
<h3 class="heading settled" data-level="4.1" id="extensions-to-navigator"><span class="secno">4.1. </span><span class="content">Extensions to <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/system-state.html#navigator" id="ref-for-navigator">Navigator</a></code></span><a class="self-link" href="#extensions-to-navigator"></a></h3>
|
||
<pre class="idl highlight def">[<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#Exposed" id="ref-for-Exposed"><c- g>Exposed</c-></a>=<c- n>Window</c->]
|
||
<c- b>partial</c-> <c- b>interface</c-> <a class="idl-code" data-link-type="interface" href="https://html.spec.whatwg.org/multipage/system-state.html#navigator" id="ref-for-navigator①"><c- g>Navigator</c-></a> {
|
||
[<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#SecureContext" id="ref-for-SecureContext"><c- g>SecureContext</c-></a>] <a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-promise" id="ref-for-idl-promise"><c- b>Promise</c-></a><<a data-link-type="idl-name" href="#environmentintegrity" id="ref-for-environmentintegrity"><c- n>EnvironmentIntegrity</c-></a>> <a class="idl-code" data-link-type="method" href="#dom-navigator-getenvironmentintegrity" id="ref-for-dom-navigator-getenvironmentintegrity"><c- g>getEnvironmentIntegrity</c-></a>(<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-DOMString" id="ref-for-idl-DOMString①"><c- b>DOMString</c-></a> <dfn class="idl-code" data-dfn-for="Navigator/getEnvironmentIntegrity(contentBinding)" data-dfn-type="argument" data-export id="dom-navigator-getenvironmentintegrity-contentbinding-contentbinding"><code><c- g>contentBinding</c-></code><a class="self-link" href="#dom-navigator-getenvironmentintegrity-contentbinding-contentbinding"></a></dfn>);
|
||
};
|
||
</pre>
|
||
<h4 class="heading settled" data-level="4.1.1" id="navigator-getenvironmentintegrity"><span class="secno">4.1.1. </span><span class="content"><code class="idl"><a data-link-type="idl" href="#dom-navigator-getenvironmentintegrity" id="ref-for-dom-navigator-getenvironmentintegrity①">getEnvironmentIntegrity()</a></code></span><a class="self-link" href="#navigator-getenvironmentintegrity"></a></h4>
|
||
<div class="algorithm" data-algorithm="navigator-getenvironmentintegrity-alg">
|
||
The <a data-link-type="dfn" href="https://infra.spec.whatwg.org/#user-agent" id="ref-for-user-agent③">user agent</a> has the global <dfn class="dfn-paneled" data-dfn-for="attesterConnection" data-dfn-type="dfn" data-noexport id="attesterconnection-attesterconnection">attesterConnection</dfn>, which is
|
||
an <code class="idl"><a data-link-type="idl" href="#attesterconnection" id="ref-for-attesterconnection④">AttesterConnection</a></code> with the <a data-link-type="dfn" href="#attester-attester" id="ref-for-attester-attester③">attester</a>.
|
||
<p>The <dfn class="dfn-paneled idl-code" data-dfn-for="Navigator" data-dfn-type="method" data-export id="dom-navigator-getenvironmentintegrity"><code>getEnvironmentIntegrity(<var>contentBinding</var>)</code></dfn> method, when invoked, runs these steps:</p>
|
||
<ol>
|
||
<li data-md>
|
||
<p>Let <var>promise</var> be <a data-link-type="dfn" href="https://webidl.spec.whatwg.org/#a-new-promise" id="ref-for-a-new-promise">a new promise</a></p>
|
||
<li data-md>
|
||
<p>Run the following steps <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel" id="ref-for-in-parallel">in parallel</a>:</p>
|
||
<ol>
|
||
<li data-md>
|
||
<p>Let <var>environmentIntegrity</var> be a new <code class="idl"><a data-link-type="idl" href="#environmentintegrity" id="ref-for-environmentintegrity①">EnvironmentIntegrity</a></code></p>
|
||
<li data-md>
|
||
<p>Set <var>environmentIntegrity</var>.<code class="idl"><a data-link-type="idl" href="#dom-environmentintegrity-attestationtoken" id="ref-for-dom-environmentintegrity-attestationtoken">attestationToken</a></code> to <a data-link-type="dfn" href="#attesterconnection-attesterconnection" id="ref-for-attesterconnection-attesterconnection">attesterConnection</a>.<a class="idl-code" data-link-type="method" href="#dom-attesterconnection-getattestation" id="ref-for-dom-attesterconnection-getattestation">getAttestation(<var>contentBinding</var>)</a>. If this fails then:</p>
|
||
<ol>
|
||
<li data-md>
|
||
<p><a data-link-type="dfn" href="https://webidl.spec.whatwg.org/#reject" id="ref-for-reject">Reject</a> <var>promise</var> with a <i>TODO</i> <a data-link-type="dfn" href="https://webidl.spec.whatwg.org/#dfn-exception" id="ref-for-dfn-exception">Exception</a></p>
|
||
<li data-md>
|
||
<p>Abort these steps</p>
|
||
</ol>
|
||
<li data-md>
|
||
<p><a data-link-type="dfn" href="https://webidl.spec.whatwg.org/#resolve" id="ref-for-resolve">Resolve</a> <var>promise</var> with <var>environmentIntegrity</var></p>
|
||
</ol>
|
||
<li data-md>
|
||
<p>Return <var>promise</var></p>
|
||
</ol>
|
||
</div>
|
||
<h3 class="heading settled" data-level="4.2" id="environment-integrity"><span class="secno">4.2. </span><span class="content"><code class="idl"><a data-link-type="idl" href="#environmentintegrity" id="ref-for-environmentintegrity②">EnvironmentIntegrity</a></code></span><a class="self-link" href="#environment-integrity"></a></h3>
|
||
<pre class="idl highlight def"><c- b>interface</c-> <dfn class="dfn-paneled idl-code" data-dfn-type="interface" data-export id="environmentintegrity"><code><c- g>EnvironmentIntegrity</c-></code></dfn> {
|
||
<c- b>readonly</c-> <c- b>attribute</c-> <a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-ArrayBuffer" id="ref-for-idl-ArrayBuffer①"><c- b>ArrayBuffer</c-></a> <dfn class="dfn-paneled idl-code" data-dfn-for="EnvironmentIntegrity" data-dfn-type="attribute" data-export data-readonly data-type="ArrayBuffer" id="dom-environmentintegrity-attestationtoken"><code><c- g>attestationToken</c-></code></dfn>;
|
||
<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-DOMString" id="ref-for-idl-DOMString②"><c- b>DOMString</c-></a> <dfn class="idl-code" data-dfn-for="EnvironmentIntegrity" data-dfn-type="method" data-export data-lt="encode()" id="dom-environmentintegrity-encode"><code><c- g>encode</c-></code><a class="self-link" href="#dom-environmentintegrity-encode"></a></dfn>();
|
||
<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-object" id="ref-for-idl-object"><c- b>object</c-></a> <dfn class="idl-code" data-dfn-for="EnvironmentIntegrity" data-dfn-type="method" data-export data-lt="toJSON()" id="dom-environmentintegrity-tojson"><code><c- g>toJSON</c-></code><a class="self-link" href="#dom-environmentintegrity-tojson"></a></dfn>();
|
||
};
|
||
</pre>
|
||
<dl>
|
||
<dt data-md>attestationToken
|
||
<dd data-md>
|
||
<p>The attestation token is a COSE signed CBOR object as an ArrayBuffer from the attester.</p>
|
||
<dt data-md>encode()
|
||
<dd data-md>
|
||
<p>The encode method will return a Base64 string representation of the attestation token.</p>
|
||
<dt data-md>toJSON()
|
||
<dd data-md>
|
||
<p>The toJSON method returns a human readable JSON representation of the attestation token. It will first decode the CBOR object. Useful for local debugging.</p>
|
||
</dl>
|
||
<h2 class="heading settled" data-level="5" id="security-and-privacy"><span class="secno">5. </span><span class="content">Security and privacy considerations</span><a class="self-link" href="#security-and-privacy"></a></h2>
|
||
<h3 class="heading settled" data-level="5.1" id="security"><span class="secno">5.1. </span><span class="content">Security considerations</span><a class="self-link" href="#security"></a></h3>
|
||
<p><i>Todo</i></p>
|
||
<h3 class="heading settled" data-level="5.2" id="privacy"><span class="secno">5.2. </span><span class="content">Privacy considerations</span><a class="self-link" href="#privacy"></a></h3>
|
||
<p><i>Todo</i></p>
|
||
</main>
|
||
<div data-fill-with="conformance">
|
||
<h2 class="no-ref no-num heading settled" id="conformance"><span class="content"> Conformance</span><a class="self-link" href="#conformance"></a></h2>
|
||
<p> Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology.
|
||
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”
|
||
in the normative parts of this document
|
||
are to be interpreted as described in RFC 2119.
|
||
However, for readability,
|
||
these words do not appear in all uppercase letters in this specification. </p>
|
||
<p> All of the text of this specification is normative
|
||
except sections explicitly marked as non-normative, examples, and notes. <a data-link-type="biblio" href="#biblio-rfc2119" title="Key words for use in RFCs to Indicate Requirement Levels">[RFC2119]</a> </p>
|
||
<p> Examples in this specification are introduced with the words “for example”
|
||
or are set apart from the normative text with <code>class="example"</code>, like this: </p>
|
||
<div class="example" id="example-example"><a class="self-link" href="#example-example"></a> This is an example of an informative example. </div>
|
||
<p> Informative notes begin with the word “Note”
|
||
and are set apart from the normative text with <code>class="note"</code>, like this: </p>
|
||
<p class="note" role="note"> Note, this is an informative note.</p>
|
||
</div>
|
||
<script>
|
||
(function() {
|
||
"use strict";
|
||
var collapseSidebarText = '<span aria-hidden="true">←</span> '
|
||
+ '<span>Collapse Sidebar</span>';
|
||
var expandSidebarText = '<span aria-hidden="true">→</span> '
|
||
+ '<span>Pop Out Sidebar</span>';
|
||
var tocJumpText = '<span aria-hidden="true">↑</span> '
|
||
+ '<span>Jump to Table of Contents</span>';
|
||
|
||
var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
|
||
var autoToggle = function(e){ toggleSidebar(e.matches) };
|
||
if(sidebarMedia.addListener) {
|
||
sidebarMedia.addListener(autoToggle);
|
||
}
|
||
|
||
function toggleSidebar(on) {
|
||
if (on == undefined) {
|
||
on = !document.body.classList.contains('toc-sidebar');
|
||
}
|
||
|
||
/* Don’t scroll to compensate for the ToC if we’re above it already. */
|
||
var headY = 0;
|
||
var head = document.querySelector('.head');
|
||
if (head) {
|
||
// terrible approx of "top of ToC"
|
||
headY += head.offsetTop + head.offsetHeight;
|
||
}
|
||
var skipScroll = window.scrollY < headY;
|
||
|
||
var toggle = document.getElementById('toc-toggle');
|
||
var tocNav = document.getElementById('toc');
|
||
if (on) {
|
||
var tocHeight = tocNav.offsetHeight;
|
||
document.body.classList.add('toc-sidebar');
|
||
document.body.classList.remove('toc-inline');
|
||
toggle.innerHTML = collapseSidebarText;
|
||
if (!skipScroll) {
|
||
window.scrollBy(0, 0 - tocHeight);
|
||
}
|
||
tocNav.focus();
|
||
sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
|
||
}
|
||
else {
|
||
document.body.classList.add('toc-inline');
|
||
document.body.classList.remove('toc-sidebar');
|
||
toggle.innerHTML = expandSidebarText;
|
||
if (!skipScroll) {
|
||
window.scrollBy(0, tocNav.offsetHeight);
|
||
}
|
||
if (toggle.matches(':hover')) {
|
||
/* Unfocus button when not using keyboard navigation,
|
||
because I don’t know where else to send the focus. */
|
||
toggle.blur();
|
||
}
|
||
}
|
||
}
|
||
|
||
function createSidebarToggle() {
|
||
/* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
|
||
var toggle = document.createElement('a');
|
||
/* This should probably be a button, but appearance isn’t standards-track.*/
|
||
toggle.id = 'toc-toggle';
|
||
toggle.class = 'toc-toggle';
|
||
toggle.href = '#toc';
|
||
toggle.innerHTML = collapseSidebarText;
|
||
|
||
sidebarMedia.addListener(autoToggle);
|
||
var toggler = function(e) {
|
||
e.preventDefault();
|
||
sidebarMedia.removeListener(autoToggle); // persist explicit off states
|
||
toggleSidebar();
|
||
return false;
|
||
}
|
||
toggle.addEventListener('click', toggler, false);
|
||
|
||
|
||
/* Get <nav id=toc-nav>, or make it if we don’t have one. */
|
||
var tocNav = document.getElementById('toc-nav');
|
||
if (!tocNav) {
|
||
tocNav = document.createElement('p');
|
||
tocNav.id = 'toc-nav';
|
||
/* Prepend for better keyboard navigation */
|
||
document.body.insertBefore(tocNav, document.body.firstChild);
|
||
}
|
||
/* While we’re at it, make sure we have a Jump to Toc link. */
|
||
var tocJump = document.getElementById('toc-jump');
|
||
if (!tocJump) {
|
||
tocJump = document.createElement('a');
|
||
tocJump.id = 'toc-jump';
|
||
tocJump.href = '#toc';
|
||
tocJump.innerHTML = tocJumpText;
|
||
tocNav.appendChild(tocJump);
|
||
}
|
||
|
||
tocNav.appendChild(toggle);
|
||
}
|
||
|
||
var toc = document.getElementById('toc');
|
||
if (toc) {
|
||
createSidebarToggle();
|
||
toggleSidebar(sidebarMedia.matches);
|
||
|
||
/* If the sidebar has been manually opened and is currently overlaying the text
|
||
(window too small for the MQ to add the margin to body),
|
||
then auto-close the sidebar once you click on something in there. */
|
||
toc.addEventListener('click', function(e) {
|
||
if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
|
||
toggleSidebar(false);
|
||
}
|
||
}, false);
|
||
}
|
||
else {
|
||
console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
|
||
}
|
||
|
||
/* Wrap tables in case they overflow */
|
||
var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
|
||
var numTables = tables.length;
|
||
for (var i = 0; i < numTables; i++) {
|
||
var table = tables[i];
|
||
var wrapper = document.createElement('div');
|
||
wrapper.className = 'overlarge';
|
||
table.parentNode.insertBefore(wrapper, table);
|
||
wrapper.appendChild(table);
|
||
}
|
||
|
||
})();
|
||
</script>
|
||
<h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2>
|
||
<h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
|
||
<ul class="index">
|
||
<li><a href="#dom-environmentintegrity-attestationtoken">attestationToken</a><span>, in § 4.2</span>
|
||
<li><a href="#attester-attester">attester</a><span>, in § 3</span>
|
||
<li><a href="#attesterconnection">AttesterConnection</a><span>, in § 3.3</span>
|
||
<li><a href="#attesterconnection-attesterconnection">attesterConnection</a><span>, in § 4.1.1</span>
|
||
<li><a href="#dom-environmentintegrity-encode">encode()</a><span>, in § 4.2</span>
|
||
<li><a href="#environmentintegrity">EnvironmentIntegrity</a><span>, in § 4.2</span>
|
||
<li><a href="#dom-attesterconnection-getattestation">getAttestation(contentBinding)</a><span>, in § 3.3</span>
|
||
<li><a href="#dom-navigator-getenvironmentintegrity">getEnvironmentIntegrity(contentBinding)</a><span>, in § 4.1.1</span>
|
||
<li><a href="#integrity-verdict-integrity-verdict">Integrity verdict</a><span>, in § 3</span>
|
||
<li><a href="#dom-environmentintegrity-tojson">toJSON()</a><span>, in § 4.2</span>
|
||
<li><a href="#web-environment-web-environment">web environment</a><span>, in § 2</span>
|
||
</ul>
|
||
<h3 class="no-num no-ref heading settled" id="index-defined-elsewhere"><span class="content">Terms defined by reference</span><a class="self-link" href="#index-defined-elsewhere"></a></h3>
|
||
<ul class="index">
|
||
<li>
|
||
<a data-link-type="biblio">[HTML]</a> defines the following terms:
|
||
<ul>
|
||
<li><span class="dfn-paneled" id="be0c27b2">Navigator</span>
|
||
<li><span class="dfn-paneled" id="a72449dd">in parallel</span>
|
||
</ul>
|
||
<li>
|
||
<a data-link-type="biblio">[INFRA]</a> defines the following terms:
|
||
<ul>
|
||
<li><span class="dfn-paneled" id="6d19ac93">user agent</span>
|
||
</ul>
|
||
<li>
|
||
<a data-link-type="biblio">[WEBIDL]</a> defines the following terms:
|
||
<ul>
|
||
<li><span class="dfn-paneled" id="2f8afbfe">ArrayBuffer</span>
|
||
<li><span class="dfn-paneled" id="8855a9aa">DOMString</span>
|
||
<li><span class="dfn-paneled" id="889e932f">Exposed</span>
|
||
<li><span class="dfn-paneled" id="bdbd19d1">Promise</span>
|
||
<li><span class="dfn-paneled" id="b75bb3bd">SecureContext</span>
|
||
<li><span class="dfn-paneled" id="dacde8b5">a new promise</span>
|
||
<li><span class="dfn-paneled" id="cd787c3f">exception</span>
|
||
<li><span class="dfn-paneled" id="efd1ec5d">object</span>
|
||
<li><span class="dfn-paneled" id="b262501e">reject</span>
|
||
<li><span class="dfn-paneled" id="3b90bdcd">resolve</span>
|
||
</ul>
|
||
</ul>
|
||
<h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
|
||
<h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3>
|
||
<dl>
|
||
<dt id="biblio-html">[HTML]
|
||
<dd>Anne van Kesteren; et al. <a href="https://html.spec.whatwg.org/multipage/"><cite>HTML Standard</cite></a>. Living Standard. URL: <a href="https://html.spec.whatwg.org/multipage/">https://html.spec.whatwg.org/multipage/</a>
|
||
<dt id="biblio-infra">[INFRA]
|
||
<dd>Anne van Kesteren; Domenic Denicola. <a href="https://infra.spec.whatwg.org/"><cite>Infra Standard</cite></a>. Living Standard. URL: <a href="https://infra.spec.whatwg.org/">https://infra.spec.whatwg.org/</a>
|
||
<dt id="biblio-rfc2119">[RFC2119]
|
||
<dd>S. Bradner. <a href="https://datatracker.ietf.org/doc/html/rfc2119"><cite>Key words for use in RFCs to Indicate Requirement Levels</cite></a>. March 1997. Best Current Practice. URL: <a href="https://datatracker.ietf.org/doc/html/rfc2119">https://datatracker.ietf.org/doc/html/rfc2119</a>
|
||
<dt id="biblio-webidl">[WEBIDL]
|
||
<dd>Edgar Chen; Timothy Gu. <a href="https://webidl.spec.whatwg.org/"><cite>Web IDL Standard</cite></a>. Living Standard. URL: <a href="https://webidl.spec.whatwg.org/">https://webidl.spec.whatwg.org/</a>
|
||
</dl>
|
||
<h2 class="no-num no-ref heading settled" id="idl-index"><span class="content">IDL Index</span><a class="self-link" href="#idl-index"></a></h2>
|
||
<pre class="idl highlight def"><c- b>interface</c-> <a href="#attesterconnection"><code><c- g>AttesterConnection</c-></code></a> {
|
||
<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-ArrayBuffer"><c- b>ArrayBuffer</c-></a> <a href="#dom-attesterconnection-getattestation"><code><c- g>getAttestation</c-></code></a>(<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-DOMString"><c- b>DOMString</c-></a> <a href="#dom-attesterconnection-getattestation-contentbinding-contentbinding"><code><c- g>contentBinding</c-></code></a>);
|
||
};
|
||
|
||
[<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#Exposed"><c- g>Exposed</c-></a>=<c- n>Window</c->]
|
||
<c- b>partial</c-> <c- b>interface</c-> <a class="idl-code" data-link-type="interface" href="https://html.spec.whatwg.org/multipage/system-state.html#navigator"><c- g>Navigator</c-></a> {
|
||
[<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#SecureContext"><c- g>SecureContext</c-></a>] <a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-promise"><c- b>Promise</c-></a><<a data-link-type="idl-name" href="#environmentintegrity"><c- n>EnvironmentIntegrity</c-></a>> <a class="idl-code" data-link-type="method" href="#dom-navigator-getenvironmentintegrity"><c- g>getEnvironmentIntegrity</c-></a>(<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-DOMString"><c- b>DOMString</c-></a> <a href="#dom-navigator-getenvironmentintegrity-contentbinding-contentbinding"><code><c- g>contentBinding</c-></code></a>);
|
||
};
|
||
|
||
<c- b>interface</c-> <a href="#environmentintegrity"><code><c- g>EnvironmentIntegrity</c-></code></a> {
|
||
<c- b>readonly</c-> <c- b>attribute</c-> <a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-ArrayBuffer"><c- b>ArrayBuffer</c-></a> <a data-readonly data-type="ArrayBuffer" href="#dom-environmentintegrity-attestationtoken"><code><c- g>attestationToken</c-></code></a>;
|
||
<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-DOMString"><c- b>DOMString</c-></a> <a href="#dom-environmentintegrity-encode"><code><c- g>encode</c-></code></a>();
|
||
<a class="idl-code" data-link-type="interface" href="https://webidl.spec.whatwg.org/#idl-object"><c- b>object</c-></a> <a href="#dom-environmentintegrity-tojson"><code><c- g>toJSON</c-></code></a>();
|
||
};
|
||
|
||
</pre>
|
||
<script>/* Boilerplate: script-dfn-panel */
|
||
"use strict";
|
||
{
|
||
const dfnsJson = window.dfnsJson || {};
|
||
|
||
function genDfnPanel({dfnID, url, dfnText, refSections, external}) {
|
||
return mk.aside({
|
||
class: "dfn-panel",
|
||
id: `infopanel-for-${dfnID}`,
|
||
"data-for": dfnID,
|
||
"aria-labelled-by":`infopaneltitle-for-${dfnID}`,
|
||
},
|
||
mk.span({id:`infopaneltitle-for-${dfnID}`, style:"display:none"},
|
||
`Info about the '${dfnText}' ${external?"external":""} reference.`),
|
||
mk.a({href:url}, url),
|
||
mk.b({}, "Referenced in:"),
|
||
mk.ul({},
|
||
...refSections.map(section=>
|
||
mk.li({},
|
||
...section.refs.map((ref, refI)=>
|
||
[
|
||
mk.a({
|
||
href: `#${ref.id}`
|
||
},
|
||
(refI == 0) ? section.title : `(${refI + 1})`
|
||
),
|
||
" ",
|
||
]
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
function genAllDfnPanels() {
|
||
for(const panelData of Object.values(window.dfnpanelData)) {
|
||
const dfnID = panelData.dfnID;
|
||
const dfn = document.getElementById(dfnID);
|
||
if(!dfn) {
|
||
console.log(`Can't find dfn#${dfnID}.`, panelData);
|
||
} else {
|
||
const panel = genDfnPanel(panelData);
|
||
append(document.body, panel);
|
||
insertDfnPopupAction(dfn, panel)
|
||
}
|
||
}
|
||
}
|
||
|
||
document.addEventListener("DOMContentLoaded", ()=>{
|
||
genAllDfnPanels();
|
||
|
||
// Add popup behavior to all dfns to show the corresponding dfn-panel.
|
||
var dfns = queryAll('.dfn-paneled');
|
||
for(let dfn of dfns) { ; }
|
||
|
||
document.body.addEventListener("click", (e) => {
|
||
// If not handled already, just hide all dfn panels.
|
||
hideAllDfnPanels();
|
||
});
|
||
})
|
||
|
||
|
||
function hideAllDfnPanels() {
|
||
// Turn off any currently "on" or "activated" panels.
|
||
queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(el=>hideDfnPanel(el));
|
||
}
|
||
|
||
function showDfnPanel(dfnPanel, dfn) {
|
||
hideAllDfnPanels(); // Only display one at this time.
|
||
dfn.setAttribute("aria-expanded", "true");
|
||
dfnPanel.classList.add("on");
|
||
dfnPanel.style.left = "5px";
|
||
dfnPanel.style.top = "0px";
|
||
const panelRect = dfnPanel.getBoundingClientRect();
|
||
const panelWidth = panelRect.right - panelRect.left;
|
||
if (panelRect.right > document.body.scrollWidth) {
|
||
// Panel's overflowing the screen.
|
||
// Just drop it below the dfn and flip it rightward instead.
|
||
// This still wont' fix things if the screen is *really* wide,
|
||
// but fixing that's a lot harder without 'anchor()'.
|
||
dfnPanel.style.top = "1.5em";
|
||
dfnPanel.style.left = "auto";
|
||
dfnPanel.style.right = "0px";
|
||
}
|
||
}
|
||
|
||
function pinDfnPanel(dfnPanel) {
|
||
// Switch it to "activated" state, which pins it.
|
||
dfnPanel.classList.add("activated");
|
||
dfnPanel.style.left = null;
|
||
dfnPanel.style.top = null;
|
||
}
|
||
|
||
function hideDfnPanel(dfnPanel, dfn) {
|
||
if(!dfn) {
|
||
dfn = document.getElementById(dfnPanel.getAttribute("data-for"));
|
||
}
|
||
dfn.setAttribute("aria-expanded", "false")
|
||
dfnPanel.classList.remove("on");
|
||
dfnPanel.classList.remove("activated");
|
||
}
|
||
|
||
function toggleDfnPanel(dfnPanel, dfn) {
|
||
if(dfnPanel.classList.contains("on")) {
|
||
hideDfnPanel(dfnPanel, dfn);
|
||
} else {
|
||
showDfnPanel(dfnPanel, dfn);
|
||
}
|
||
}
|
||
|
||
function insertDfnPopupAction(dfn, dfnPanel) {
|
||
// Find dfn panel
|
||
const panelWrapper = document.createElement('span');
|
||
panelWrapper.appendChild(dfnPanel);
|
||
panelWrapper.style.position = "relative";
|
||
panelWrapper.style.height = "0px";
|
||
dfn.insertAdjacentElement("afterend", panelWrapper);
|
||
dfn.setAttribute('role', 'button');
|
||
dfn.setAttribute('aria-expanded', 'false')
|
||
dfn.tabIndex = 0;
|
||
dfn.classList.add('has-dfn-panel');
|
||
dfn.addEventListener('click', (event) => {
|
||
showDfnPanel(dfnPanel, dfn);
|
||
event.stopPropagation();
|
||
});
|
||
dfn.addEventListener('keypress', (event) => {
|
||
const kc = event.keyCode;
|
||
// 32->Space, 13->Enter
|
||
if(kc == 32 || kc == 13) {
|
||
toggleDfnPanel(dfnPanel, dfn);
|
||
event.stopPropagation();
|
||
event.preventDefault();
|
||
}
|
||
});
|
||
|
||
dfnPanel.addEventListener('click', (event) => {
|
||
if (event.target.nodeName == 'A') {
|
||
pinDfnPanel(dfnPanel);
|
||
}
|
||
event.stopPropagation();
|
||
});
|
||
|
||
dfnPanel.addEventListener('keydown', (event) => {
|
||
if(event.keyCode == 27) { // Escape key
|
||
hideDfnPanel(dfnPanel, dfn);
|
||
event.stopPropagation();
|
||
event.preventDefault();
|
||
}
|
||
})
|
||
}
|
||
}
|
||
</script>
|
||
<script>/* Boilerplate: script-dfn-panel */
|
||
"use strict";
|
||
{
|
||
const dfnsJson = window.dfnsJson || {};
|
||
|
||
function genDfnPanel({dfnID, url, dfnText, refSections, external}) {
|
||
return mk.aside({
|
||
class: "dfn-panel",
|
||
id: `infopanel-for-${dfnID}`,
|
||
"data-for": dfnID,
|
||
"aria-labelled-by":`infopaneltitle-for-${dfnID}`,
|
||
},
|
||
mk.span({id:`infopaneltitle-for-${dfnID}`, style:"display:none"},
|
||
`Info about the '${dfnText}' ${external?"external":""} reference.`),
|
||
mk.a({href:url}, url),
|
||
mk.b({}, "Referenced in:"),
|
||
mk.ul({},
|
||
...refSections.map(section=>
|
||
mk.li({},
|
||
...section.refs.map((ref, refI)=>
|
||
[
|
||
mk.a({
|
||
href: `#${ref.id}`
|
||
},
|
||
(refI == 0) ? section.title : `(${refI + 1})`
|
||
),
|
||
" ",
|
||
]
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
function genAllDfnPanels() {
|
||
for(const panelData of Object.values(window.dfnpanelData)) {
|
||
const dfnID = panelData.dfnID;
|
||
const dfn = document.getElementById(dfnID);
|
||
if(!dfn) {
|
||
console.log(`Can't find dfn#${dfnID}.`, panelData);
|
||
} else {
|
||
const panel = genDfnPanel(panelData);
|
||
append(document.body, panel);
|
||
insertDfnPopupAction(dfn, panel)
|
||
}
|
||
}
|
||
}
|
||
|
||
document.addEventListener("DOMContentLoaded", ()=>{
|
||
genAllDfnPanels();
|
||
|
||
// Add popup behavior to all dfns to show the corresponding dfn-panel.
|
||
var dfns = queryAll('.dfn-paneled');
|
||
for(let dfn of dfns) { ; }
|
||
|
||
document.body.addEventListener("click", (e) => {
|
||
// If not handled already, just hide all dfn panels.
|
||
hideAllDfnPanels();
|
||
});
|
||
})
|
||
|
||
|
||
function hideAllDfnPanels() {
|
||
// Turn off any currently "on" or "activated" panels.
|
||
queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(el=>hideDfnPanel(el));
|
||
}
|
||
|
||
function showDfnPanel(dfnPanel, dfn) {
|
||
hideAllDfnPanels(); // Only display one at this time.
|
||
dfn.setAttribute("aria-expanded", "true");
|
||
dfnPanel.classList.add("on");
|
||
dfnPanel.style.left = "5px";
|
||
dfnPanel.style.top = "0px";
|
||
const panelRect = dfnPanel.getBoundingClientRect();
|
||
const panelWidth = panelRect.right - panelRect.left;
|
||
if (panelRect.right > document.body.scrollWidth) {
|
||
// Panel's overflowing the screen.
|
||
// Just drop it below the dfn and flip it rightward instead.
|
||
// This still wont' fix things if the screen is *really* wide,
|
||
// but fixing that's a lot harder without 'anchor()'.
|
||
dfnPanel.style.top = "1.5em";
|
||
dfnPanel.style.left = "auto";
|
||
dfnPanel.style.right = "0px";
|
||
}
|
||
}
|
||
|
||
function pinDfnPanel(dfnPanel) {
|
||
// Switch it to "activated" state, which pins it.
|
||
dfnPanel.classList.add("activated");
|
||
dfnPanel.style.left = null;
|
||
dfnPanel.style.top = null;
|
||
}
|
||
|
||
function hideDfnPanel(dfnPanel, dfn) {
|
||
if(!dfn) {
|
||
dfn = document.getElementById(dfnPanel.getAttribute("data-for"));
|
||
}
|
||
dfn.setAttribute("aria-expanded", "false")
|
||
dfnPanel.classList.remove("on");
|
||
dfnPanel.classList.remove("activated");
|
||
}
|
||
|
||
function toggleDfnPanel(dfnPanel, dfn) {
|
||
if(dfnPanel.classList.contains("on")) {
|
||
hideDfnPanel(dfnPanel, dfn);
|
||
} else {
|
||
showDfnPanel(dfnPanel, dfn);
|
||
}
|
||
}
|
||
|
||
function insertDfnPopupAction(dfn, dfnPanel) {
|
||
// Find dfn panel
|
||
const panelWrapper = document.createElement('span');
|
||
panelWrapper.appendChild(dfnPanel);
|
||
panelWrapper.style.position = "relative";
|
||
panelWrapper.style.height = "0px";
|
||
dfn.insertAdjacentElement("afterend", panelWrapper);
|
||
dfn.setAttribute('role', 'button');
|
||
dfn.setAttribute('aria-expanded', 'false')
|
||
dfn.tabIndex = 0;
|
||
dfn.classList.add('has-dfn-panel');
|
||
dfn.addEventListener('click', (event) => {
|
||
showDfnPanel(dfnPanel, dfn);
|
||
event.stopPropagation();
|
||
});
|
||
dfn.addEventListener('keypress', (event) => {
|
||
const kc = event.keyCode;
|
||
// 32->Space, 13->Enter
|
||
if(kc == 32 || kc == 13) {
|
||
toggleDfnPanel(dfnPanel, dfn);
|
||
event.stopPropagation();
|
||
event.preventDefault();
|
||
}
|
||
});
|
||
|
||
dfnPanel.addEventListener('click', (event) => {
|
||
if (event.target.nodeName == 'A') {
|
||
pinDfnPanel(dfnPanel);
|
||
}
|
||
event.stopPropagation();
|
||
});
|
||
|
||
dfnPanel.addEventListener('keydown', (event) => {
|
||
if(event.keyCode == 27) { // Escape key
|
||
hideDfnPanel(dfnPanel, dfn);
|
||
event.stopPropagation();
|
||
event.preventDefault();
|
||
}
|
||
})
|
||
}
|
||
}
|
||
</script>
|
||
<script>/* Boilerplate: script-dfn-panel-json */
|
||
window.dfnpanelData = {};
|
||
window.dfnpanelData['be0c27b2'] = {"dfnID": "be0c27b2", "url": "https://html.spec.whatwg.org/multipage/system-state.html#navigator", "dfnText": "Navigator", "refSections": [{"refs": [{"id": "ref-for-navigator"}, {"id": "ref-for-navigator\u2460"}], "title": "4.1. Extensions to Navigator"}], "external": true};
|
||
window.dfnpanelData['a72449dd'] = {"dfnID": "a72449dd", "url": "https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel", "dfnText": "in parallel", "refSections": [{"refs": [{"id": "ref-for-in-parallel"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": true};
|
||
window.dfnpanelData['6d19ac93'] = {"dfnID": "6d19ac93", "url": "https://infra.spec.whatwg.org/#user-agent", "dfnText": "user agent", "refSections": [{"refs": [{"id": "ref-for-user-agent"}, {"id": "ref-for-user-agent\u2460"}, {"id": "ref-for-user-agent\u2461"}], "title": "3. Attesters"}, {"refs": [{"id": "ref-for-user-agent\u2462"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": true};
|
||
window.dfnpanelData['2f8afbfe'] = {"dfnID": "2f8afbfe", "url": "https://webidl.spec.whatwg.org/#idl-ArrayBuffer", "dfnText": "ArrayBuffer", "refSections": [{"refs": [{"id": "ref-for-idl-ArrayBuffer"}], "title": "3.3. AttesterConnection"}, {"refs": [{"id": "ref-for-idl-ArrayBuffer\u2460"}], "title": "4.2. EnvironmentIntegrity"}], "external": true};
|
||
window.dfnpanelData['8855a9aa'] = {"dfnID": "8855a9aa", "url": "https://webidl.spec.whatwg.org/#idl-DOMString", "dfnText": "DOMString", "refSections": [{"refs": [{"id": "ref-for-idl-DOMString"}], "title": "3.3. AttesterConnection"}, {"refs": [{"id": "ref-for-idl-DOMString\u2460"}], "title": "4.1. Extensions to Navigator"}, {"refs": [{"id": "ref-for-idl-DOMString\u2461"}], "title": "4.2. EnvironmentIntegrity"}], "external": true};
|
||
window.dfnpanelData['889e932f'] = {"dfnID": "889e932f", "url": "https://webidl.spec.whatwg.org/#Exposed", "dfnText": "Exposed", "refSections": [{"refs": [{"id": "ref-for-Exposed"}], "title": "4.1. Extensions to Navigator"}], "external": true};
|
||
window.dfnpanelData['bdbd19d1'] = {"dfnID": "bdbd19d1", "url": "https://webidl.spec.whatwg.org/#idl-promise", "dfnText": "Promise", "refSections": [{"refs": [{"id": "ref-for-idl-promise"}], "title": "4.1. Extensions to Navigator"}], "external": true};
|
||
window.dfnpanelData['b75bb3bd'] = {"dfnID": "b75bb3bd", "url": "https://webidl.spec.whatwg.org/#SecureContext", "dfnText": "SecureContext", "refSections": [{"refs": [{"id": "ref-for-SecureContext"}], "title": "4.1. Extensions to Navigator"}], "external": true};
|
||
window.dfnpanelData['dacde8b5'] = {"dfnID": "dacde8b5", "url": "https://webidl.spec.whatwg.org/#a-new-promise", "dfnText": "a new promise", "refSections": [{"refs": [{"id": "ref-for-a-new-promise"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": true};
|
||
window.dfnpanelData['cd787c3f'] = {"dfnID": "cd787c3f", "url": "https://webidl.spec.whatwg.org/#dfn-exception", "dfnText": "exception", "refSections": [{"refs": [{"id": "ref-for-dfn-exception"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": true};
|
||
window.dfnpanelData['efd1ec5d'] = {"dfnID": "efd1ec5d", "url": "https://webidl.spec.whatwg.org/#idl-object", "dfnText": "object", "refSections": [{"refs": [{"id": "ref-for-idl-object"}], "title": "4.2. EnvironmentIntegrity"}], "external": true};
|
||
window.dfnpanelData['b262501e'] = {"dfnID": "b262501e", "url": "https://webidl.spec.whatwg.org/#reject", "dfnText": "reject", "refSections": [{"refs": [{"id": "ref-for-reject"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": true};
|
||
window.dfnpanelData['3b90bdcd'] = {"dfnID": "3b90bdcd", "url": "https://webidl.spec.whatwg.org/#resolve", "dfnText": "resolve", "refSections": [{"refs": [{"id": "ref-for-resolve"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": true};
|
||
window.dfnpanelData['web-environment-web-environment'] = {"dfnID": "web-environment-web-environment", "url": "#web-environment-web-environment", "dfnText": "web environment", "refSections": [{"refs": [{"id": "ref-for-web-environment-web-environment"}], "title": "3. Attesters"}], "external": false};
|
||
window.dfnpanelData['attester-attester'] = {"dfnID": "attester-attester", "url": "#attester-attester", "dfnText": "attester", "refSections": [{"refs": [{"id": "ref-for-attester-attester"}, {"id": "ref-for-attester-attester\u2460"}], "title": "3. Attesters"}, {"refs": [{"id": "ref-for-attester-attester\u2461"}], "title": "3.3. AttesterConnection"}, {"refs": [{"id": "ref-for-attester-attester\u2462"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": false};
|
||
window.dfnpanelData['integrity-verdict-integrity-verdict'] = {"dfnID": "integrity-verdict-integrity-verdict", "url": "#integrity-verdict-integrity-verdict", "dfnText": "Integrity verdict", "refSections": [{"refs": [{"id": "ref-for-integrity-verdict-integrity-verdict"}, {"id": "ref-for-integrity-verdict-integrity-verdict\u2460"}], "title": "3. Attesters"}, {"refs": [{"id": "ref-for-integrity-verdict-integrity-verdict\u2461"}], "title": "3.3. AttesterConnection"}], "external": false};
|
||
window.dfnpanelData['attesterconnection'] = {"dfnID": "attesterconnection", "url": "#attesterconnection", "dfnText": "AttesterConnection", "refSections": [{"refs": [{"id": "ref-for-attesterconnection"}, {"id": "ref-for-attesterconnection\u2460"}, {"id": "ref-for-attesterconnection\u2461"}], "title": "3. Attesters"}, {"refs": [{"id": "ref-for-attesterconnection\u2462"}], "title": "3.3. AttesterConnection"}, {"refs": [{"id": "ref-for-attesterconnection\u2463"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": false};
|
||
window.dfnpanelData['dom-attesterconnection-getattestation'] = {"dfnID": "dom-attesterconnection-getattestation", "url": "#dom-attesterconnection-getattestation", "dfnText": "getAttestation", "refSections": [{"refs": [{"id": "ref-for-dom-attesterconnection-getattestation"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": false};
|
||
window.dfnpanelData['attesterconnection-attesterconnection'] = {"dfnID": "attesterconnection-attesterconnection", "url": "#attesterconnection-attesterconnection", "dfnText": "attesterConnection", "refSections": [{"refs": [{"id": "ref-for-attesterconnection-attesterconnection"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": false};
|
||
window.dfnpanelData['dom-navigator-getenvironmentintegrity'] = {"dfnID": "dom-navigator-getenvironmentintegrity", "url": "#dom-navigator-getenvironmentintegrity", "dfnText": "getEnvironmentIntegrity(contentBinding)", "refSections": [{"refs": [{"id": "ref-for-dom-navigator-getenvironmentintegrity"}], "title": "4.1. Extensions to Navigator"}, {"refs": [{"id": "ref-for-dom-navigator-getenvironmentintegrity\u2460"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": false};
|
||
window.dfnpanelData['environmentintegrity'] = {"dfnID": "environmentintegrity", "url": "#environmentintegrity", "dfnText": "EnvironmentIntegrity", "refSections": [{"refs": [{"id": "ref-for-environmentintegrity"}], "title": "4.1. Extensions to Navigator"}, {"refs": [{"id": "ref-for-environmentintegrity\u2460"}], "title": "4.1.1. getEnvironmentIntegrity()"}, {"refs": [{"id": "ref-for-environmentintegrity\u2461"}], "title": "4.2. EnvironmentIntegrity"}], "external": false};
|
||
window.dfnpanelData['dom-environmentintegrity-attestationtoken'] = {"dfnID": "dom-environmentintegrity-attestationtoken", "url": "#dom-environmentintegrity-attestationtoken", "dfnText": "attestationToken", "refSections": [{"refs": [{"id": "ref-for-dom-environmentintegrity-attestationtoken"}], "title": "4.1.1. getEnvironmentIntegrity()"}], "external": false};
|
||
</script>
|
||
<script>/* Boilerplate: script-dom-helper */
|
||
function query(sel) { return document.querySelector(sel); }
|
||
|
||
function queryAll(sel) { return [...document.querySelectorAll(sel)]; }
|
||
|
||
function iter(obj) {
|
||
if(!obj) return [];
|
||
var it = obj[Symbol.iterator];
|
||
if(it) return it;
|
||
return Object.entries(obj);
|
||
}
|
||
|
||
function mk(tagname, attrs, ...children) {
|
||
const el = document.createElement(tagname);
|
||
for(const [k,v] of iter(attrs)) {
|
||
if(k.slice(0,3) == "_on") {
|
||
const eventName = k.slice(3);
|
||
el.addEventListener(eventName, v);
|
||
} else if(k[0] == "_") {
|
||
// property, not attribute
|
||
el[k.slice(1)] = v;
|
||
} else {
|
||
if(v === false || v == null) {
|
||
continue;
|
||
} else if(v === true) {
|
||
el.setAttribute(k, "");
|
||
continue;
|
||
} else {
|
||
el.setAttribute(k, v);
|
||
}
|
||
}
|
||
}
|
||
append(el, children);
|
||
return el;
|
||
}
|
||
|
||
/* Create shortcuts for every known HTML element */
|
||
[
|
||
"a",
|
||
"abbr",
|
||
"acronym",
|
||
"address",
|
||
"applet",
|
||
"area",
|
||
"article",
|
||
"aside",
|
||
"audio",
|
||
"b",
|
||
"base",
|
||
"basefont",
|
||
"bdo",
|
||
"big",
|
||
"blockquote",
|
||
"body",
|
||
"br",
|
||
"button",
|
||
"canvas",
|
||
"caption",
|
||
"center",
|
||
"cite",
|
||
"code",
|
||
"col",
|
||
"colgroup",
|
||
"datalist",
|
||
"dd",
|
||
"del",
|
||
"details",
|
||
"dfn",
|
||
"dialog",
|
||
"div",
|
||
"dl",
|
||
"dt",
|
||
"em",
|
||
"embed",
|
||
"fieldset",
|
||
"figcaption",
|
||
"figure",
|
||
"font",
|
||
"footer",
|
||
"form",
|
||
"frame",
|
||
"frameset",
|
||
"head",
|
||
"header",
|
||
"h1",
|
||
"h2",
|
||
"h3",
|
||
"h4",
|
||
"h5",
|
||
"h6",
|
||
"hr",
|
||
"html",
|
||
"i",
|
||
"iframe",
|
||
"img",
|
||
"input",
|
||
"ins",
|
||
"kbd",
|
||
"label",
|
||
"legend",
|
||
"li",
|
||
"link",
|
||
"main",
|
||
"map",
|
||
"mark",
|
||
"meta",
|
||
"meter",
|
||
"nav",
|
||
"nobr",
|
||
"noscript",
|
||
"object",
|
||
"ol",
|
||
"optgroup",
|
||
"option",
|
||
"output",
|
||
"p",
|
||
"param",
|
||
"pre",
|
||
"progress",
|
||
"q",
|
||
"s",
|
||
"samp",
|
||
"script",
|
||
"section",
|
||
"select",
|
||
"small",
|
||
"source",
|
||
"span",
|
||
"strike",
|
||
"strong",
|
||
"style",
|
||
"sub",
|
||
"summary",
|
||
"sup",
|
||
"table",
|
||
"tbody",
|
||
"td",
|
||
"template",
|
||
"textarea",
|
||
"tfoot",
|
||
"th",
|
||
"thead",
|
||
"time",
|
||
"title",
|
||
"tr",
|
||
"u",
|
||
"ul",
|
||
"var",
|
||
"video",
|
||
"wbr",
|
||
"xmp",
|
||
].forEach(tagname=>{
|
||
mk[tagname] = (...args) => mk(tagname, ...args);
|
||
});
|
||
|
||
function* nodesFromChildList(children) {
|
||
for(const child of children.flat(Infinity)) {
|
||
if(child instanceof Node) {
|
||
yield child;
|
||
} else {
|
||
yield new Text(child);
|
||
}
|
||
}
|
||
}
|
||
function append(el, ...children) {
|
||
for(const child of nodesFromChildList(children)) {
|
||
if(el instanceof Node) el.appendChild(child);
|
||
else el.push(child);
|
||
}
|
||
return el;
|
||
}
|
||
|
||
function insertAfter(el, ...children) {
|
||
for(const child of nodesFromChildList(children)) {
|
||
el.parentNode.insertBefore(child, el.nextSibling);
|
||
}
|
||
return el;
|
||
}
|
||
|
||
function clearContents(el) {
|
||
el.innerHTML = "";
|
||
return el;
|
||
}
|
||
|
||
function parseHTML(markup) {
|
||
if(markup.toLowerCase().trim().indexOf('<!doctype') === 0) {
|
||
const doc = document.implementation.createHTMLDocument("");
|
||
doc.documentElement.innerHTML = markup;
|
||
return doc;
|
||
} else {
|
||
const el = mk.template({});
|
||
el.innerHTML = markup;
|
||
return el.content;
|
||
}
|
||
}
|
||
</script>
|
||
<script>/* Boilerplate: script-var-click-highlighting */
|
||
/*
|
||
Color-choosing design:
|
||
|
||
Colors are ordered by goodness.
|
||
Each color has a usage count (initially zero).
|
||
Each variable has a last-used color.
|
||
|
||
* If the var has a last-used color, and that color's usage is 0,
|
||
return that color.
|
||
* Otherwise, return the lowest-indexed color with the lowest usage.
|
||
Increment the color's usage and set it as the last-used color
|
||
for that var.
|
||
* On unclicking, decrement usage of the color.
|
||
*/
|
||
"use strict";
|
||
{
|
||
document.addEventListener("click", e=>{
|
||
if(e.target.nodeName == "VAR") {
|
||
highlightSameAlgoVars(e.target);
|
||
}
|
||
});
|
||
const indexCounts = new Map();
|
||
const indexNames = new Map();
|
||
function highlightSameAlgoVars(v) {
|
||
// Find the algorithm container.
|
||
let algoContainer = null;
|
||
let searchEl = v;
|
||
while(algoContainer == null && searchEl != document.body) {
|
||
searchEl = searchEl.parentNode;
|
||
if(searchEl.hasAttribute("data-algorithm")) {
|
||
algoContainer = searchEl;
|
||
}
|
||
}
|
||
|
||
// Not highlighting document-global vars,
|
||
// too likely to be unrelated.
|
||
if(algoContainer == null) return;
|
||
|
||
const algoName = algoContainer.getAttribute("data-algorithm");
|
||
const varName = getVarName(v);
|
||
const addClass = !v.classList.contains("selected");
|
||
let highlightClass = null;
|
||
if(addClass) {
|
||
const index = chooseHighlightIndex(algoName, varName);
|
||
indexCounts.get(algoName)[index] += 1;
|
||
indexNames.set(algoName+"///"+varName, index);
|
||
highlightClass = nameFromIndex(index);
|
||
} else {
|
||
const index = previousHighlightIndex(algoName, varName);
|
||
indexCounts.get(algoName)[index] -= 1;
|
||
highlightClass = nameFromIndex(index);
|
||
}
|
||
|
||
// Find all same-name vars, and toggle their class appropriately.
|
||
for(const el of algoContainer.querySelectorAll("var")) {
|
||
if(getVarName(el) == varName) {
|
||
el.classList.toggle("selected", addClass);
|
||
el.classList.toggle(highlightClass, addClass);
|
||
}
|
||
}
|
||
}
|
||
function getVarName(el) {
|
||
return el.textContent.replace(/(\s|\xa0)+/, " ").trim();
|
||
}
|
||
function chooseHighlightIndex(algoName, varName) {
|
||
let indexes = null;
|
||
if(indexCounts.has(algoName)) {
|
||
indexes = indexCounts.get(algoName);
|
||
} else {
|
||
// 7 classes right now
|
||
indexes = [0,0,0,0,0,0,0];
|
||
indexCounts.set(algoName, indexes);
|
||
}
|
||
|
||
// If the element was recently unclicked,
|
||
// *and* that color is still unclaimed,
|
||
// give it back the same color.
|
||
const lastIndex = previousHighlightIndex(algoName, varName);
|
||
if(indexes[lastIndex] === 0) return lastIndex;
|
||
|
||
// Find the earliest index with the lowest count.
|
||
const minCount = Math.min.apply(null, indexes);
|
||
let index = null;
|
||
for(var i = 0; i < indexes.length; i++) {
|
||
if(indexes[i] == minCount) {
|
||
return i;
|
||
}
|
||
}
|
||
}
|
||
function previousHighlightIndex(algoName, varName) {
|
||
return indexNames.get(algoName+"///"+varName);
|
||
}
|
||
function nameFromIndex(index) {
|
||
return "selected" + index;
|
||
}
|
||
}
|
||
</script> |