Skip to content

Commit

Permalink
feat: add template-explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
Dmaziyo committed Feb 16, 2023
1 parent f164aa8 commit 38956a3
Show file tree
Hide file tree
Showing 20 changed files with 1,919 additions and 33 deletions.
5 changes: 5 additions & 0 deletions src/compiler/codegen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function generate(ast) {
return `
console.log('hello world')
`
}
7 changes: 7 additions & 0 deletions src/compiler/compile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { generate } from './codegen'
import { baseParse } from './parse'

export function compile(template) {
const ast = baseParse(template)
return generate(ast)
}
88 changes: 88 additions & 0 deletions src/examples/commits.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<script src="../../dist/mini-vue.js"></script>

<div id="demo">
<h1>Latest MiniVue.js Commits</h1>
<span v-for="branch in branches">
<input
type="radio"
:id="branch"
:value="branch"
name="branch"
v-model="currentBranch.value"
/>
<label :for="branch">{{ branch }}</label>
</span>
<p>leaon4/mini-vue3@{{ currentBranch.value }}</p>
<ul>
<li v-for="({ html_url, sha, author, commit }) in commits.value">
<a :href="html_url" target="_blank" class="commit"
>{{ sha.slice(0, 7) }}</a
>
- <span class="message">{{ truncate(commit.message) }}</span><br />
by
<span class="author"
><a :href="author.html_url" target="_blank"
>{{ commit.author.name }}</a
></span
>
at <span class="date">{{ formatDate(commit.author.date) }}</span>
</li>
</ul>
</div>

<script>
const { createApp, ref, effect } = MiniVue;
const API_URL = `https://api.github.com/repos/leaon4/mini-vue3/commits?per_page=3&sha=`;

const truncate = (v) => {
const newline = v.indexOf('\n');
return newline > 0 ? v.slice(0, newline) : v;
};

const formatDate = (v) => v.replace(/T|Z/g, ' ');

var app = createApp({
setup() {
const currentBranch = ref('master');
const commits = ref(null);

effect(() => {
fetch(`${API_URL}${currentBranch.value}`)
.then((res) => res.json())
.then((data) => {
commits.value = data;
});
});

return {
branches: ['master', 'template-explorer'],
currentBranch,
commits,
truncate,
formatDate,
};
},
});
app.mount('#demo');
</script>

<style>
#demo {
font-family: 'Helvetica', Arial, sans-serif;
}

a {
text-decoration: none;
color: #f66;
}

li {
line-height: 1.5em;
margin-bottom: 20px;
}

.author,
.date {
font-weight: bold;
}
</style>
188 changes: 188 additions & 0 deletions src/examples/grid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<script src="../../dist/mini-vue.js"></script>

<!-- DemoGrid component template -->
<script type="text/x-template" id="grid-template">
<table v-if="filteredData.value.length">
<thead>
<tr>
<th v-for="key in columns"
@click="sortBy(key)"
:class="state.sortKey == key ? 'active' : ''">
{{ capitalize(key) }}
<span :class="'arrow ' + (state.sortOrders[key] > 0 ? 'asc' : 'dsc')">
</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="entry in filteredData.value">
<td v-for="key in columns">
{{entry[key]}}
</td>
</tr>
</tbody>
</table>
<p v-else>No matches found.</p>
</script>
<!-- DemoGrid component script -->
<script>
const { reactive, computed, ref } = MiniVue;

const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);

const DemoGrid = {
template: '#grid-template',
props: ['data', 'columns', 'filterKey'],
setup(props) {
const state = reactive({
sortKey: '',
sortOrders: props.columns.reduce((o, key) => ((o[key] = 1), o), {}),
});

const filteredData = computed(() => {
let { data, filterKey } = props;
if (filterKey) {
filterKey = filterKey.toLowerCase();
data = data.filter((row) => {
return Object.keys(row).some((key) => {
return String(row[key]).toLowerCase().indexOf(filterKey) > -1;
});
});
}
const { sortKey } = state;
if (sortKey) {
const order = state.sortOrders[sortKey];
data = data.slice().sort((a, b) => {
a = a[sortKey];
b = b[sortKey];
return (a === b ? 0 : a > b ? 1 : -1) * order;
});
}
return data;
});

function sortBy(key) {
state.sortKey = key;
state.sortOrders[key] *= -1;
}

return {
state,
filteredData,
sortBy,
capitalize,
};
},
};
</script>

