Skip to content

Commit

Permalink
docs: editable scripts with game preview in docs (#221)
Browse files Browse the repository at this point in the history
* docs(localisation): first version of narrat docs localised in fr/jp/zh

* chore: asset url issue

* chore(docs|css): vitepress and theme updated, CSS changes

Includes CSS changes to make narrat affect other pages less, including the `.nrt-` prefix

* chore: narrat preview in docs working

* docs: previewable games in docs working

* chore: narrat docs editable preview working

* chore: wait to be loaded to try to show the custom element

* chore: docs preview working, removed annoying big dependency from narrat

* chore: missing file due to gitignore
  • Loading branch information
liana-p authored Jan 30, 2024
1 parent c74f606 commit 7a07581
Show file tree
Hide file tree
Showing 56 changed files with 1,493 additions and 583 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ There is now a plugin system developers can use to add new functionality to narr

(Note: The narrat-bitsy plugin hasn't been updated for 2.0.0 and might be a bit out of date).

## Docs

The documentation website uses Vitepress. Files are in markdown and can be edited. Making a pull request or pushing to master will deploy the change.

To run the docs, open a terminal at the root of the monorepo (not in the docs folder) and run:

```
pnpm run docs:dev
```

The docs also use:

- `highlight.js` for custom syntax highlighting
- `code-input` to turn syntax highlight editable for the live narrat preview in the docs

## Assets used in demo games

- [Pointing arrows from OpenGameArt](https://opengameart.org/content/pointing-arrows)
Expand Down
4 changes: 3 additions & 1 deletion demo-template/src/css/main.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* See https://docs.narrat.dev/guides/theming-the-game-and-ui for info on how to customise your game with CSS. */

#narrat-app {
#narrat {
/* Customise CSS variables here. They will override the existing narrat ones. You can also add your own variables */
--bg-color: #131720;
--text-color: #d9e1f2;
--primary: hsl(255, 30%, 55%);
--focus: hsl(210, 90%, 50%);
--secondary: #42b983;
/* You can easily override a CSS style by making it more specific than the original one.
Any css added here will applied to elements inside of #narrat and be likely more specific than their original version */
}

/* Add any other CSS you want here */
60 changes: 40 additions & 20 deletions docs/.vitepress/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import Narrat from 'vite-plugin-narrat';

/**
* @type {import('vitepress').UserConfig}
*/
const config = {
vite: {
plugins: [Narrat()],
},
vue: {
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('code-input'),
},
},
},
locales: {
root: {
label: 'English',
Expand Down Expand Up @@ -41,6 +53,13 @@ const config = {
{},
"window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-1LLT0JWVV5');",
],
['link', { rel: 'stylesheet', href: '/vendors/code-input.min.css' }],
[
'script',
{
src: '/vendors/code-input.min.js',
},
],
],
themeConfig: {
outline: [1, 6],
Expand All @@ -63,9 +82,9 @@ const config = {
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/liana-p/narrat-engine' },
{ icon: 'twitter', link: 'https://twitter.com/NarratEngine' },
// { icon: 'twitter', link: 'https://twitter.com/NarratEngine' },
{ icon: 'mastodon', link: 'https://mastodon.gamedev.place/@narrat' },
{ icon: 'discord', link: 'https://discord.gg/Xgz7EQ2Xgh' },
// { icon: 'discord', link: 'https://discord.gg/Xgz7EQ2Xgh' },
{
icon: {
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc. --><path d="M352 256c0 22.2-1.2 43.6-3.3 64H163.3c-2.2-20.4-3.3-41.8-3.3-64s1.2-43.6 3.3-64H348.7c2.2 20.4 3.3 41.8 3.3 64zm28.8-64H503.9c5.3 20.5 8.1 41.9 8.1 64s-2.8 43.5-8.1 64H380.8c2.1-20.6 3.2-42 3.2-64s-1.1-43.4-3.2-64zm112.6-32H376.7c-10-63.9-29.8-117.4-55.3-151.6c78.3 20.7 142 77.5 171.9 151.6zm-149.1 0H167.7c6.1-36.4 15.5-68.6 27-94.7c10.5-23.6 22.2-40.7 33.5-51.5C239.4 3.2 248.7 0 256 0s16.6 3.2 27.8 13.8c11.3 10.8 23 27.9 33.5 51.5c11.6 26 20.9 58.2 27 94.7zm-209 0H18.6C48.6 85.9 112.2 29.1 190.6 8.4C165.1 42.6 145.3 96.1 135.3 160zM8.1 192H131.2c-2.1 20.6-3.2 42-3.2 64s1.1 43.4 3.2 64H8.1C2.8 299.5 0 278.1 0 256s2.8-43.5 8.1-64zM194.7 446.6c-11.6-26-20.9-58.2-27-94.6H344.3c-6.1 36.4-15.5 68.6-27 94.6c-10.5 23.6-22.2 40.7-33.5 51.5C272.6 508.8 263.3 512 256 512s-16.6-3.2-27.8-13.8c-11.3-10.8-23-27.9-33.5-51.5zM135.3 352c10 63.9 29.8 117.4 55.3 151.6C112.2 482.9 48.6 426.1 18.6 352H135.3zm358.1 0c-30 74.1-93.6 130.9-171.9 151.6c25.5-34.2 45.2-87.7 55.3-151.6H493.4z"/></svg>',
Expand Down Expand Up @@ -237,26 +256,27 @@ const config = {
items: [
{ text: 'Example Config', link: '/examples/example-config' },
{ text: 'Editing the config', link: '/guides/config-files' },
{ text: 'All config files', link: '/config/all-config-files' },
],
},
{
text: 'Version',
items: [
{ text: 'Current Version', link: 'https://docs.narrat.dev' },
{
text: 'v3.0.0',
link: 'https://2-17-0--ornate-pie-561978.netlify.app/',
},
{
text: 'v2.17.0',
link: 'https://2-17-0--ornate-pie-561978.netlify.app/',
},
{
text: 'v2.12.0',
link: 'https://2-12-0--ornate-pie-561978.netlify.app/',
},
],
},
// {
// text: 'Version',
// items: [
// { text: 'Current Version', link: 'https://docs.narrat.dev' },
// {
// text: 'v3.0.0',
// link: 'https://2-17-0--ornate-pie-561978.netlify.app/',
// },
// {
// text: 'v2.17.0',
// link: 'https://2-17-0--ornate-pie-561978.netlify.app/',
// },
// {
// text: 'v2.12.0',
// link: 'https://2-12-0--ornate-pie-561978.netlify.app/',
// },
// ],
// },
],
},
title: 'Narrat Documentation',
Expand Down
18 changes: 18 additions & 0 deletions docs/.vitepress/shims-narrat.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// shims-narrat.d.ts

declare module '*.narrat' {
import { NarratScript } from 'narrat';
const narratScript: NarratScript;
export default narratScript;
}

declare module '*.yaml' {
import { NarratYaml } from 'narrat';
const narratYaml: NarratYaml;
export default narratYaml;
}
declare module '*.yml' {
import { NarratYaml } from 'narrat';
const narratYaml: NarratYaml;
export default narratYaml;
}
48 changes: 48 additions & 0 deletions docs/.vitepress/theme/custom.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
:root {
/* Original vitepress values: */
--vp-c-red-1: #b8272c;
--vp-c-red-2: #d5393e;
--vp-c-red-3: #e0575b;
--vp-c-red-soft: rgba(244, 63, 94, 0.14);

/* Overriden values@ */
--vp-c-red-1: #f66f81;
--vp-c-red-2: #e75c5c;
--vp-c-red-3: #dd3e3e;

/* Deprecated values */
--vp-c-brand-darker: #772222;
--vp-c-brand-dark: #aa3232;
--vp-c-brand: #e64545;
--vp-c-brand-light: #e64545;
--vp-c-brand-lighter: #ff4b4b;

/* Final brand values */
--vp-c-brand-1: var(--vp-c-red-1);
--vp-c-brand-2: var(--vp-c-red-2);
--vp-c-brand-3: var(--vp-c-red-3);
--vp-c-brand-soft: var(--vp-c-red-soft);

--vp-home-hero-name-background: linear-gradient(120deg, #b82727 30%, #b827b1);
--vp-home-hero-name-color: transparent;

/* tips */
--vp-c-tip-1: var(--vp-c-indigo-1);
--vp-c-tip-2: var(--vp-c-indigo-2);
--vp-c-tip-3: var(--vp-c-indigo-3);
--vp-c-tip-soft: var(--vp-c-indigo-soft);
}

.dark {
/* --vp-c-bg: #1f0808; */
}

#narrat .replay-button {
padding: 30px;
border-radius: 10px;
font-size: 3rem;
font-weight: bold;
border: 2px solid white;
}

#narrat {
--selected-border: 0px;
.dialog-box {
margin-top: 10px;
}
.dialog-title {
font-size: 1.7rem;
}
.dialog-text {
font-size: 1.5rem;
}
}
1 change: 1 addition & 0 deletions docs/.vitepress/theme/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'narrat/dist/style.css';
import DefaultTheme from 'vitepress/theme';
import FeedbackForm from '../../components/FeedbackForm.vue';

Expand Down
6 changes: 6 additions & 0 deletions docs/.vitepress/vue-shim.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare module '*.vue' {
import { defineComponent } from 'vue';

const component: ReturnType<typeof defineComponent>;
export default component;
}
34 changes: 34 additions & 0 deletions docs/components/EditableCode.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<pre
class="editable-code"
><code :class="`language-${props.language}`" v-html="highlightedCode"></code></pre>
</template>
<script lang="ts" setup>
import { defineProps, ref } from 'vue';
import hljs from 'highlight.js/lib/core';
const props = defineProps<{
codeInput: string;
language: string;
}>();
console.log(props.codeInput);
const test = `function test() {
console.log('test');
}`;
const convertedCode = hljs.highlight(test, {
language: 'javascript',
});
console.log(convertedCode);
const highlightedCode = ref(convertedCode.value);
</script>
<style scoped>
.editable-code {
border: 1px solid gray;
margin-top: 20px;
margin-bottom: 20px;
/* background-color: white; */
}
</style>
120 changes: 120 additions & 0 deletions docs/components/NarratPreview.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<template>
<code-input
v-if="loaded"
lang="narrat"
placeholder="Type code here"
template="syntax-highlighted"
:oninput="codeInputChanged"
:style="{
width: '100%',
height: props.codeHeight + 'px',
}"
>{{ props.scriptContent }}</code-input
>
<div class="narrat-preview" ref="narratContainer"></div>
</template>

<script setup lang="ts">
import { onMounted, ref, defineProps, shallowRef } from 'vue';
import { gameConfig } from '../data/defaultGameConfig';
import { getCodeInput } from '../utils/code-input';
const narratContainer = ref<HTMLDivElement | null>(null);
const isNarratRunning = ref<boolean>(false);
async function importNarrat() {
const narrat = await import('narrat');
return narrat;
}
type NarratModule = Awaited<ReturnType<typeof importNarrat>>;
const narrat = shallowRef<NarratModule | null>(null);
const loaded = ref(false);
const props = defineProps<{
scriptContent: string;
autoJumpOnChange: boolean;
codeHeight: number;
}>();
const script = ref({
fileName: 'demo-script.narrat',
code: props.scriptContent,
id: 'demo-script',
type: 'script',
});
function scriptToNarratModule(): {
default: any;
} {
return {
default: {
fileName: script.value.fileName,
code: script.value.code,
id: script.value.id,
type: 'script',
},
};
}
function codeInputChanged(el) {
const newCode = el.target.value;
script.value.code = newCode;
narrat.value.handleHMR(scriptToNarratModule() as any);
if (props.autoJumpOnChange) {
jumpBackToLabel();
}
}
onMounted(async () => {
await readyCodeInput();
loaded.value = true;
narrat.value = await importNarrat();
launchNarratGame();
});
async function readyCodeInput() {
const codeInput = await getCodeInput();
console.log('uwu ', codeInput);
}
function launchNarratGame() {
if (narratContainer.value) {
if (!isNarratRunning.value) {
startNarratApp();
}
} else {
console.error('narratContainer is null');
}
}
function stopNarratGame() {
narrat.value.stopApp();
isNarratRunning.value = false;
}
function jumpBackToLabel() {
const vm = narrat.value.useVM();
vm.jumpToLabel('main');
}
function startNarratApp() {
narrat.value.startApp({
debug: true,
logging: false,
scripts: [script.value],
container: narratContainer.value!,
config: gameConfig as any,
});
isNarratRunning.value = true;
}
</script>

<style scoped>
.narrat-preview {
width: 100%;
aspect-ratio: 1280/720;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
</style>
19 changes: 19 additions & 0 deletions docs/components/NarratSnippetClient.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<ClientOnly>
<NarratPreview
:scriptContent="scriptContent"
:autoJumpOnChange="autoJumpOnChange"
:codeHeight="codeHeight"
/>
</ClientOnly>
</template>
<script lang="ts" setup>
import NarratPreview from './NarratPreview.vue';
import { defineProps } from 'vue';
defineProps<{
scriptContent: string;
autoJumpOnChange: boolean;
codeHeight: number;
}>();
</script>
Loading

0 comments on commit 7a07581

Please sign in to comment.