Skip to content

Commit

Permalink
Merge 98f760e into 9659a20
Browse files Browse the repository at this point in the history
  • Loading branch information
dgadelha committed Apr 23, 2024
2 parents 9659a20 + 98f760e commit 6333f5e
Show file tree
Hide file tree
Showing 10 changed files with 876 additions and 77 deletions.
30 changes: 29 additions & 1 deletion docs/.vitepress/config.ts
@@ -1,4 +1,6 @@
import path from 'node:path';
import { defineConfig } from 'vitepress';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import KnexDialectsPlugins from './knexDialects';

export default defineConfig({
Expand All @@ -17,6 +19,7 @@ export default defineConfig({
editLinkText: 'Edit this page on GitHub',
lastUpdated: 'Last Updated',
nav: [
{ text: 'Playground', link: '/playground/' },
{ text: 'Guide', link: '/guide/', activeMatch: '^/guide/' },
{
text: 'F.A.Q.',
Expand All @@ -39,7 +42,32 @@ export default defineConfig({
},
},
vite: {
plugins: [KnexDialectsPlugins()],
plugins: [
KnexDialectsPlugins(),
viteStaticCopy({
targets: [
{
src: path.resolve(
path.join(__dirname, '..', 'node_modules', 'knex', 'types')
),
dest: 'playground-assets',
},
],
}),
],
define: {
process: {
env: {},
},
},
build: {
target: ['es2020'],
},
optimizeDeps: {
esbuildOptions: {
target: 'es2020',
},
},
},
});

Expand Down
154 changes: 154 additions & 0 deletions docs/.vitepress/theme/Playground.vue
@@ -0,0 +1,154 @@
<script setup>
import Knex from 'knex';
import * as sqlFormatter from 'sql-formatter';
import Split from 'split.js';
import { computed, onMounted, ref, shallowRef, watch } from 'vue';
import { useBreakpoints } from './breakpoint';
import { useDialect } from './dialect';
import { useDarkMode } from './dark-mode';
const formatter = {
cockroachdb: 'postgresql',
mssql: 'tsql',
mysql: 'mysql',
mysql2: 'mysql',
oracledb: 'plsql',
pg: 'postgresql',
pgnative: 'postgresql',
redshift: 'redshift',
sqlite3: 'sqlite',
};
const { dialect } = useDialect();
const { isDark } = useDarkMode();
const { type } = useBreakpoints();
const isVertical = computed(() => ['xs', 'sm'].includes(type.value));
const split = shallowRef();
const sql = ref('');
const code = ref('');
onMounted(() => {
split.value = Split(['#editor', '#output'], {
direction: isVertical.value ? 'vertical' : 'horizontal',
sizes: [50, 50],
});
});
watch(isVertical, () => {
split.value?.destroy(false, false);
split.value = Split(['#editor', '#output'], {
direction: isVertical.value ? 'vertical' : 'horizontal',
sizes: [50, 50],
});
});
const editorOptions = {
scrollBeyondLastLine: false,
wordWrap: 'on',
};
const outputEditorOptions = {
readOnly: true,
scrollBeyondLastLine: false,
wordWrap: 'on',
};
function handleMountEditor() {
code.value = (() => {
const hash = location.hash.slice(1);
const code = '// Knex code\nknex("table").select()\n';
try {
return hash ? decodeURIComponent(atob(hash)) || code : code;
} catch {
return code;
}
})();
fetch('/playground-assets/types/index.d.ts')
.then((res) => res.text())
.then((typeRes) => {
const mappedTypes = typeRes
.replace(/^import .*$/gmu, '')
.replace(/[^ ]export /gu, ' ')
.replace(
'declare function knex<TRecord extends {} = any, TResult = unknown[]>(\n config: Knex.Config | string\n): Knex<TRecord, TResult>;',
'declare const knex: Knex.Client & (<TRecord extends {} = any, TResult = unknown[]>(config: Knex.Config | string) => Knex<TRecord, TResult>);'
);
// @ts-ignore
monaco.languages.typescript.typescriptDefaults.addExtraLib(
mappedTypes,
'knex.d.ts'
);
})
.catch(() => {
window.location.reload();
});
}
watch([code, dialect], () => {
let output = '--- generated SQL code\n';
try {
const knex = Knex({ client: dialect.value });
output += eval(code.value).toQuery();
try {
output = sqlFormatter.format(output, {
language: formatter[dialect.value],
});
} catch (e) {
output += `\n--- sqlFormatter failed to run: ${e?.toString() ?? e}\n`;
}
} catch (err) {
output = `--- ${err?.toString() ?? err}\n`;
}
sql.value = `${output}\n`;
window.history.replaceState(
null,
'',
`#${btoa(encodeURIComponent(code.value))}`
);
});
</script>
<template>
<div
class="playground split"
:class="{ 'split-vertical': isVertical, 'split-horizontal': !isVertical }"
>
<vue-monaco-editor
id="editor"
language="typescript"
:theme="isDark ? 'vs-dark' : 'vs-light'"
v-model:value="code"
:options="editorOptions"
:saveViewState="false"
@mount="handleMountEditor"
/>
<vue-monaco-editor
id="output"
language="sql"
:theme="isDark ? 'vs-dark' : 'vs-light'"
v-model:value="sql"
:options="outputEditorOptions"
:saveViewState="false"
/>
</div>
</template>
<style scoped>
.playground {
width: 100vw;
height: 100vh;
padding-top: var(--header-height);
}
</style>
27 changes: 7 additions & 20 deletions docs/.vitepress/theme/ToggleDark.vue
@@ -1,27 +1,14 @@
<script setup>
import { onMounted, ref, computed, watch } from 'vue';
import { onMounted, watch } from 'vue';
import { useDarkMode } from './dark-mode';
const { isDark, toggleDark } = useDarkMode();
const prefersDark = ref(false);
const setting = ref('auto');
const isDark = computed(
() =>
setting.value === 'dark' || (prefersDark.value && setting.value !== 'light')
);
const toggleDark = () => {
setting.value = setting.value === 'dark' ? 'light' : 'dark';
localStorage.setItem('color-scheme', setting.value);
};
watch(isDark, () => {
function onDarkChange() {
document.documentElement.classList.toggle('dark', isDark.value);
});
}
onMounted(() => {
prefersDark.value =
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches;
setting.value = localStorage.getItem('color-scheme') || 'auto';
document.documentElement.classList.toggle('dark', isDark.value);
});
watch(isDark, onDarkChange);
onMounted(onDarkChange);
</script>

<template>
Expand Down
28 changes: 28 additions & 0 deletions docs/.vitepress/theme/breakpoint.js
@@ -0,0 +1,28 @@
import { computed, onMounted, onUnmounted, ref } from 'vue';

/**
* @ref https://stackoverflow.com/a/63944126
*/
export function useBreakpoints() {
let windowWidth = ref(window.innerWidth);

const onWidthChange = () => (windowWidth.value = window.innerWidth);
onMounted(() => window.addEventListener('resize', onWidthChange));
onUnmounted(() => window.removeEventListener('resize', onWidthChange));

/**
* @ref https://getbootstrap.com/docs/5.3/layout/breakpoints/#available-breakpoints
*/
const type = computed(() => {
if (windowWidth.value < 576) return 'xs';
if (windowWidth.value >= 576 && windowWidth.value < 768) return 'sm';
if (windowWidth.value >= 768 && windowWidth.value < 992) return 'md';
if (windowWidth.value >= 992 && windowWidth.value < 1200) return 'lg';
if (windowWidth.value >= 1200 && windowWidth.value < 1400) return 'xl';
else return 'xxl'; // Fires when windowWidth.value >= 1400
});

const width = computed(() => windowWidth.value);

return { width, type };
}
27 changes: 27 additions & 0 deletions docs/.vitepress/theme/dark-mode.js
@@ -0,0 +1,27 @@
import { ref, computed, inject } from 'vue';

export function createDarkMode(app) {
const prefersDark = ref(false);
const setting = ref('auto');

const isDark = computed(
() =>
setting.value === 'dark' ||
(prefersDark.value && setting.value !== 'light')
);
const toggleDark = () => {
setting.value = setting.value === 'dark' ? 'light' : 'dark';
localStorage.setItem('color-scheme', setting.value);
};

prefersDark.value =
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches;
setting.value = localStorage.getItem('color-scheme') || 'auto';

app.provide('is-dark', { isDark, toggleDark });
}

export function useDarkMode() {
return inject('is-dark');
}
10 changes: 10 additions & 0 deletions docs/.vitepress/theme/index.js
@@ -1,7 +1,10 @@
import { install as VueMonacoEditorPlugin } from '@guolao/vue-monaco-editor';
import defaultTheme from 'vitepress/theme';
import Layout from './Layout.vue';
import { createDialect } from './dialect';
import { createDarkMode } from './dark-mode';
import SqlOutput from './SqlOutput.vue';
import Playground from './Playground.vue';
import './styles.css';

// @todo: hack, vite.config.ts define option seem not to work
Expand All @@ -15,6 +18,13 @@ export default {

enhanceApp({ app }) {
createDialect(app);
createDarkMode(app);
app.component('SqlOutput', SqlOutput);
app.component('Playground', Playground);
app.use(VueMonacoEditorPlugin, {
paths: {
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs',
},
});
},
};
24 changes: 24 additions & 0 deletions docs/.vitepress/theme/styles.css
Expand Up @@ -122,3 +122,27 @@ a.header-anchor {
.language-sql code {
color: #ccc;
}

.split {
display: flex;
}
.split-vertical {
flex-direction: column;
}
.split-horizontal {
flex-direction: row;
}
.gutter {
background-color: var(--c-divider);
background-repeat: no-repeat;
background-position: 50%;
flex-shrink: 0;
}
.gutter.gutter-vertical {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
cursor: row-resize;
}
.gutter.gutter-horizontal {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
cursor: col-resize;
}

0 comments on commit 6333f5e

Please sign in to comment.