├── .nvmrc ├── docs └── CNAME ├── src ├── style │ ├── common │ │ ├── link-color.scss │ │ ├── heading-color.scss │ │ ├── body-font-family.scss │ │ ├── code-font-family.scss │ │ ├── media-queries │ │ │ ├── max-width-for-small-screens.scss │ │ │ ├── on-very-small-screens.scss │ │ │ ├── on-small-screens.scss │ │ │ └── on-regular-screens.scss │ │ ├── heading-selector.scss │ │ ├── heading-font-family.scss │ │ ├── heavy-shadow.scss │ │ ├── mild-shadow.scss │ │ ├── faux-inline-button.scss │ │ ├── default-example-user-input-shading.scss │ │ ├── example-user-input-shading.scss │ │ └── faux-button.scss │ ├── writing-conventions │ │ ├── image.scss │ │ ├── video.scss │ │ ├── parenthetical.scss │ │ ├── link.scss │ │ ├── emphasis-and-italics.scss │ │ ├── heavy-shadow.scss │ │ ├── footnote-block.scss │ │ ├── highlight.scss │ │ ├── footnote-reference.scss │ │ ├── line-block.scss │ │ ├── inline-quote.scss │ │ ├── thematic-break.scss │ │ ├── ordered-and-unordered-lists.scss │ │ ├── description-list.scss │ │ ├── blockquote.scss │ │ ├── revealable.scss │ │ ├── heading.scss │ │ ├── table.scss │ │ ├── example-user-input.scss │ │ └── code-blocks-and-inline-code.scss │ ├── editor.scss │ ├── app.scss │ ├── syncing-animation.scss │ ├── tab-list.scss │ ├── layout.scss │ ├── documentation-container.scss │ ├── table-of-contents.scss │ └── lib │ │ └── codemirror.css ├── getElementById.js ├── upSettings.js ├── repeat.js ├── isOnIosDevice.js ├── onLinkClick.js ├── debounce.js ├── isTotallyHidden.js ├── throttle.js ├── layout │ └── index.hbs ├── configureTableOfContentsVisibility.js ├── app.js ├── addScrollSyncingEventListeners.js ├── configureEditor.js └── content │ └── documentation.up ├── postcss.config.js ├── README.md ├── LICENSE ├── package.json └── webpack.config.js /.nvmrc: -------------------------------------------------------------------------------- 1 | v8.17.0 2 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | tryup.org 2 | -------------------------------------------------------------------------------- /src/style/common/link-color.scss: -------------------------------------------------------------------------------- 1 | $link-color: #579; 2 | -------------------------------------------------------------------------------- /src/style/common/heading-color.scss: -------------------------------------------------------------------------------- 1 | $heading-color: black; 2 | -------------------------------------------------------------------------------- /src/style/writing-conventions/image.scss: -------------------------------------------------------------------------------- 1 | img { max-width: 100% } 2 | -------------------------------------------------------------------------------- /src/style/writing-conventions/video.scss: -------------------------------------------------------------------------------- 1 | video { max-width: 100% } 2 | -------------------------------------------------------------------------------- /src/getElementById.js: -------------------------------------------------------------------------------- 1 | export default document.getElementById.bind(document) 2 | -------------------------------------------------------------------------------- /src/style/common/body-font-family.scss: -------------------------------------------------------------------------------- 1 | $body-font-family: system-ui, sans-serif; 2 | -------------------------------------------------------------------------------- /src/style/common/code-font-family.scss: -------------------------------------------------------------------------------- 1 | $code-font-family: Menlo, Consolas, monospace; 2 | -------------------------------------------------------------------------------- /src/style/common/media-queries/max-width-for-small-screens.scss: -------------------------------------------------------------------------------- 1 | $max-width-for-small-screens: 980px -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer') 4 | ] 5 | } -------------------------------------------------------------------------------- /src/style/common/heading-selector.scss: -------------------------------------------------------------------------------- 1 | $heading-selector: 'h1, h2, h3, h4, h5, h6, [role="heading"]'; 2 | -------------------------------------------------------------------------------- /src/style/common/heading-font-family.scss: -------------------------------------------------------------------------------- 1 | @import 'body-font-family'; 2 | 3 | $heading-font-family: $body-font-family; 4 | -------------------------------------------------------------------------------- /src/upSettings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parsing: { createSourceMap: true }, 3 | rendering: { idPrefix: '' } 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The [website](https://tryup.org) for [Up](https://github.com/start/up), a markup language for writing structured documents in plain text. 2 | -------------------------------------------------------------------------------- /src/style/common/heavy-shadow.scss: -------------------------------------------------------------------------------- 1 | @mixin heavy-shadow { 2 | box-shadow: 3 | 0 3px 6px rgba(0, 0, 0, 0.16), 4 | 0 3px 6px rgba(0, 0, 0, 0.23); 5 | } 6 | -------------------------------------------------------------------------------- /src/style/common/mild-shadow.scss: -------------------------------------------------------------------------------- 1 | @mixin mild-shadow { 2 | box-shadow: 3 | 0 1px 3px rgba(0, 0, 0, 0.12), 4 | 0 1px 2px rgba(0, 0, 0, 0.24); 5 | } 6 | -------------------------------------------------------------------------------- /src/style/writing-conventions/parenthetical.scss: -------------------------------------------------------------------------------- 1 | small { 2 | font-size: 100%; 3 | opacity: .5; 4 | } 5 | 6 | .up-square-brackets { font-style: italic } 7 | -------------------------------------------------------------------------------- /src/style/writing-conventions/link.scss: -------------------------------------------------------------------------------- 1 | @import '../common/link-color'; 2 | 3 | a { 4 | color: $link-color; 5 | 6 | &:hover { text-decoration: none; } 7 | } 8 | -------------------------------------------------------------------------------- /src/style/writing-conventions/emphasis-and-italics.scss: -------------------------------------------------------------------------------- 1 | i, em, caption { 2 | i, em { 3 | display: inline-block; 4 | transform: skewX(-20deg); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/style/common/media-queries/on-very-small-screens.scss: -------------------------------------------------------------------------------- 1 | @mixin on-very-small-screens { 2 | @media only screen and (max-width: 420px) { 3 | @content; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/style/writing-conventions/heavy-shadow.scss: -------------------------------------------------------------------------------- 1 | @mixin heavy-shadow { 2 | box-shadow: 3 | 0 3px 6px rgba(0, 0, 0, 0.16), 4 | 0 3px 6px rgba(0, 0, 0, 0.23); 5 | } 6 | -------------------------------------------------------------------------------- /src/repeat.js: -------------------------------------------------------------------------------- 1 | // Returns a new string consisting of `count` copies of `text`. 2 | export default function repeat(text, count) { 3 | return new Array(count + 1).join(text) 4 | } 5 | -------------------------------------------------------------------------------- /src/isOnIosDevice.js: -------------------------------------------------------------------------------- 1 | // Returns `true` on an iPhone, iPad, or iPod. 2 | export default function isOnIosDevice() { 3 | return ['iPhone', 'iPad', 'iPod'].indexOf(navigator.platform) !== -1 4 | } 5 | -------------------------------------------------------------------------------- /src/style/writing-conventions/footnote-block.scss: -------------------------------------------------------------------------------- 1 | .up-footnotes { 2 | font-size: 85%; 3 | 4 | dt { 5 | font-weight: normal; 6 | 7 | a:before { content: '↑' } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/style/common/media-queries/on-small-screens.scss: -------------------------------------------------------------------------------- 1 | @import 'max-width-for-small-screens'; 2 | 3 | @mixin on-small-screens { 4 | @media only screen and (max-width: $max-width-for-small-screens) { 5 | @content; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/style/writing-conventions/highlight.scss: -------------------------------------------------------------------------------- 1 | mark { 2 | background-color: yellow; 3 | padding: (1em / 16); 4 | 5 | mark { 6 | background-color: gold; 7 | 8 | mark { background-color: orange } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/style/common/media-queries/on-regular-screens.scss: -------------------------------------------------------------------------------- 1 | @import 'max-width-for-small-screens'; 2 | 3 | @mixin on-regular-screens { 4 | @media only screen and (min-width: 1 + $max-width-for-small-screens) { 5 | @content; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/style/writing-conventions/footnote-reference.scss: -------------------------------------------------------------------------------- 1 | .up-footnote-reference a { 2 | font-size: 110%; 3 | margin-left: (1em / 8); 4 | text-decoration: none; 5 | 6 | &:before { content: '[' } 7 | &:after { content: ']' } 8 | } 9 | -------------------------------------------------------------------------------- /src/style/common/faux-inline-button.scss: -------------------------------------------------------------------------------- 1 | @import 'faux-button'; 2 | 3 | @mixin faux-inline-button { 4 | @include faux-button; 5 | 6 | display: inline; 7 | font-size: 65%; 8 | margin: 0 5px; 9 | padding: 4px 12px 3px 12px; 10 | } 11 | -------------------------------------------------------------------------------- /src/style/editor.scss: -------------------------------------------------------------------------------- 1 | @import 'common/code-font-family'; 2 | 3 | .CodeMirror { 4 | font-size: 14px; 5 | line-height: 1.3; 6 | font-family: $code-font-family !important; 7 | 8 | .CodeMirror-scroll { -webkit-overflow-scrolling: touch } 9 | } 10 | -------------------------------------------------------------------------------- /src/style/writing-conventions/line-block.scss: -------------------------------------------------------------------------------- 1 | .up-lines { 2 | text-align: center; 3 | 4 | // Without some extra margin, consecutive line blocks appear merged together. 5 | + .up-lines { margin-top: 20px } 6 | 7 | > div { margin-bottom: 5px } 8 | } 9 | -------------------------------------------------------------------------------- /src/style/writing-conventions/inline-quote.scss: -------------------------------------------------------------------------------- 1 | q { 2 | margin: 0 (1em / 16); 3 | quotes: '“' '”' "‘" "’"; 4 | } 5 | 6 | q:before, 7 | q:after { font-family: serif } 8 | 9 | q:before { content: open-quote } 10 | q:after { content: close-quote } 11 | -------------------------------------------------------------------------------- /src/style/app.scss: -------------------------------------------------------------------------------- 1 | @import '~normalize.css'; 2 | @import 'layout'; 3 | @import 'editor'; 4 | @import 'tab-list'; 5 | @import 'documentation-container'; 6 | @import 'syncing-animation'; 7 | @import 'lib/codemirror'; 8 | 9 | html { scroll-behavior: smooth; } 10 | -------------------------------------------------------------------------------- /src/style/syncing-animation.scss: -------------------------------------------------------------------------------- 1 | @mixin dirty { 2 | opacity: 0.5; 3 | transition: 0.5s; 4 | } 5 | 6 | @keyframes clean { 7 | from { @include dirty } 8 | to { opacity: 1 } 9 | } 10 | 11 | .dirty, { @include dirty } 12 | .clean { animation: 0.2s clean } 13 | -------------------------------------------------------------------------------- /src/style/tab-list.scss: -------------------------------------------------------------------------------- 1 | @import 'common/faux-button'; 2 | 3 | #tab-container { 4 | display: flex; 5 | justify-content: center; 6 | 7 | span[role="tab"] { 8 | @include faux-button; 9 | 10 | &[aria-selected="true"] { display: none } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/style/common/default-example-user-input-shading.scss: -------------------------------------------------------------------------------- 1 | @import 'example-user-input-shading'; 2 | 3 | @mixin default-example-user-input-shading { 4 | @include example-user-input-shading( 5 | $text-color: #444, 6 | $border-color: #aaa, 7 | $shadow-color: rgba(#0d0d0d, 0.2)); 8 | } 9 | -------------------------------------------------------------------------------- /src/style/writing-conventions/thematic-break.scss: -------------------------------------------------------------------------------- 1 | hr { 2 | border: 0; 3 | padding-bottom: 30px; 4 | text-align: center; 5 | } 6 | 7 | hr:after { 8 | color: #ccc; 9 | content: '☆ ☆ ☆'; 10 | font-size: 10px; 11 | } 12 | 13 | @media speech, braille { 14 | hr:after { content: none } 15 | } 16 | -------------------------------------------------------------------------------- /src/onLinkClick.js: -------------------------------------------------------------------------------- 1 | export default function onLinkClick(container, callback) { 2 | container.addEventListener('click', event => { 3 | let clickedElement = event.target 4 | 5 | do { 6 | if (clickedElement.tagName === 'A') { 7 | callback(event) 8 | return 9 | } 10 | } while (clickedElement = clickedElement.parentNode) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /src/debounce.js: -------------------------------------------------------------------------------- 1 | // Returns a version of `callback` that won't execute until `delay` 2 | // milliseconds after it was most recently invoked. 3 | export default function debounce(callback, delay) { 4 | let timeoutHandle 5 | 6 | return (...args) => { 7 | clearTimeout(timeoutHandle) 8 | 9 | timeoutHandle = 10 | setTimeout(() => callback(...args), delay) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/style/writing-conventions/ordered-and-unordered-lists.scss: -------------------------------------------------------------------------------- 1 | // Without some extra margin, consecutive lists appear merged together. 2 | ol + ol, 3 | ul + ul { margin-top: 40px } 4 | 5 | // Most list items contain just a single line (technically a paragraph). 6 | // 7 | // Unless we shrink the margins of that single inner paragraph, those 8 | // list items appear a little too spaced out. 9 | li p:only-child { margin: .5em 0 } -------------------------------------------------------------------------------- /src/style/common/example-user-input-shading.scss: -------------------------------------------------------------------------------- 1 | @mixin example-user-input-shading($text-color, $border-color, $shadow-color) { 2 | $bottom-edge-length: (1em / 4); 3 | $side-edge-length: (1em / 8); 4 | 5 | border-color: $border-color; 6 | box-shadow: 7 | 0 $bottom-edge-length 0 $shadow-color, 8 | $side-edge-length $bottom-edge-length 0 $shadow-color, 9 | -$side-edge-length $bottom-edge-length 0 $shadow-color; 10 | color: $text-color; 11 | } 12 | -------------------------------------------------------------------------------- /src/style/writing-conventions/description-list.scss: -------------------------------------------------------------------------------- 1 | @import '../common/heading-color'; 2 | @import '../common/heading-font-family'; 3 | 4 | dl { 5 | margin-bottom: 25px; 6 | 7 | dl { margin-bottom: 0 } 8 | 9 | dt { 10 | color: $heading-color; 11 | font-family: $heading-font-family; 12 | font-weight: bold; 13 | } 14 | 15 | dd { margin-left: 20px } 16 | 17 | // Without some extra spacing, consecutive description lists appear merged together. 18 | + dl { margin-top: 45px } 19 | } 20 | -------------------------------------------------------------------------------- /src/style/common/faux-button.scss: -------------------------------------------------------------------------------- 1 | @import 'mild-shadow'; 2 | 3 | @mixin faux-button { 4 | @include mild-shadow; 5 | 6 | background-color: #c00; 7 | border-radius: 3px; 8 | color: white; 9 | cursor: pointer; 10 | display: inline-block; 11 | font-size: 75%; 12 | margin: 10px 0; 13 | padding: 7px 12px 5px 12px; 14 | text-transform: uppercase; 15 | white-space: nowrap; 16 | user-select: none; 17 | 18 | &:hover { 19 | background: #b00; 20 | } 21 | 22 | &:active { 23 | background: #a00; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/isTotallyHidden.js: -------------------------------------------------------------------------------- 1 | // Returns `true` if an element is hidden (directly or indirectly) via 2 | // `display: none`. 3 | // 4 | // NOTE: This function does not work for elements whose `position` is `fixed`; it 5 | // will always return `true`. 6 | export default function isTotallyHidden(element) { 7 | // If an element's `display` (or the `display` of an ancestor) is set to `none`, 8 | // its `offsetParent` returns `null`. 9 | // 10 | // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent 11 | // 12 | // We don't check `style.display` directly, because it returns an empty string if 13 | // it wasn't set by JavaScript. 14 | return !element.offsetParent; 15 | } 16 | -------------------------------------------------------------------------------- /src/style/writing-conventions/blockquote.scss: -------------------------------------------------------------------------------- 1 | @mixin nested-blockquoted-colors($nesting-level) { 2 | $amount-to-darken: $nesting-level * 4%; 3 | 4 | border-color: darken($blockquote-indent-color, $amount-to-darken); 5 | background-color: darken($blockquote-bg-color, $amount-to-darken); 6 | } 7 | 8 | $blockquote-bg-color: #fcfcfc; 9 | $blockquote-indent-color: #ddd; 10 | 11 | blockquote { 12 | border-left: 20px solid $blockquote-indent-color; 13 | background-color: $blockquote-bg-color; 14 | margin: 15px 0; 15 | padding: 5px 20px; 16 | 17 | blockquote { 18 | @include nested-blockquoted-colors(1); 19 | 20 | blockquote { 21 | @include nested-blockquoted-colors(2); 22 | 23 | blockquote { 24 | @include nested-blockquoted-colors(3) 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/style/layout.scss: -------------------------------------------------------------------------------- 1 | @import 'common/media-queries/on-regular-screens'; 2 | @import 'common/media-queries/on-small-screens'; 3 | 4 | 5 | #tab-container { 6 | align-items: center; 7 | display: flex; 8 | height: 44px; 9 | } 10 | 11 | $editor-width: 510px; 12 | 13 | #documentation-container { 14 | margin-left: $editor-width; 15 | padding: 0 15px; 16 | 17 | #table-of-contents { display: none } 18 | 19 | #documentation, 20 | #table-of-contents { 21 | margin: 0 auto; 22 | max-width: 580px; 23 | overflow-x: hidden; 24 | } 25 | } 26 | 27 | @include on-regular-screens { 28 | #editor-container { 29 | border-right: 1px solid #aaa; 30 | position: fixed; 31 | left: 0; 32 | top: 0; 33 | width: $editor-width; 34 | 35 | .CodeMirror { height: 100vh; } 36 | } 37 | } 38 | 39 | @include on-small-screens { 40 | #editor-container { display: none } 41 | #documentation-container { margin-left: 0 } 42 | } 43 | -------------------------------------------------------------------------------- /src/style/writing-conventions/revealable.scss: -------------------------------------------------------------------------------- 1 | @import 'common/faux-button'; 2 | @import 'common/faux-inline-button'; 3 | 4 | @keyframes reveal { 5 | 0% { opacity: 1; } 6 | 30% { opacity: .5 } 7 | 100% { opacity: 1 } 8 | } 9 | 10 | // Inline revealables and revealable blocks 11 | .up-revealable { 12 | > label { @include faux-button } 13 | 14 | > input[type="radio"] { 15 | display: none; 16 | 17 | ~ span, 18 | ~ div { display: none } 19 | 20 | &.up-hide:checked + label { display: none } 21 | 22 | &.up-reveal:checked { 23 | + label { display: none } 24 | 25 | ~ span, 26 | ~ div { animation: 1s reveal } 27 | 28 | ~ span { display: inline } 29 | ~ div { display: block } 30 | } 31 | } 32 | 33 | > div { margin-left: 20px } 34 | } 35 | 36 | // Inline revealables 37 | span.up-revealable > label { @include faux-inline-button } 38 | 39 | // Revealable blocks 40 | div.up-revealable > label { @include faux-button } 41 | -------------------------------------------------------------------------------- /src/style/writing-conventions/heading.scss: -------------------------------------------------------------------------------- 1 | @import '../common/heading-selector'; 2 | @import '../common/heading-color'; 3 | @import '../common/heading-font-family'; 4 | 5 | 6 | #{$heading-selector} { 7 | color: $heading-color; 8 | font-family: $heading-font-family; 9 | line-height: 1.5; 10 | overflow-x: auto; 11 | padding-top: 10px; 12 | } 13 | 14 | h1 { 15 | font-size: 180%; 16 | padding-bottom: 15px; 17 | text-align: center; 18 | } 19 | 20 | h2 { font-size: 140% } 21 | h3 { font-size: 120% } 22 | h4 { font-size: 110% } 23 | h5 { font-size: 100% } 24 | h6 { font-size: 90% } 25 | 26 | // Headings with levels 7 and higher are rendered as `
` 27 | // elements with an `aria-level` attribute equal to their level. 28 | [role="heading"] { 29 | font-size: 60%; 30 | margin: 1.5em 0; 31 | } 32 | 33 | [aria-level="7"] { font-size: 85% } 34 | [aria-level="8"] { font-size: 80% } 35 | [aria-level="9"] { font-size: 75% } 36 | [aria-level="10"] { font-size: 70% } 37 | -------------------------------------------------------------------------------- /src/throttle.js: -------------------------------------------------------------------------------- 1 | // Returns a version of `callback` that won't execute more than 2 | // once per `cooldown` period (in milliseconds). 3 | // 4 | // If the returned function is invoked during the cooldown period, 5 | // it will execute as soon as the cooldown period ends. 6 | export default function throttle(callback, cooldown) { 7 | let isInCooldown = false, wasInvokedDuringCooldown = false 8 | 9 | return (...args) => { 10 | if (isInCooldown) { 11 | wasInvokedDuringCooldown = true 12 | } else { 13 | isInCooldown = true 14 | executeAndScheduleEndOfCooldown() 15 | } 16 | 17 | function executeAndScheduleEndOfCooldown() { 18 | callback(...args) 19 | setTimeout(onEndOfCooldown, cooldown) 20 | } 21 | 22 | function onEndOfCooldown() { 23 | if (wasInvokedDuringCooldown) { 24 | executeAndScheduleEndOfCooldown() 25 | wasInvokedDuringCooldown = false 26 | } else { 27 | isInCooldown = false 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/style/writing-conventions/table.scss: -------------------------------------------------------------------------------- 1 | @import '../common/heading-color'; 2 | @import '../common/heading-font-family'; 3 | @import 'common/media-queries/on-very-small-screens'; 4 | 5 | 6 | table { 7 | border-collapse: collapse; 8 | margin: 20px 0; 9 | 10 | @include on-very-small-screens { 11 | font-size: 80%; 12 | } 13 | 14 | caption { font-style: italic } 15 | 16 | tbody tr { 17 | &:hover { 18 | td { background: #ddd } 19 | } 20 | 21 | &:nth-child(even) { 22 | td { background-color: #eee } 23 | 24 | &:hover { 25 | td { background-color: #ccc } 26 | td { border-color: #999 } 27 | } 28 | } 29 | } 30 | 31 | td, th { 32 | padding: 10px; 33 | border: 1px solid #bbb; 34 | 35 | &.up-numeric { text-align: right } 36 | &[colspan] { text-align: center } 37 | } 38 | 39 | th { 40 | border: 0; 41 | color: $heading-color; 42 | font-family: $heading-font-family; 43 | 44 | &[scope="row"] { text-align: right } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/style/writing-conventions/example-user-input.scss: -------------------------------------------------------------------------------- 1 | @import '../common/body-font-family'; 2 | @import '../common/link-color'; 3 | @import '../common/example-user-input-shading'; 4 | @import '../common/default-example-user-input-shading'; 5 | 6 | // This is mostly taken from Stackoverflow's `` styling. 7 | kbd { 8 | @include default-example-user-input-shading; 9 | 10 | border-radius: (1em / 4); 11 | border-style: solid; 12 | border-width: (1em / 8); 13 | display: inline-block; 14 | font-family: $body-font-family; 15 | font-size: 70%; 16 | line-height: 1.4; 17 | margin: 0 .1em; 18 | padding: .1em .6em; 19 | text-shadow: 0 (1em / 10) 0 white; 20 | white-space: nowrap; 21 | } 22 | 23 | // We don't need to worry about removing the underline for 24 | // example input within links, because `display: inline-block` 25 | // above takes care of that for us. 26 | a kbd { 27 | @include example-user-input-shading( 28 | $text-color: $link-color, 29 | $border-color: $link-color, 30 | $shadow-color: rgba($link-color, 0.3)); 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Daniel Miller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/style/writing-conventions/code-blocks-and-inline-code.scss: -------------------------------------------------------------------------------- 1 | @import '../common/code-font-family'; 2 | @import '../common/heavy-shadow'; 3 | @import '../common/mild-shadow'; 4 | 5 | // Inline code and code blocks 6 | pre, code { 7 | background: #234; 8 | color: white; 9 | font-family: $code-font-family; 10 | font-size: 100% * (7 / 8); 11 | } 12 | 13 | .up-inline-code { 14 | @include mild-shadow; 15 | 16 | border-radius: (1em / 8); 17 | font-weight: normal; 18 | margin: 0 (1em / 16); 19 | padding: 0 .2em; 20 | white-space: pre; 21 | } 22 | 23 | // Inline code within links 24 | // 25 | // Links are already underlined, but we want the underline 26 | // to be the same color as the code itself. 27 | a code { text-decoration: underline } 28 | a:hover code { text-decoration: none; } 29 | 30 | // Code blocks 31 | pre { 32 | @include heavy-shadow; 33 | 34 | border-radius: (3em / 16); 35 | line-height: 1.5; 36 | margin: 20px 0; 37 | overflow-x: auto; 38 | padding: 7px 9px; 39 | 40 | @include on-very-small-screens { 41 | font-size: 85%; 42 | line-height: 1.4; 43 | } 44 | } 45 | 46 | pre > code { 47 | box-shadow: none; 48 | border-radius: 0; 49 | padding: 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/style/documentation-container.scss: -------------------------------------------------------------------------------- 1 | @import 'common/body-font-family'; 2 | 3 | #documentation-container { 4 | font: 1em/1.6 $body-font-family; 5 | 6 | @import 'table-of-contents'; 7 | 8 | @import 'writing-conventions/blockquote.scss'; 9 | @import 'writing-conventions/code-blocks-and-inline-code.scss'; 10 | @import 'writing-conventions/description-list.scss'; 11 | @import 'writing-conventions/emphasis-and-italics.scss'; 12 | @import 'writing-conventions/example-user-input.scss'; 13 | @import 'writing-conventions/footnote-reference.scss'; 14 | @import 'writing-conventions/footnote-block.scss'; 15 | @import 'writing-conventions/image.scss'; 16 | @import 'writing-conventions/heading.scss'; 17 | @import 'writing-conventions/highlight.scss'; 18 | @import 'writing-conventions/inline-quote.scss'; 19 | @import 'writing-conventions/line-block.scss'; 20 | @import 'writing-conventions/link.scss'; 21 | @import 'writing-conventions/ordered-and-unordered-lists'; 22 | @import 'writing-conventions/parenthetical.scss'; 23 | @import 'writing-conventions/revealable.scss'; 24 | @import 'writing-conventions/table.scss'; 25 | @import 'writing-conventions/thematic-break.scss'; 26 | @import 'writing-conventions/video.scss'; 27 | } 28 | -------------------------------------------------------------------------------- /src/layout/index.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | What’s Up? 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | Show table of contents 15 | 16 | 17 | Hide table of contents 18 | 19 |
20 | 23 |
24 | {{{ htmlWebpackPlugin.options.documentationHtml }}} 25 |
26 |
27 | 28 |
29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "tryup.org", 4 | "version": "0.0.0", 5 | "description": "The website for [Up](https://github.com/start/up), a markup language for writing structured content in plain text.", 6 | "scripts": { 7 | "dev": "webpack-dev-server", 8 | "build": "rm -f docs/{index.html,*.js} && webpack" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/start/tryup.org.git" 13 | }, 14 | "author": "Daniel Miller ", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/start/tryup.org/issues" 18 | }, 19 | "homepage": "https://tryup.org", 20 | "devDependencies": { 21 | "@babel/core": "7.5.5", 22 | "@babel/preset-env": "7.5.5", 23 | "autoprefixer": "9.6.1", 24 | "babel-loader": "8.0.6", 25 | "codemirror": "5.48.4", 26 | "css-loader": "3.2.0", 27 | "handlebars": "4.1.2", 28 | "handlebars-loader": "1.7.1", 29 | "html-webpack-plugin": "3.2.0", 30 | "node-sass": "4.12.0", 31 | "normalize.css": "8.0.1", 32 | "postcss-loader": "3.0.0", 33 | "raw-loader": "3.1.0", 34 | "sass-loader": "7.3.1", 35 | "style-loader": "1.0.0", 36 | "@xcvz/up": "1.0.1", 37 | "webpack": "4.39.3", 38 | "webpack-cli": "3.3.7", 39 | "webpack-dev-server": "3.8.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const fs = require('fs') 3 | const Up = require('@xcvz/up') 4 | const upSettings = require('./src/upSettings') 5 | const path = require('path') 6 | 7 | const documentationMarkup = 8 | fs.readFileSync(fromSourceDir('content/documentation.up'), 'utf-8') 9 | 10 | const renderedUp = 11 | Up.parseAndRenderWithTableOfContents(documentationMarkup, upSettings) 12 | 13 | const outputDir = path.resolve('./docs'); 14 | 15 | module.exports = { 16 | entry: fromSourceDir('app.js'), 17 | output: { 18 | path: outputDir, 19 | filename: 'bundle-[hash].js' 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /.js$/, 25 | use: { 26 | loader: 'babel-loader', 27 | options: { 28 | presets: ['@babel/preset-env'] 29 | } 30 | }, 31 | exclude: /node_modules/, 32 | }, 33 | { 34 | test: /\.css$/, 35 | use: ["style-loader", "css-loader", "postcss-loader"] 36 | }, 37 | { 38 | test: /\.scss$/, 39 | use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"] 40 | }, 41 | { 42 | test: /\.hbs$/, 43 | use: 'handlebars-loader' 44 | }, 45 | { 46 | test: /\.up$/, 47 | use: 'raw-loader', 48 | } 49 | ], 50 | }, 51 | plugins: [ 52 | new HtmlWebpackPlugin({ 53 | template: fromSourceDir('layout/index.hbs'), 54 | documentationHtml: renderedUp.documentHtml, 55 | tableOfContentsHtml: renderedUp.tableOfContentsHtml, 56 | inject: 'head' 57 | }) 58 | ], 59 | devServer: { 60 | contentBase: outputDir, 61 | compress: true, 62 | port: 9000, 63 | open: true 64 | } 65 | } 66 | 67 | 68 | function fromSourceDir(pathAndFilename) { 69 | return path.resolve('src', pathAndFilename) 70 | } 71 | -------------------------------------------------------------------------------- /src/configureTableOfContentsVisibility.js: -------------------------------------------------------------------------------- 1 | import getElementById from './getElementById' 2 | import onLinkClick from './onLinkClick' 3 | 4 | 5 | export default function configureTableOfContentsVisibility(documentationTab, tableOfContentsTab) { 6 | configureTab({ tab: documentationTab, otherTab: tableOfContentsTab }) 7 | configureTab({ tab: tableOfContentsTab, otherTab: documentationTab }) 8 | 9 | // When the user clicks on a table of contents entry, we hide the 10 | // table of contents. 11 | onLinkClick(getAssociatedTabPanel(tableOfContentsTab), event => { 12 | const { tagName } = event.target 13 | 14 | // However, if the user clicks a revealable convention's "reveal" 15 | // button within a table of contents entry, we want the table of 16 | // contents to remain visible. 17 | // 18 | // Each "reveal" button is actually a