diff --git a/docs/css/access-nri.css b/docs/css/access-nri.css index 1d9602ed0..2673debff 100644 --- a/docs/css/access-nri.css +++ b/docs/css/access-nri.css @@ -54,10 +54,9 @@ --md-typeset-kbd-color: rgb(39, 39, 39); /* keyboard key background ( tag) */ --md-typeset-kbd-accent-color: rgb(126, 126, 126, .16); /* keyboard key inner border ( tag) */ --md-typeset-kbd-border-color: rgb(30, 30, 30); /* text as keyboard outer border ( tag) */ - --navigation-borders: var(--md-default-fg-color--lighter); /* Border of cards */ - --navigation-borders-lighter: rgba(var(--default-fg-color),.2); /* Lighter border of cards */ - --navigation-borders-lightest: var(--md-default-fg-color--lightest); /* Lightest color for left border of navigation and toc */ - --md-typeset-table-color: var(--navigation-borders); /* table borders ( tag) */ + --navigation-borders: #115D9750; /* Left border on the toc and navigation */ + --card-borders: var(--md-primary-fg-color--dark); /* Borders of cards */ + --md-typeset-table-color: var(--card-borders); /* table borders (
tag) */ --md-admonition-fg-color: var(--md-typeset-color); /* Main text warnings */ --md-admonition-bg-color: var(--md-default-bg-color); /* Background warnings */ --md-footer-fg-color: var(--md-primary-bg-color); /* footer text (not much used) */ @@ -72,7 +71,11 @@ --card-shadows: #00000075; /* Shadows on cards and other elements */ --card-shadows-hover: #00000090; /* Shadows hover on cards and other elements */ --img-background: #FFFFFF; /* Background for transparent images */ - --shadow-hover-background: rgba(29, 28, 28, 0.185) /* Shadow Background on hover */ + --shadow-hover-background: rgba(29, 28, 28, 0.185); /* Shadow Background on hover */ + --terminal-animation-directory: var(--nri-green); + --terminal-animation-buttons: var(--nri-orange); + --terminal-animation-buttons-hover: var(--nri-dark-blue); + } [data-md-color-scheme="custom-light"] { @@ -102,7 +105,7 @@ --md-accent-bg-color: var(--nri-orange); /* back to top button text hover */ --md-accent-bg-color--light: #115D97B0; --md-code-fg-color: rgb(33, 36, 44); /* code element text */ - --md-code-bg-color: #c3c3c3; /* code element background */ + --md-code-bg-color: #dedede; /* code element background */ --md-code-hl-color: rgba(255,255,0,.5); --md-code-hl-number-color: #d52a2a; --md-code-hl-special-color: #db1457; @@ -124,10 +127,9 @@ --md-typeset-kbd-color: rgb(226, 226, 226); /* keyboard key background ( tag) */ --md-typeset-kbd-accent-color: rgb(255, 255, 255, .78); /* keyboard key inner border ( tag) */ --md-typeset-kbd-border-color: rgb(212, 212, 212); /* text as keyboard outer border ( tag) */ - --navigation-borders: var(--md-default-fg-color--lighter); /* Left border on the toc and navigation, border of cards */ - --navigation-borders-lighter: rgba(var(--default-fg-color),.2); /* Lighter border of cards */ - --navigation-borders-lightest: var(--md-default-fg-color--lightest); /* Lightest left border for navigation */ - --md-typeset-table-color: var(--navigation-borders); /* table borders (
tag) */ + --navigation-borders: #FAA61950; /* Left border on the toc and navigation */ + --card-borders: var(--md-primary-fg-color--dark); /* Borders of cards */ + --md-typeset-table-color: var(--card-borders); /* table borders (
tag) */ --md-admonition-fg-color: var(--md-typeset-color); /* Main text warnings */ --md-admonition-bg-color: var(--md-default-bg-color); /* Background warnings */ --md-footer-fg-color: var(--md-primary-bg-color); /* footer text (not much used) */ @@ -142,7 +144,10 @@ --card-shadows: #00000075; /* Shadows on cards and other elements */ --card-shadows-hover: #00000090; /* Shadows hover on cards and other elements */ --img-background: #FFFFFF; /* Background for transparent images */ - --shadow-hover-background: rgba(29, 28, 28, 0.185) /* Shadow Background on hover */ + --shadow-hover-background: rgba(29, 28, 28, 0.185); /* Shadow Background on hover */ + --terminal-animation-directory: var(--nri-blue); + --terminal-animation-buttons: var(--nri-dark-blue); + --terminal-animation-buttons-hover: var(--nri-orange); } @@ -154,6 +159,14 @@ h1 { font-weight: 600 !important; } +h2 { + font-weight: 500 !important; +} + +h3 { + margin: 1em 0 0.4em !important; +} + /* =============================================================== Introductory paragraph */ @@ -383,7 +396,7 @@ h1 { display: flex; justify-content: center; align-items: center; - border: 1px solid var(--navigation-borders-lighter); + border: 1px solid var(--card-borders); border-radius: 15px; box-shadow: 6px 6px 10px var(--card-shadows); } @@ -475,10 +488,131 @@ a.component-card { box-shadow: unset; } +/* =============================================================== + References +*/ +.references { + font-size:0.8em; +} + +/* =============================================================== + Page summary ('on this page' section) +*/ +div.page-summary { + max-width: 100%; + border: solid 0.5px var(--md-typeset-color); + border-radius: 3px; + padding: 0 15px 10px; + line-height: 1.2em; + margin: 20px 0; +} + +.page-summary h4 { + margin: 0.7em 0; +} + +.page-summary ol { + list-style-type: none !important; + counter-reset: item !important; + margin: 0 !important; + padding: 0 !important; +} + +.page-summary li { + display: table !important; + counter-increment: item !important; + margin: 0 0 0.5em 0.5em !important; +} + +.page-summary li:before { + content: counters(item, ".") ". " !important; + display: table-cell !important; + padding-right: 0.3em !important; +} + +.page-summary li li { + margin: 0.1em 0 0 0 !important; +} + +.page-summary li li:before { + content: counters(item, ".") ". " !important; +} + + +/* =============================================================== + Show different markers for different hierarchy of points (up to 3d hierarchy) +*/ +ul:not([class^='md-']) li { + list-style-type: disc; +} + +ul:not([class^='md-']) li ul li { + list-style-type: circle; +} + +ul:not([class^='md-']) li ul li ul li { + list-style-type: square; +} + +/* =============================================================== + Code block +*/ +pre:has(code) { + display: flow-root !important; + text-align: left !important; + padding: 0 0 !important; + margin-top: 0.5em !important; + margin-bottom: 0.5em !important; +} + +pre>code { + white-space: pre-line !important; + padding: 0.5em 0.8em !important; + word-break: break-all !important; +} + +/* =============================================================== + Terminal animations +*/ +::part(terminal-container) { + background-color: var(--md-code-bg-color); + color: var(--md-code-fg-color); + font-family: var(--md-code-font-family); + font-weight: unset; +} + +::part(input-character) { + color: var(--terminal-animation-buttons); +} + +::part(directory) { + color: var(--terminal-animation-directory); +} + +::part(fast-button), ::part(restart-button) { + color: var(--terminal-animation-buttons); + font-weight: 700; +} + +::part(fast-button):hover, ::part(restart-button):hover { + color: var(--terminal-animation-buttons-hover); +} + +/* Try to format like the output of `ls` command */ +.ls-output-format { + word-spacing: 2em; + word-break: normal; +} + /* =============================================================== Miscellaneous */ +/* Justified text */ +.justified { + text-align: justify; +} + /* Highlight the background */ .highlight-bg { background-color: var(--highlight-bg); @@ -502,7 +636,7 @@ a.component-card { /* With borders */ .with-border { border-radius: 7px; - border: 1px solid var(--navigation-borders-lightest); + border: 1px solid var(--card-borders); box-sizing: border-box; } diff --git a/docs/css/termynal.css b/docs/css/termynal.css deleted file mode 100644 index a11274415..000000000 --- a/docs/css/termynal.css +++ /dev/null @@ -1,114 +0,0 @@ -/** - * termynal.js - * - * @author Ines Montani - * @version 0.0.1 - * @license MIT - */ - - -:root { - --color-bg: #252a33; - --color-text: #eee; - --color-text-subtle: #a2a2a2; - --color-text-directory: var(--nri-green); /* Colour taken from ACCESS-NRI website */ - --color-text-symlink: var(--nri-blue); /* Colour taken from ACCESS-NRI website */ - --color-text-dollar-sign: var(--nri-orange); /* Colour taken from ACCESS-NRI website */ - --color-control-buttons: #115D97; -} - -.termynal { - /* width: 750px; */ - max-width: 100%; - background: var(--color-bg); - color: var(--color-text); - display: flex; - flex-direction: column; - justify-content: flex-start; - font-size: 13px; - font-family: 'Roboto Mono', 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; - font-weight: bold; - border-radius: 4px; - padding: 35px 25px 25px; - position: relative; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -.termynal::before { - content: ''; - position: absolute; - top: 15px; - left: 15px; - display: inline-block; - width: 15px; - height: 15px; - border-radius: 50%; - /* A little hack to display the window buttons in one pseudo element. */ - background: #d9515d; - -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; - box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; -} - -[data-ty] { - line-height: 2; - justify-self: center; -} - -[data-ty]::before { - /* Set up defaults and ensure empty lines are displayed. */ - content: ''; - display: inline-block; -} - -[data-ty][prompt]::before { - content: attr(prompt); - color: var(--color-text-subtle); -} - -[data-ty="input"][directory]::before { - content: attr(directory); - color: var(--color-text-directory); -} - -[cursor]::after { - content: attr(cursor); - font-family: monospace; - -webkit-animation: blink 1s infinite; - animation: blink 1s infinite; -} - -a[termynal-control-buttons] { - align-self: flex-end; - color: var(--color-control-buttons); -} - -.directory-text { - color: var(--color-text-directory); -} - -.symlink-text { - color: var(--color-text-symlink); -} - -.double-spaced { - word-spacing: 1em; -} - -[charBeforeInput] { - color: var(--color-text-dollar-sign); -} - -/* Cursor animation */ - -@-webkit-keyframes blink { - 50% { - opacity: 0; - } -} - -@keyframes blink { - 50% { - opacity: 0; - } -} diff --git a/docs/js/terminal_animation.js b/docs/js/terminal_animation.js new file mode 100644 index 000000000..e2d702c06 --- /dev/null +++ b/docs/js/terminal_animation.js @@ -0,0 +1,1032 @@ +/** + * terminal-animation components + * Components based on the animated terminal app 'termynal.js' by Ines Montani . + * + * @author Davide Marchegiani + * @version 1.0.0 + * + * The usage is as follow: + * + * + * First input line + * Second input line + * Third input with red span + * First output line + * + * + * The tag allows only and tags inside it. All the other nodes will be removed. + * E.g.: + * + * This line will be removed + * This line will be kept + *
Also this line will be removed
+ *
+ * + * The tag allows only text nodes or tags inside it. All the other nodes will be removed. + * E.g.: + * All this line will be kept + * This will be kept but
this will be removed
+ * + * The animation starts only when the terminal becomes visible, unless the 'init' + * attribute is present (in that case the animation starts right after the page loads). + * To know all the other possible attributes and what they do please read the specific components. + * + * + * List of sub-components editable with the CSS ::part pseudo-element: + * - Terminal Container -> ::part(terminal-container) + * - Fast Button -> ::part(fast-button) + * - Restart Button -> ::part(restart-button) + * - Directory -> ::part(directory) + * - Input Character(s) -> ::part(input-character) + * - Prompt Character(s) -> ::part(prompt-character) +*/ +'use strict'; + + +const terminalTemplate = document.createElement('template'); +terminalTemplate.innerHTML = ` + + +
+ +
+` +/* Terminal component */ +class TerminalAnimation extends HTMLElement { + /** + * Custom attributes for the component: + * + * @param {string} mode - 'light' for light mode; 'dark' for dark mode (default). + * @param {string} data - Type of prompt for each line of the entire terminal. Choices can be: + * - 'output': Output of the terminal. Written all at once; (default) + * - 'input': Input to the terminal. Written with typing animation after 'directory' and 'inputChar' attributes; + * - 'prompt': Same as input, but with written with typing animation after 'promptChar' attribute; + * - 'progress' Line with progress bar animation. + * @param {number || string} startDelay - Delay before the start of terminal animation, in ms. + * @param {number || string} lineDelay - Delay before the start of each terminal line animation, in ms. + * @param {number || string} typingDelay - Delay between each typed character in the terminal, in ms. + * @param {string} progressChar – Character(s) to use for progress bar for the entire terminal, defaults to █. + * @param {number || string} progressPercent - Max percent of progress for the entire terminal, default 100%. + * @param {string} cursor – Character to use for cursor for the entire terminal, defaults to ▋. + * @param {string} inputChar – Character(s) to use before the 'input' prompt for the entire terminal, defaults to '$'. + * @param {string} directory – Directory to write in the 'input' prompt before the input character for the entire terminal. + * @param {string} promptChar – Character(s) to use before the 'prompt' prompt for the entire terminal, defaults to '>>>'. + * @param {string} PS1 – String to write in the 'input' prompt before the actual line for the entire terminal. + * If present, any 'directory' or 'input' attribute will be disregarded. + * Accepts HTML format. E.g.: "This is a valid PS1 attribute" + * @param {boolean} init - Initialise the terminal animation at page load. + * @param {boolean} static - Create a static terminal without animation. + */ + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this.shadowRoot.appendChild(terminalTemplate.content.cloneNode(true)); + this.applyMode(); + this.ALLOWED_TAGS = ['terminal-line','img']; + this.DATA_TYPES = ['input','prompt','progress','output']; + this.keepLines(); + if (!this.static) { + this.setTerminal(); + if (this.init) { + this.initialiseAnimation(); + } else { + this.initialiseWhenVisible(); + } + } else { + this.generateAllProgress(); + } + } + + get container() { + const container = this.shadowRoot.querySelector(".terminal-container"); + if (this.hasAttribute('lineDelay')) { + container.setAttribute('lineDelay',parseFloat(this.getAttribute('lineDelay'))) + } + if (this.hasAttribute('typingDelay')) { + container.setAttribute('typingDelay',parseFloat(this.getAttribute('typingDelay'))) + } + return container + } + + get mode() { + /** + * Getter for the mode property + */ + if (this.getAttribute('mode')?.toString().toLowerCase() == 'light') { + return 'light'; + } else { + return 'dark'; + } + } + + get data() { + /** + * Getter for the data property + */ + let attr = this.getAttribute('data'); + if (this.DATA_TYPES.includes(attr)) { + return attr; + } else { + return 'output' + } + } + + get startDelay() { + /** + * Resets startDelay property. + */ + return parseFloat(this.getAttribute('startDelay')) || 300; + } + + get progressChar() { + /** + * Getter for the progressChar property + */ + return this.getAttribute('progressChar')?.toString() || '█'; + } + + get progressPercent() { + /** + * Getter for the progressPercent property + */ + return parseFloat(this.getAttribute('progressPercent')) || 100; + } + + get cursor() { + /** + * Getter for the cursor property + */ + return this.getAttribute('cursor')?.toString() || '▋'; + } + + get inputChar() { + /** + * Getter for the inputChar property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('inputChar')?.toString() || '$'; + } + } + + get promptChar() { + /** + * Getter for the promptChar property + */ + return this.getAttribute('promptChar')?.toString() || '>>>'; + } + + get directory() { + /** + * Getter for the directory property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('directory')?.toString() || ''; + } + } + + get PS1() { + /** + * Getter for the PS1 property + */ + if (this.hasAttribute('PS1')) { + return this.getAttribute('PS1'); + } else { + return `${this.directory}${this.inputChar} `; + } + } + + get static() { + /** + * Getter for the static property + */ + let attr = this.getAttribute('static') + if (attr == 'false') { + return false + } else if (attr == "") { + return true + } else { + return !!attr + } + } + + get init() { + /** + * Getter for the init property + */ + let attr = this.getAttribute('init') + if (attr == 'false') { + return false + } else if (attr == "") { + return true + } else { + return !!attr + } + } + + applyMode() { + /** + * Sets the color scheme according to the mode selected. + */ + const colors = document.createElement('style'); + if (this.mode == 'dark') { + colors.innerHTML = ` + :host { + --color-bg: #252a33; + --color-text: #eee; + --color-control-buttons: #FAA619; + --color-control-buttons-hover: #115D97; + --color-scrollbar: rgba(255, 255, 255, .6); + ` + } else { + colors.innerHTML = ` + :host { + --color-text: #252a33; + --color-bg: #eee; + --color-control-buttons-hover: #FAA619; + --color-control-buttons: #115D97; + --color-scrollbar: rgba(0, 0, 0, .6); + ` + } + this.shadowRoot.appendChild(colors); + } + + keepLines() { + /* + * Delete all terminal lines without tags or whose tags are not within the elementList + * and create the lines property with the kept ones. + */ + for (let i=0; i { + if (line.data == 'progress') { + line.generateProgress(); + } + }) + } + + hide(element) { + /** + * Change element's style to 'hidden' + */ + element.style.visibility = 'hidden'; + } + + show(element) { + /** + * Change element's style to 'visible' + */ + element.style.visibility = 'visible'; + } + + sleep(time) { + /** + * Sleep for an amount of time + */ + return new Promise(resolve => setTimeout(resolve, time)); + } + + resetDelays() { + this.lines.forEach(line => { + line._lineDelay; + line._typingDelay; + }) + } + + hideLines() { + /** + * Hide lines inside the terminal + */ + this.lines.forEach(line => this.hide(line)); + } + + generateRestartButton() { + /** + * Generate restart button and adds it hidden to 'this.container' + */ + const restart = document.createElement('a') + restart.setAttribute('part','restart-button') + restart.onclick = e => { + e.preventDefault(); + this.hideAll(); + this.scrollToTop(); + this.mutationObserver.disconnect(); + this.initialiseAnimation(); + } + restart.href = ''; + restart.classList.add('restart-button'); + restart.innerHTML = "restart ↻"; + this.hide(restart); + restart.addEventListener('click', e => this.hide(restart)); + this.restartButton = restart; + this.container.appendChild(restart); + } + + generateFastButton() { + /** + * Generate fast button and adds it hidden to 'this.container' + */ + function nullifyDelays(_this) { + _this.lines.forEach(line => { + line._lineDelay = 0; + line._typingDelay = 0; + }) + } + const fast = document.createElement('a') + fast.setAttribute('part','fast-button') + fast.onclick = (e) => { + e.preventDefault(); + nullifyDelays(this); + } + fast.href = ''; + fast.classList.add('fast-button'); + fast.innerHTML = "fast ❯❯❯"; + this.hide(fast); + fast.addEventListener('click', e => this.hide(fast)); + this.addFocusOnTerminalContainerOnClick(fast); + this.fastButton = fast; + this.container.prepend(fast); + } + + setTerminal() { + /** + * Clear container and generate restart/fast buttons. + */ + this.hideLines(); + this.generateRestartButton(); + this.generateFastButton(); + this.generateObservers(); + } + + hidePS1AndPromptChar() { + /** + * Hides PS1 and Prompt Char for terminal reset + */ + this.lines.forEach(line => { + let elem = line.shadowRoot?.querySelector('.ps1, .promptChar'); + if (elem) { + this.hide(elem); + } + }) + } + + hideAll() { + this.hideLines(); + this.hidePS1AndPromptChar(); + } + + async initialiseAnimation() { + /** + * Start the animation and render the lines + */ + // while (this.container.scrollTop != 0) {await this.sleep(50)} //Start when the container is scroll up to the top. + this.autoScroll(); + await this.sleep(this.startDelay); + this.show(this.fastButton); + for (let line of this.lines) { + line.classList.add('isBeingTyped'); + if (line.tagName.toLowerCase() == 'terminal-line') { + // Handle lines + await line.type(); + } else if (line.tagName.toLowerCase() == 'img') { + // Handle lines + this.show(line); + // await this.sleep(2000); + // this.hide(line); + } + line.classList.remove('isBeingTyped'); + } + this.hide(this.fastButton); + this.resetDelays(); + this.show(this.restartButton); + } + + initialiseWhenVisible() { + /** + * Initialise the terminal only when it becomes visible + */ + let observer = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + this.initialiseAnimation(); + observer.unobserve(this); + } + }) + }, + { + rootMargin: "-50px", + }) + observer.observe(this); + } + + addFocusOnTerminalContainerOnClick(elem) { + elem.addEventListener('click',() => this.container.focus()) + } + + scrollToTop() { + // Scroll to the bottom of the container. + this.container.scrollTop = 0; + } + + scrollToBottom() { + // Scroll to the bottom of the container. + this.container.scrollTop = this.container.scrollHeight; + } + + scrollOneLine(line) { + const nPix = parseInt(getComputedStyle(line).height); + this.container.scrollBy(0,nPix); + } + + generateObservers() { + const intersectionFunction = entry => { + if (entry.intersectionRatio == 1) { + intersectionObserver.unobserve(entry.target); + } else { + if (entry.target.nextSibling) { + this.scrollOneLine(entry.target); + } + intersectionObserver.unobserve(entry.target); + } + } + + let margin = `${parseInt(getComputedStyle(this.container).marginBottom) - 5}px` // Margin of the intersectionObserver computed as bottom margin - 5px (5px padding) + let intersectionObserver = new IntersectionObserver(entries => { + entries.forEach(entry => { + console.log(entry.intersectionRatio) + console.log(this.container.scrollTop) + intersectionFunction(entry) + }) + }, + { + root: this.container, + rootMargin: `0px 0px ${margin} 0px`, + }) + + const mutationFunction = entry => { + if (entry.target.nextSibling) { + intersectionObserver.observe(entry.target.nextSibling) + } else { + this.scrollToBottom(); + } + } + + this.mutationObserver = new MutationObserver(entries => { + entries.forEach(entry => { + if (entry.oldValue?.includes("isBeingTyped")) { + mutationFunction(entry) + } + }) + }) + } + + autoScroll() { + /** + * Auto scrolls 1 line if the terminal content exceeds the terminal max-height. + */ + this.lines.forEach(line => { + this.mutationObserver.observe(line,{ + attributes: true, + attributeOldValue: true, + attributeFilter: ["class"] + }) + }); + + this.addEventListener('wheel', e => { + this.mutationObserver.disconnect(); + }) + + this.addEventListener('keydown', e => { + if (['ArrowDown','Space','ArrowUp'].includes(e.code)) { + this.mutationObserver.disconnect(); + } + }) + } +} + +/* ============================================================================================================= + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== + =============================================================================================================== */ + + /* Terminal line */ +const lineTemplate = document.createElement('template'); +lineTemplate.innerHTML = ` + + + +
+ + +` + +class TerminalLine extends HTMLElement { + /** + * Defining custom attributes for component + // * @param {string} data - Type of prompt for the current line. Choices can be: + // * - 'output': Output of the terminal. Written all at once; (default) + // * - 'input': Input to the terminal. Written with typing animation after 'directory' and 'inputChar' attributes; + // * - 'prompt': Same as input, but with written with typing animation after 'promptChar' attribute; + // * - 'progress' Line with progress bar animation. + // * @param {number} lineDelay - Delay before the start of the line animation, in ms. + // * @param {number} typingDelay - Delay between each typed character in the line, in ms. + // * @param {string} progressChar – Character to use for progress bar in the line, defaults to █. + // * @param {number} progressPercent - Max percent of progress in the line, default 100%. + // * @param {string} cursor – Character to use for cursor in the line, defaults to ▋. + // * @param {string} inputChar – Character(s) to use before the 'input' prompt in the line, defaults to '$'. + // * @param {string} directory – Directory to write in the 'input' prompt before the input character in the line. + // * @param {string} promptChar – Character(s) to use before the 'prompt' prompt in the line, defaults to '>>>'. + // * @param {string} PS1 – String to write in the 'input' prompt before the actual line. + If present, any 'directory' or 'input' attribute will be disregarded. + Accepts HTML format. E.g.: "This is a valid PS1 attribute" + // */ + constructor() { + super(); + const shadow = this.attachShadow({ mode: "open" }); + shadow.appendChild(lineTemplate.content.cloneNode(true)); + this.ALLOWED_NODES = ["span"]; + this.line = this.shadowRoot.querySelector(".terminal-line"); + this.setCursorChar(); + this.keepNodes(); + this.generatePS1AndPromptCharElements(); + this.resetDelays(); + this.container.addFocusOnTerminalContainerOnClick(this); + } + + get container() { + if (this.parentElement.tagName.toLowerCase() != 'terminal-animation') { + throw new Error("A 'terminal-line' tag can only be placed inside a 'terminal-animation' tag."); + } + return this.parentElement; + } + + get data() { + /** + * Getter for the data property + */ + if (this.hasAttribute('data')) { + let attr = this.getAttribute('data'); + if (this.container.DATA_TYPES.includes(attr)) { + return attr; + } else { + return 'output'; + } + } else { + return this.container.data; + } + } + + get _lineDelay() { + /** + * Resets lineDelay property. + */ + if (this.hasAttribute('lineDelay')) { + this.lineDelay = parseFloat(this.getAttribute('lineDelay')); + } else if (this.container.hasAttribute('lineDelay')) { + this.lineDelay = parseFloat(this.container.getAttribute('lineDelay')); + } else if (["input","prompt"].includes(this.data)) { + this.lineDelay = 600; + } else { + this.lineDelay = 100; + } + } + + set _lineDelay(time) { + /** + * Sets lineDelay property. + */ + this.lineDelay = time; + } + + get _typingDelay() { + /** + * Resets typingDelay property. + */ + if (this.hasAttribute('typingDelay')) { + this.typingDelay = parseFloat(this.getAttribute('typingDelay')); + } else if (this.container.hasAttribute('typingDelay')) { + this.typingDelay = parseFloat(this.container.getAttribute('typingDelay')); + } else if (["progress"].includes(this.data)) { + this.typingDelay = 30; + } else { + this.typingDelay = 80; + } + } + + set _typingDelay(time) { + /** + * Sets typingDelay property. + */ + this.typingDelay = time; + } + + resetDelays() { + this._lineDelay; + this._typingDelay; + } + + get progressChar() { + /** + * Getter for the progressChar property + */ + return this.getAttribute('progressChar')?.toString() || this.container.progressChar; + } + + get progressPercent() { + /** + * Getter for the progressPercent property + */ + return parseFloat(this.getAttribute('progressPercent')) || this.container.progressPercent; + } + + get cursor() { + /** + * Getter for the cursor property + */ + return this.getAttribute('cursor')?.toString() || this.container.cursor; + } + + get inputChar() { + /** + * Getter for the inputChar property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('inputChar')?.toString() || this.container.inputChar; + } + } + + get promptChar() { + /** + * Getter for the promptChar property + */ + return this.getAttribute('promptChar')?.toString() || this.container.promptChar; + } + + get directory() { + /** + * Getter for the directory property + */ + if (this.hasAttribute('PS1')) { + return ''; + } else { + return this.getAttribute('directory')?.toString() || this.container.directory; + } + } + + get PS1() { + /** + * Getter for the PS1 property + */ + if (this.hasAttribute('PS1')) { + return this.getAttribute('PS1'); + } else if (this.hasAttribute('directory') || this.hasAttribute('inputChar')) { + return `${this.directory}${this.inputChar} `; + } else { + return this.container.PS1; + } + } + + setCursorChar() { + const style = document.createElement('style'); + style.innerHTML=` + .cursor::after { + content: '${this.cursor}'; + font-family: monospace; + -webkit-animation: blink 1s infinite; + animation: blink 1s infinite; + } + + @-webkit-keyframes blink { + 50% { + opacity: 0; + } + } + + @keyframes blink { + 50% { + opacity: 0; + } + } + ` + this.shadowRoot.appendChild(style); + } + + keepNodes(elementList=this.ALLOWED_NODES) { + /* + * Delete all line nodes whose tags are not within the elementList, + * create tags around textNodes, + * and create the nodes property with the kept ones. + */ + for (let i=0; i setTimeout(resolve, time)); + } + + showPS1() { + this.show(this.shadowRoot.querySelector('.ps1')); + } + + showPromptChar() { + this.show(this.shadowRoot.querySelector('.promptChar')); + } + + async type() { + /** + * Function that handles the animation of the current line based on its data property + */ + if (this.data == 'input') { + this.showPS1(); + await this.typeInput(); + } else if (this.data == 'progress') { + await this.sleep(this.lineDelay); + await this.typeProgress(); + return; + } else if (this.data == 'prompt') { + this.showPromptChar(); + await this.typeInput(); + } else { + await this.sleep(this.lineDelay); + this.show() + } + + } + + measureChar(char=this.progressChar) { + const ruler = document.createElement('span'); + ruler.innerHTML = char; + ruler.style.whiteSpace = 'pre'; + this.appendChild(ruler); + const width = ruler.offsetWidth; + this.removeChild(ruler); + return width; + } + + async typeProgress() { + /** + * Animate a progress bar. + */ + const progressCharWidth = this.measureChar(); + const progressSteps = Math.round((parseInt(getComputedStyle(this).width)*0.8*(this.progressPercent/100))/progressCharWidth); + let percent = 0; + this.textContent = '0%'; + this.show(); + for (let i=1; i<=progressSteps; i++) { + await this.sleep(this.typingDelay); + percent = Math.round(this.progressPercent/progressSteps*i) + this.textContent = `${this.progressChar.repeat(i)} ${percent}%`; + } + } + + generateProgress() { + const progressCharWidth = this.measureChar(); + const progressLength = Math.round((parseInt(getComputedStyle(this).width)*0.8*(this.progressPercent/100))/progressCharWidth); + this.textContent = `${this.progressChar.repeat(progressLength)} ${this.progressPercent}%`; + } + + async typeInput() { + /** + * Animate an input line. + */ + let textArray = this.getAndRemoveTextContent(); + this.show(); + this.addCursor(); + await this.sleep(this.lineDelay); + for (let i=0; i -ACCESS-CM2 is a set of sub-models (eg. UM, MOM, CICE, CABLE, OASIS) with a range of model parameters, input data, and computer related information, that need to be packaged together as a suite in order to run. +ACCESS-CM2 is a set of submodels (eg. UM, MOM, CICE, CABLE, OASIS) with a range of model parameters, input data, and computer related information, that need to be packaged together as a suite in order to run.
Each ACCESS-CM2 suite has an ID, in the format u-<suite-name>, with <suite-name> being a unique identifier (e.g. u-br565 is the CMIP6 release preindustrial experiment suite).
@@ -184,11 +184,11 @@ After completing all the modifications to the suite, we are ready to run it.
ACCESS-CM2 suites run on Gadi through a PBS job submission.
-When the suite gets run, the suite configuration files are copied on Gadi under /scratch/<$PROJECT>/$USER/cylc-run/<suite-ID>, and a symbolic link to this folder is also created in the $USER's home directory under ~/cylc-run/<suite-ID>. +When the suite gets run, its configuration files are copied on Gadi under /scratch/$PROJECT/$USER/cylc-run/<suite-ID>, and a symbolic link to this folder is also created in the $USER's home directory under ~/cylc-run/<suite-ID>.
An ACCESS-CM2 suite is constituted by several tasks (such as checking out code repositories, compiling and building the different model components, running the model, etc.). The workflow of these tasks is controlled by Cylc.
-Cylc (pronounced ‘silk’), is a workflow manager that automatically executes tasks according to the model main cycle script suite.rc. Cylc deals with how the job will be run and manages the time steps of each sub-model, as well as monitoring all the tasks and reporting any error that might occur. +Cylc (pronounced ‘silk’), is a workflow manager that automatically executes tasks according to the model main cycle script suite.rc. Cylc deals with how the job will be run and manages the time steps of each submodel, as well as monitoring all the tasks and reporting any error that might occur.
To run an ACCESS-CM2 suite, on accessdev:
    @@ -481,7 +481,7 @@ This directory contains 2 subdirectories:
    References
    -
      +
      • https://confluence.csiro.au/display/ACCESS/Using+CM2+suites+in+Rose+and+Cylc
      • diff --git a/docs/models/run-a-model/run-access-esm.md b/docs/models/run-a-model/run-access-esm.md new file mode 100644 index 000000000..d012ce066 --- /dev/null +++ b/docs/models/run-a-model/run-access-esm.md @@ -0,0 +1,416 @@ + +# Run ACCESS-ESM + + +## Requirements +
        +Before running ACCESS-ESM, you need to make sure to possess the right tools and to have an account with specific institutions. +
        + +### General requirements +
        +For the general requirements needed to run all ACCESS models, please refer to the Getting Started (TO DO check link) page. +
        + +### Model-specific requirements +
        +
          +
        • + Payu +
          + To get payu on Gadi, run: +
          module use /g/data/hh5/public/modules
          +            module load conda/analysis3
          +        
          +
        • +
        +
        +---------------------------------------------------------------------------------------- + +## Get ACCESS-ESM configuration +
        +A suitable ACCESS-ESM pre-industrial configuration is avaible on the coecms GitHub. +
        +In order to get it, on Gadi, create a directory where to keep the model configuration, and clone the GitHub repo in it by running: +
        git clone https://github.com/coecms/esm-pre-industrial
        + + mkdir -p ~/access-esm + cd ~/access-esm + git clone https://github.com/coecms/esm-pre-industrial + Cloning into 'esm-pre-industrial'... + remote: Enumerating objects: 767, done. + remote: Counting objects: 100% (295/295), done. + remote: Compressing objects: 100% (138/138), done. + remote: Total 767 (delta 173), reused 274 (delta 157), pack-reused 472 + Receiving objects: 100% (767/767), 461.57 KiB | 5.24 MiB/s, done. + Resolving deltas: 100% (450/450), done. + +Note: Some modules might interfere with the git commands (for example matlab/R2018a). If you are running into issues during the cloning of the repository, it might be a good idea to run
        module purge
        first, before trying again. +
        +---------------------------------------------------------------------------------------- + +## Edit ACCESS-ESM configuration +
        +In order to modify an ACCESS-ESM configuration, it is worth understanding a bit more how its job scheduler payu works. +
        + +### Payu +
        +Payu is a workflow management tool for running numerical models in supercomputing environments. +
        +The general layout of a payu-supported model run consists of two main directories: +
          +
        • + The laboratory is the directory where all parts of the model are kept. For ACCESS-ESM, it is typically /scratch/$PROJECT/$USER/access-esm. +
        • +
        • + The control directory, where the model configuration is kept and from where the model is run (in our case is the cloned directory ~/access-esm/esm-pre-industrial). +
        • +
        +This distinction of directories keeps the small-size configuration files separated from the larger binary outputs and inputs. In this way, we can place the configuration files in the $HOME directory (being the only filesystem on Gadi that is actively backed up), without overloading it with too much data. +
        +Moreover, this separation allows to run multiple self-resubmitting experiments simultaneously that might share common executables and input data. +
        +To proceed with the setup of the laboratory directory, from the control directory run: +
        payu init
        +This will create the laboratory directory, along with other subdirectories (depending on the configuration). The main subdirectories we are interested in are: +
          +
        • work → temporary directory where the model is actually run. It gets cleaned after each run.
        • +
        • archive → directory where the output is placed after each run.
        • + + cd ~/access-esm/esm-pre-industrial + payu init + laboratory path: /scratch/$PROJECT/$USER/access-esm + binary path: /scratch/$PROJECT/$USER/access-esm/bin + input path: /scratch/$PROJECT/$USER/access-esm/input + work path: /scratch/$PROJECT/$USER/access-esm/work + archive path: /scratch/$PROJECT/$USER/access-esm/archive + +
        +
        + +### Edit the Master Configuration file +
        +The config.yaml file, located in the control directory, is the Master Configuration file. +
        +This file controls the general model configuration and if we open it in a text editor, we can see different parts: +
          +
        • + PBS resources +
          +
          jobname: pre-industrial
          +            queue: normal
          +            walltime: 20:00:00
          +        
          + These are settings for the PBS scheduler. Edit lines in this section to change any of the PBS resources. +
          + For example, to run ACCESS-ESM under the tm70 project (TO DO add Getting started, join a NCI Project link), add the following line to this section: +
          project: tm70
          +
        • +
        • + Link to the laboratory directory +
          +
          # note: if laboratory is relative path, it is relative to /scratch/$PROJECT/$USER
          +            laboratory: access-esm
          +        
          + This will set the laboratory directory. Relative paths are relative to /scratch/$PROJECT/$USER. Absolute paths can be specified as well. +
        • +
        • + Model +
          model: access
          + The main model. This tells payu which driver to use (access stands for ACCESS-ESM). +
        • +
        • + Submodels +
          +
          submodels:
          +              - name: atmosphere
          +                model: um
          +                ncpus: 192
          +                exe: /g/data/access/payu/access-esm/bin/coe/um7.3x
          +                input:
          +                  - /g/data/access/payu/access-esm/input/pre-industrial/atmosphere
          +                  - /g/data/access/payu/access-esm/input/pre-industrial/start_dump
          +   - name: ocean +     model: mom +     ncpus: 180 +     exe: /g/data/access/payu/access-esm/bin/coe/mom5xx +     input: +       - /g/data/access/payu/access-esm/input/pre-industrial/ocean/common +       - /g/data/access/payu/access-esm/input/pre-industrial/ocean/pre-industrial
          +   - name: ice +     model: cice +     ncpus: 12 +     exe: /g/data/access/payu/access-esm/bin/coe/cicexx +     input: +       - /g/data/access/payu/access-esm/input/pre-industrial/ice
          +   - name: coupler +     model: oasis +     ncpus: 0 +     input: +       - /g/data/access/payu/access-esm/input/pre-industrial/coupler +
          + ACCESS-ESM is a coupled model, which means it has multiple submodels (i.e. model components). +
          + This section specifies the submodels and contains configuration options (for example the directories of input files) that are required to ensure the model can execute correctly. Each submodel also has additional configuration options that are read in when the submodel is running. These specific configuration options are found in the subdirectory of the control directory having the name of the submodel (e.g. in our case the configuration for the atmosphere submodel, i.e. the UM, will be in the directory ~/access-esm/esm-pre-industrial/atmosphere). +
        • +
        • + collate +
          +
          collate:
          +              exe: /g/data/access/payu/access-esm/bin/mppnccombine
          +              restart: true
          +              mem: 4GB
          +        
          + The collate process joins a number of smaller files, which contain different parts of the model grid, together into target output files. The restart files are typically tiled in the same way and will also be joined together if the restart option is set to true. +
        • +
        • + restart +
          +
          restart: /g/data/access/payu/access-esm/restart/pre-industrial
          + The location of the files used for a warm restart. +
        • +
        • + Start date and internal run length +
          +
          calendar:
          +              start:
          +                year: 101
          +                month: 1
          +                days: 1
          +   runtime: +     years: 1 +     months: 0 +     days: 0 +
          + This section specifies the start date and internal run length. +
          + Note: The internal run length (controlled by runtime) can be different from the total run length. Also, the runtime value can be lowered, but should not be increased to a total of more than 1 year, to avoid errors. If you want to know more about the difference between internal run and total run lenghts, or if you want to run the model for more than 1 year, check Run configuration for multiple years. +
        • +
        • + Number of runs per PBS submission +
          +
          runspersub: 5
          + ACCESS-ESM configurations are often run in multiple steps (or cycles), with payu running a maximum of runspersub internal runs for every PBS job submission. +
          + Note: If we increase runspersub, we might need to increase the walltime in the PBS resources. +
        • +
        +To know more about other configuration settings for the config.yaml file, please check how to configure your experiment with payu. +
        +---------------------------------------------------------------------------------------- + +## Run ACCESS-ESM configuration +After editing the configuration, we are ready to run ACCESS-ESM. +
        +ACCESS-ESM suites run on Gadi through a PBS job submission managed by payu. + +### Payu setup (optional) +
        +As a first step, from the control directory, is good practice to run: +
        payu setup
        +This will prepare the model run, based on the experiment configuration. + + payu setup + laboratory path: /scratch/$PROJECT/$USER/access-esm + binary path: /scratch/$PROJECT/$USER/access-esm/bin + input path: /scratch/$PROJECT/$USER/access-esm/input + work path: /scratch/$PROJECT/$USER/access-esm/work + archive path: /scratch/$PROJECT/$USER/access-esm/archive + Loading input manifest: manifests/input.yaml + Loading restart manifest: manifests/restart.yaml + Loading exe manifest: manifests/exe.yaml + Setting up atmosphere + Setting up ocean + Setting up ice + Setting up coupler + Checking exe and input manifests + Updating full hashes for 3 files in manifests/exe.yaml + Creating restart manifest + Updating full hashes for 30 files in manifests/restart.yaml + Writing manifests/restart.yaml + Writing manifests/exe.yaml + +Note: You can skip this step as it is included also in the run command. However, runnning it explicitly helps to check for errors and make sure executable and restart directories are accessible. +
        + +### Run configuration +
        +To run ACCESS-ESM configuration for one internal run length (controlled by runtime in the config.yaml file), run: +
        payu run -f
        +This will submit a single job to the queue with a total run length of runtime. It there is no previous run, it will start from the start date indicated in the config.yaml file, otherwise it will perform a warm restart from a precedently saved restart file. +
        +Note:The -f option ensures that payu will run even if there is an existing non-empty work directory, which happens if a run crashes. + + payu run -f + Loading input manifest: manifests/input.yaml + Loading restart manifest: manifests/restart.yaml + Loading exe manifest: manifests/exe.yaml + payu: Found modules in /opt/Modules/v4.3.0 + qsub -q normal -P <project> -l walltime=11400 -l ncpus=384 -l mem=1536GB -N pre-industrial -l wd -j n -v PAYU_PATH=/g/data/hh5/public/apps/miniconda3/envs/analysis3-23.01/bin,MODULESHOME=/opt/Modules/v4.3.0,MODULES_CMD=/opt/Modules/v4.3.0/libexec/modulecmd.tcl,MODULEPATH=/g/data3/hh5/public/modules:/etc/scl/modulefiles:/opt/Modules/modulefiles:/opt/Modules/v4.3.0/modulefiles:/apps/Modules/modulefiles -W umask=027 -l storage=gdata/access+gdata/hh5 -- /g/data/hh5/public/apps/miniconda3/envs/analysis3-23.01/bin/python3.9 /g/data/hh5/public/apps/miniconda3/envs/analysis3-23.01/bin/payu-run + <job-ID>.gadi-pbs + +
        + +### Run configuration for multiple years +
        +If you want to run ACCESS-ESM configuration for multiple internal run lengths (controlled by runtime in the config.yaml file), you can use the option -n: +
        payu run -n <number-of-runs>
        +This will run the configuration number-of-runs times with a total run length of runtime * number-of-runs. The number of consecutive PBS jobs submitted to the queue depends on the runspersub value specified in the config.yaml file. +
        + +### Understand runtime, runspersub, and -n parameters +
        +With the correct use of runtime, runspersub, and -n parameters, we can have full control of our run. +
        +
          +
        • + runtime defines the internal run length. +
        • +
        • + runspersub defines the maximum number of internal runs for every PBS job submission. +
        • +
        • + -n sets the number of internal runs to be performed. +
        • +
        +Let's have some practical examples: +
          +
        • + Run 20 years of simulation, with resubmission every 5 years +
          + To have a total run length of 20 years, with a resubmition cycle of 5 years, we can leave runtime to the default value of 1 year, set runspersub to 5, and run the configuration using -n 20: +
          payu run -n 20
          + This will submit subsequent jobs for the following years: 1 to 5, 6 to 10, 11 to 15, and 16 to 20. With a total of 4 PBS jobs. +
        • +
        • + Run 7 years of simulation, with resubmission every 3 years +
          + To have a total run length of 7 years, with a resubmition cycle of 3 years, we can leave runtime to the default value of 1 year, set runspersub to 3, and run the configuration using -n 7: +
          payu run -n 7
          + This will submit subsequent jobs for the following years: 1 to 3, 4 to 6, and 7. With a total of 3 PBS jobs. +
        • +
        • + Run 3 months and 10 days of simulation, in one single submission +
          + To have a total run length of 3 months and 10 days, all in a single submission, we have to set runtime to: +
          years: 0
          +            months: 3
          +            days: 10
          +        
          + set runspersub to 1 (or any value > 1), and run the configuration without -n (or with -n equals 1): +
          payu run
          +
        • +
        • + Run 1 year and 4 months of simulation, with resubmission every 4 months +
          + To have a total run length of 1 year and 4 months (16 months), we will have to split it into multiple internal runs. For example, we can have 4 internal runs of 4 months each. Therefore, we will have to set runtime to: +
          years: 0
          +            months: 4
          +            days: 0
          +        
          + Since the internal run length is set to 4 months, to resubmit our jobs every 4 months (i.e. every internal run), we have to set runspersub to 1. Finally, we will perform 4 internal runs by running the configuration with -n 4: +
          payu run -n 4
          +
        • +
        +
        +---------------------------------------------------------------------------------------- + +## Monitor runs +
        +Currently, there is no specific tool to monitor ACCESS-ESM runs. +
        +One way to check the status of our run is running: +
        qstat -u $USER
        +This will show the status of all your PBS jobs (if there is any PBS job submitted): + + qstat -u $USER + Job id                Name             User             Time Use S Queue + --------------------- ---------------- ---------------- -------- - ----- + <job-ID>.gadi-pbs     pre-industrial   <$USER>            <time> R normal-exec + <job-ID>.gadi-pbs     <other-job-name> <$USER>            <time> R normal-exec + <job-ID>.gadi-pbs     <other-job-name> <$USER>            <time> R normal-exec + +If you changed the jobname in the PBS resources of the Master Configuration file, that will be your job's Name instead of pre-industrial. +
        +S indicates the status of your run: +
          +
        • Q → Job waiting in the queue to start
        • +
        • R → Job running
        • +
        • E → Job ending
        • +
        +If there is no listed job with your jobname (or if there is no job submitted at all), your run might have successfully completed, or might have been terminated due to an error. +
        + +### Check the output and error log files +
        +While the model is running, payu saves the standard output and standard error into the files access.out and access.err in the control directory. You can examine these files, as the run progresses, to check on it's status. +
        +After the model has completed its run, or if it crashed, the output and error log files, respectively, are renamed by default into jobname.o<job-ID> and jobname.e<job-ID>. +
        +---------------------------------------------------------------------------------------- + +## Model outputs +
        +While the configuration is running, output files (as well as restart files) are moved from the work directory to the archive directory, under /scratch/$PROJECT/$USER/access-esm/archive (also symlinked in the control directory under ~/access-esm/esm-pre-industrial/archive). +
        +Both outputs and restarts are stored into subfolders for each different configuration (esm-pre-industrial in our case), and inside the configuration folder, they are subdivided for each internal run. +
        +The format of a typical output folder is outputXXX, whereas the typical restart folder is usually formatted as restartXXX, with XXX being the number of internal run, starting from 000. +
        +In the respective folders, outputs and restarts are separated for each model component. +
        +For the atmospheric output data, each file it is usually a UM fieldsfile, formatted as <UM-suite-identifier>a.p<output-stream-identifier><time-identifier>. + + cd /scratch/$PROJECT/$USER/access-esm/archive/esm-pre-industrial + ls + output000 pbs_logs restart000 + ls output000/atmosphere + aiihca.daa1210 aiihca.daa1810 aiihca.paa1apr aiihca.paa1jun aiihca.pea1apr aiihca.pea1jun aiihca.pga1apr aiihca.pga1jun atm.fort6.pe0 exstat ihist prefix.CNTLGEN UAFLDS_A aiihca.daa1310 aiihca.daa1910 aiihca.paa1aug aiihca.paa1mar aiihca.pea1aug aiihca.pea1mar aiihca.pga1aug aiihca.pga1mar cable.nml fort.57 INITHIS prefix.PRESM_A um_env.py aiihca.daa1410 aiihca.daa1a10 aiihca.paa1dec aiihca.paa1may aiihca.pea1dec aiihca.pea1may aiihca.pga1dec aiihca.pga1may CNTLALL ftxx input_atm.nml SIZES xhist aiihca.daa1510 aiihca.daa1b10 aiihca.paa1feb aiihca.paa1nov aiihca.pea1feb aiihca.pea1nov aiihca.pga1feb aiihca.pga1nov CONTCNTL ftxx.new namelists STASHC aiihca.daa1610 aiihca.daa1c10 aiihca.paa1jan aiihca.paa1oct aiihca.pea1jan aiihca.pea1oct aiihca.pga1jan aiihca.pga1oct debug.root.01 ftxx.vars nout.000000 thist aiihca.daa1710 aiihca.daa2110 aiihca.paa1jul aiihca.paa1sep aiihca.pea1jul aiihca.pea1sep aiihca.pga1jul aiihca.pga1sep errflag hnlist prefix.CNTLATM UAFILES_A + + +
        + + + +
        +
        References
        + \ No newline at end of file diff --git a/docs/models/running-a-model/running-access-om.md b/docs/models/run-a-model/run-access-om.md similarity index 100% rename from docs/models/running-a-model/running-access-om.md rename to docs/models/run-a-model/run-access-om.md diff --git a/docs/models/running-a-model/running-access-esm.md b/docs/models/running-a-model/running-access-esm.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/models/running-a-model/running-access-s.md b/docs/models/running-a-model/running-access-s.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/mkdocs.yml b/mkdocs.yml index 91d6a34cc..443f599c8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -41,11 +41,6 @@ theme: - search.share - toc.follow # the sidebar is automatically scrolled to the active anchor - # - navigation.expand - # - navigation.path - # - toc.integrate - # - navigation.sections - logo: assets/ACCESS_icon_HIVE.png favicon: assets/ACCESS_icon_HIVE.png icon: @@ -75,10 +70,14 @@ markdown_extensions: - pymdownx.details - pymdownx.superfences - pymdownx.inlinehilite + - pymdownx.tabbed: + alternate_style: true - def_list - footnotes - tables - pymdownx.keys + - toc: + title: On this page # Navigation nav: @@ -118,16 +117,16 @@ nav: - ACCESS-OM: models/configurations/access-om.md - Run a Model: - - models/running-a-model/index.md + - models/run-a-model/index.md # If we add an additional subsection # - Getting Started: # - models/running-a-model/getting_started/index.md # - Access to Gadi@NCI: models/running-a-model/getting_started/access_to_gadi_at_nci.md - - Computing Access (Gadi@NCI): models/running-a-model/getting_started/access_to_gadi_at_nci.md - - Run ACCESS-ESM: models/running-a-model/running-access-esm.md - - Run ACCESS-CM: models/running-a-model/running-access-cm.md - - Run ACCESS-AM: models/running-a-model/running-access-am.md - - Run ACCESS-OM: models/running-a-model/running-access-om.md + - Computing Access (Gadi@NCI): models/run-a-model/getting_started/access_to_gadi_at_nci.md + - Run ACCESS-ESM: models/run-a-model/run-access-esm.md + - Run ACCESS-CM: models/run-a-model/run-access-cm.md + - Run ACCESS-AM: models/run-a-model/run-access-am.md + - Run ACCESS-OM: models/run-a-model/run-access-om.md - Model Evaluation: - model_evaluation/index.md @@ -180,8 +179,6 @@ nav: # Footer extra: generator: true - # version: - # provider: mike social: - icon: fontawesome/brands/twitter link: https://twitter.com/ACCESS_NRI @@ -196,28 +193,12 @@ extra: provider: google property: G-2T6SQEH2CX - # Original implementation - # supported: '' - # recommended: '' - # community: '' - - # Octicons experimental - # supported: ':octicons-check-circle-24:{ .icon-supported title="Supported by ACCESS-NRI" }' - # recommended: ':octicons-star-24:{ .icon-recommended title="Recommended by ACCESS-NRI" }' - # community: ':octicons-heart-fill-24:{ .heart title="Community contributed" }' - - # Material icons experimental - # supported: 'check_circle_outlined' - # recommended: 'star' - # community: 'favorite' - - # Fontawesome icons - supported: '' - recommended: '' - community: '' + # # Fontawesome icons + # supported: '' + # recommended: '' + # community: '' extra_css: - - css/termynal.css - css/fontello.css - "https://fonts.googleapis.com/icon?family=Material+Icons" # Material Icons Reference - https://material.io/resources/icons/?style=baseline - css/fontawesome-free-6.4.0-web/css/fontawesome.css @@ -226,5 +207,5 @@ extra_css: extra_javascript: - https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js # For tablesort functionality - - js/termynal.js + - js/terminal_animation.js - js/miscellaneous.js diff --git a/overrides/partials/toc.html b/overrides/partials/toc.html index 524a211d0..45f92e04e 100644 --- a/overrides/partials/toc.html +++ b/overrides/partials/toc.html @@ -1,8 +1,7 @@ {#- This file was automatically generated - do not edit -#} - - {% set title = "On this page" %} + {% set title = lang.t("toc") %} {% if config.mdx_configs.toc and config.mdx_configs.toc.title %} {% set title = config.mdx_configs.toc.title %} {% endif %}