<!-- App template (in DOM) -->
<div id="demo">
<form id="search">
Search <input name="query" v-model="searchQuery.value" />
</form>
<demo-grid
:data="gridData"
:columns="gridColumns"
:filter-key="searchQuery.value"
>
</demo-grid>
</div>
<!-- App script -->
<script>
MiniVue.createApp({
components: {
DemoGrid,
},
setup() {
return {
// 不同于原版,这里需要用ref
// 可能是因为v-model机制不同,原版修改的是经过props响应化后的响应式对象,
// 而这里修改的是普通值,因此要显示定义为ref
searchQuery: ref(''),
gridColumns: ['name', 'power'],
gridData: [
{
name: 'Chuck Norris',
power: Infinity,
},
{
name: 'Bruce Lee',
power: 9000,
},
{
name: 'Jackie Chan',
power: 7000,
},
{
name: 'Jet Li',
power: 8000,
},
],
};
},
}).mount('#demo');
</script>

<style>
body {
font-family: Helvetica Neue, Arial, sans-serif;
font-size: 14px;
color: #444;
}

table {
border: 2px solid #42b983;
border-radius: 3px;
background-color: #fff;
}

th {
background-color: #42b983;
color: rgba(255, 255, 255, 0.66);
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

td {
background-color: #f9f9f9;
}

th,
td {
min-width: 120px;
padding: 10px 20px;
}

th.active {
color: #fff;
}

th.active .arrow {
opacity: 1;
}

.arrow {
display: inline-block;
vertical-align: middle;
width: 0;
height: 0;
margin-left: 5px;
opacity: 0.66;
}

.arrow.asc {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid #fff;
}

.arrow.dsc {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #fff;
}
</style>
22 changes: 22 additions & 0 deletions src/examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Expamels</title>
</head>

<body>
<h1>Expamels</h1>
<ul>
<li><a href="./commits.html">commits</a></li>
<li><a href="./grid.html">grid</a></li>
<li><a href="./markdown.html">markdown</a></li>
<li><a href="./todomvc.html">todomvc</a></li>
<li><a href="./tree.html">tree</a></li>
<li><a href="./vModel.html">vModel</a></li>
<li><a href="./template-explorer">template-explorer</a></li>
</ul>
</body>
</html>
71 changes: 71 additions & 0 deletions src/examples/markdown.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script src="./node_modules/marked/marked.min.js"></script>
<script src="./node_modules/lodash/lodash.min.js"></script>
<script src="../../dist/mini-vue.js"></script>

<div id="editor">
<textarea :value="input.value" @input="update"></textarea>
<div v-html="output.value"></div>
</div>

<script>
const { ref, computed } = MiniVue;

MiniVue.createApp({
setup() {
const input = ref('# hello');
const output = computed(() =>
marked(input.value, {
sanitize: true,
})
);
const update = _.debounce((e) => {
input.value = e.target.value;
}, 50);

return {
input,
output,
update,
};
},
}).mount('#editor');
</script>

<style>
html,
body,
#editor {
margin: 0;
height: 100%;
font-family: 'Helvetica Neue', Arial, sans-serif;
color: #333;
}

textarea,
#editor div {
display: inline-block;
overflow: auto;
width: 50%;
height: 100%;
vertical-align: top;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0 20px;
}

textarea {
border: none;
border-right: 1px solid #ccc;
resize: none;
outline: none;
background-color: #f6f6f6;
font-size: 14px;
font-family: 'Monaco', courier, monospace;
padding: 20px;
}

code {
color: #f66;
}
</style>
Loading

0 comments on commit 38956a3

Please sign in to comment.