Add VueBuilder and vue files

This commit is contained in:
the1812 2019-08-29 20:53:27 +08:00
parent 7dcecc88d3
commit 237f3d591b
11 changed files with 229 additions and 86 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -29,6 +29,7 @@ namespace BilibiliEvolved.Build
.BuildClient()
.BuildPreview()
.BuildMaster()
.BuildVue()
.BuildTypeScripts()
.BuildSass()
.BuildResources()

View File

@ -31,7 +31,11 @@ namespace BilibiliEvolved.Build
});
Console.Write(tsc.Run().Trim());
Parallel.ForEach(changedFiles.Select(f => ".ts-output/" + f.Replace(".ts", ".js").Replace($"src{Path.DirectorySeparatorChar}", "")), file => {
var min = uglifyJs.Minify(File.ReadAllText(file));
var text = RegexReplacer.Replace(File.ReadAllText(file), @"import\(\(\(\)\s*=>\s*(.*)\)\(\)\)", match => {
Console.WriteLine($"import({match.Groups[1].Value})");
return $"import({match.Groups[1].Value})";
});
var min = uglifyJs.Minify(text);
var minFile = ResourceMinifier.GetMinimizedFileName(file);
File.WriteAllText(minFile, min);
WriteHint($"\t=> {minFile}");

View File

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Threading.Tasks;
namespace BilibiliEvolved.Build
{
sealed class VueBuildException : Exception
{
public VueBuildException(string message) : base(message) {}
}
partial class ProjectBuilder
{
public ProjectBuilder BuildVue()
{
var files = ResourceMinifier.GetFiles(file =>
file.FullName.Contains(@"src\") &&
file.Extension == ".vue"
);
using (var cache = new BuildCache())
{
var changedFiles = files.Where(file => !cache.Contains(file)).ToArray();
if (changedFiles.Any())
{
Parallel.ForEach(changedFiles, file =>
{
cache.AddCache(file);
WriteInfo($"Vue build: {file}");
var source = File.ReadAllText(file);
var compiledText = new StringBuilder("");
{
var regex = @"<template\s*(lang=""(.+)"")?\s*>([^\0]*)</template>";
var match = new Regex(regex).Match(source);
if (match is null)
{
throw new VueBuildException($"Missing <template> in {file}.");
}
if (match.Groups.Count >= 4 && match.Groups[2].Value.ToLowerInvariant() != "html")
{
throw new VueBuildException($"{file}: Unsupported template lang: {match.Groups[2].Value.ToLowerInvariant()}");
}
var index = match.Groups.Count >= 4 ? 4 : 1;
compiledText.AppendLine($"const template = /*html*/`{match.Groups[index].Value}`");
}
{
var regex = @"<script\s*(lang=""(.+)"")?\s*>([^\0]*)</script>";
var match = new Regex(regex).Match(source);
if (match is null)
{
throw new VueBuildException($"Missing <script> in {file}.");
}
var contentIndex = match.Groups.Count >= 4 ? 4 : 1;
var content = match.Groups[contentIndex].Value;
var lang = match.Groups.Count >= 4 ? match.Groups[2].Value.ToLowerInvariant() : "js";
if (lang == "js" || lang == "javascript")
{
var jsc = new UglifyJs();
var result = jsc.Run(content);
}
else if (lang == "ts" || lang == "typescript")
{
}
else
{
throw new VueBuildException($"{file}: Unsupported script lang: {lang}");
}
}
{
var regex = @"<style\s*(lang=""(.+)"")?\s*>([^\0]*)</style>";
var match = new Regex(regex).Match(source);
if (match != null)
{
var contentIndex = match.Groups.Count >= 4 ? 4 : 1;
var content = match.Groups[contentIndex].Value;
var lang = match.Groups.Count >= 4 ? match.Groups[2].Value.ToLowerInvariant() : "css";
if (lang == "css")
{
}
else if (lang == "scss")
{
}
else
{
throw new VueBuildException($"{file}: Unsupported style lang: {lang}");
}
}
}
});
}
cache.SaveCache();
}
WriteSuccess("Vue build complete.");
return this;
}
}
}

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -114,54 +114,6 @@ body.dark .download-video {
padding-top: 12px;
font-size: 10pt;
}
.v-dropdown {
position: relative;
background-color: #8884;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
min-width: 100px;
}
.v-dropdown .dropdown-menu {
transform-origin: top;
transform: scaleY(0) translateX(-50%);
position: absolute;
top: calc(100% + 2px);
left: 50%;
background-color: var(--download-video-background);
z-index: 1;
transition: .2s cubic-bezier(0.6, -0.28, 0.74, 0.05);
box-shadow: rgba(0,0,0,0.2) 0 4px 8px 0px;
}
.v-dropdown .dropdown-menu.opened {
transform: scaleY(1) translateX(-50%);
transition-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
.v-dropdown .dropdown-menu li {
padding: 4px 8px;
white-space: nowrap;
min-width: 80px;
text-align: center;
cursor: pointer;
color: var(--download-video-foreground);
background-color: transparent;
}
.v-dropdown .dropdown-menu li:hover {
background-color: rgba(0,0,0,0.16);
}
.v-dropdown .mdi-chevron-down {
font-size: 16pt;
line-height: 1;
transform: rotate(0deg);
}
.v-dropdown .dropdown-menu.opened ~ .mdi-chevron-down {
transform: rotate(180deg);
}
.v-dropdown .selected {
user-select: none;
padding: 4px 8px;
}
.download-video .tabs {
display: flex;
padding-top: 12px;

View File

@ -496,35 +496,8 @@ async function loadWidget() {
}, { once: true })
}
async function loadPanel() {
Vue.component('v-dropdown', {
template: /*html*/`
<div class="v-dropdown" v-on:click="toggleDropdown()">
<span class="selected">{{value}}</span>
<ul class="dropdown-menu" v-bind:class="{opened: dropdownOpen}">
<li v-for="item in items" v-bind:key="item" v-bind:data-value="item" v-on:click="select(item)">{{item}}</li>
</ul>
<i class="mdi mdi-chevron-down"></i>
</div>
`,
props: [
'items',
'value'
],
data() {
return {
dropdownOpen: false,
}
},
methods: {
toggleDropdown() {
this.dropdownOpen = !this.dropdownOpen
},
select(item: string) {
this.$emit('update:value', item)
this.$emit('change', item)
},
},
})
const VueDropDown = await import((() => './v-dropdown.vue')())
Vue.component('v-dropdown', VueDropDown)
Vue.component('v-checkbox', {
template: /*html*/`
<div class="v-checkbox" v-on:click="toggleCheck()" v-bind:class="{checked: checked}">

View File

@ -0,0 +1,79 @@
<template>
<div class="v-dropdown" @click="toggleDropdown()">
<span class="selected">{{ value }}</span>
<ul class="dropdown-menu" :class="{ opened: dropdownOpen }">
<li v-for="item in items" :key="item" :data-value="item" @click="select(item)">{{ item }}</li>
</ul>
<i class="mdi mdi-chevron-down"></i>
</div>
</template>
<script lang="ts">
export default {
props: ['items', 'value'],
data() {
return {
dropdownOpen: false
}
},
methods: {
toggleDropdown() {
this.dropdownOpen = !this.dropdownOpen
},
select(item: string) {
this.$emit('update:value', item)
this.$emit('change', item)
}
}
}
</script>
<style lang="scss">
.v-dropdown {
position: relative;
background-color: #8884;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
min-width: 100px;
.dropdown-menu {
transform-origin: top;
transform: scaleY(0) translateX(-50%);
position: absolute;
top: calc(100% + 2px);
left: 50%;
background-color: var(--download-video-background);
z-index: 1;
transition: 0.2s cubic-bezier(0.6, -0.28, 0.74, 0.05);
box-shadow: rgba(0, 0, 0, 0.2) 0 4px 8px 0px;
&.opened {
transform: scaleY(1) translateX(-50%);
transition-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
li {
padding: 4px 8px;
white-space: nowrap;
min-width: 80px;
text-align: center;
cursor: pointer;
color: var(--download-video-foreground);
background-color: transparent;
&:hover {
background-color: rgba(0, 0, 0, 0.16);
}
}
}
.mdi-chevron-down {
font-size: 16pt;
line-height: 1;
transform: rotate(0deg);
}
.dropdown-menu.opened ~ .mdi-chevron-down {
transform: rotate(180deg);
}
.selected {
user-select: none;
padding: 4px 8px;
}
}
</style>