Skip to content

Instantly share code, notes, and snippets.

@yue4u
Created September 16, 2019 16:57
Show Gist options
  • Select an option

  • Save yue4u/e4103a1e32bba8b4693e2e27e1499ed8 to your computer and use it in GitHub Desktop.

Select an option

Save yue4u/e4103a1e32bba8b4693e2e27e1499ed8 to your computer and use it in GitHub Desktop.
// Server API makes it possible to hook into various parts of Gridsome
// on server-side and add custom data to the GraphQL data layer.
// Learn more: https://gridsome.org/docs/server-api
// Changes here require a server restart.
// To restart press CTRL + C in terminal and run `gridsome develop`
const syllabus = require("../data/syllabus.json");
const search = require("../data/search.json");
const { createHash } = require("crypto")
const nodeExternals = require('webpack-node-externals')
const hash = (text) => {
return createHash('md5').update(text).digest('hex').slice(0, 8)
}
const hashStore = {}
const uniqueHash = (text) => {
let hashString = '';
while (true) {
hashString = hash(text)
if (hashString in hashStore) {
hashString = hash(hashString)
} else {
hashStore[text] = hashString
hashStore[hashString] = text
break;
}
}
return hashString;
}
const upper = (text) => text.slice(0, 1).toUpperCase() + text.slice(1);
module.exports = function (api) {
api.chainWebpack((config, { isServer }) => {
if (isServer) {
config.externals([
nodeExternals({
whitelist: [/^vuetify/]
})
])
}
})
api.loadSource(({ addContentType, createReference, addReference }) => {
const subjectType = addContentType({
typeName: "Subject",
route: "/subject/:id"
});
const detailType = addContentType({
typeName: "Detail"
});
const teacherType = addContentType({
typeName: "Teacher",
route: "/teacher/:id"
});
const categoryType = addContentType({
typeName: "Category",
route: "/category/:id"
});
const fieldType = addContentType({
typeName: "Field",
route: "/field/:id"
});
const yearType = addContentType({
typeName: "Year",
route: "/year/:id"
});
const teachers = {};
const categories = {};
const years = {};
const fields = {};
const gather = (collection, key, code) => {
if (key in collection) {
collection[key].subjects.push(code);
} else {
collection[key] = {
subjects: [code]
};
}
};
const create = (contentTypeName, contentType, collection) => {
Object.entries(collection).map(([key, val]) => {
const hash = uniqueHash(`${contentTypeName}:${key}`)
collection[key].id = hash;
contentType.addNode({
id: hash,
name: key || "不明",
...val,
subjects: {
totalCount: val.subjects.length,
node: createReference("Subject", val.subjects)
}
});
});
};
syllabus.data.map(subject => {
gather(teachers, subject.teacher, subject.code);
gather(categories, subject.category, subject.code);
gather(years, subject.year, subject.code);
gather(fields, subject.field, subject.code);
});
create('teacher', teacherType, teachers);
create('category', categoryType, categories);
create('year', yearType, years);
create('field', fieldType, fields);
syllabus.data.map(subject => {
const detail = { ...subject.detail };
delete subject.detail;
const detailNode = detailType.addNode({
...detail,
path: `subject/${subject.code}/detail`
});
const subjectRef = Object.fromEntries(
['teacher', 'category', 'year', 'field'].map(typeName => {
const hash = hashStore[`${typeName}:${subject[typeName]}`];
const typeNameUpper = upper(typeName);
return [typeName, createReference(typeNameUpper, hash)]
}))
subjectType.addNode({
...subject,
...subjectRef,
id: subject.code,
detail: createReference(detailNode),
teacher: createReference("Teacher", teachers[subject.teacher].id),
categories: createReference("Categoy", categories[subject.category].id),
year: createReference("Year", years[subject.year].id)
});
});
const emailType = addContentType({
typeName: "Email"
});
const emailMap = {}
search.data.map(item => {
/**
* @see https://stackoverflow.com/a/1373724
*/
const emailMatched = [...item.text.matchAll(
/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi)].map(match => match[1])
const subject = syllabus.data.find(subject => item.id === subject.code)
if (subject && emailMatched.length) {
for (let email of emailMatched) {
if (!Array.isArray(emailMap[subject.teacher])) {
emailMap[subject.teacher] = []
}
if (!emailMap[subject.teacher].includes(email)) {
emailMap[subject.teacher].push({
link: email,
subject: createReference('Subject', subject.code)
})
}
}
}
})
Object.entries(emailMap).map(([teacher, item]) => {
const teacherID = hashStore[`teacher:${teacher}`];
emailType.addNode({
id: hash(`email:${teacher}`),
teacher: createReference('Teacher', teacherID),
addresses: item
});
})
});
//api.createPages(({ createPage }) => {
// Use the Pages API here: https://gridsome.org/docs/pages-api
//});
};
// This is the main.js file. Import global CSS and scripts here.
// The Client API can be used here. Learn more: gridsome.org/docs/client-api
import DefaultLayout from "~/layouts/Default.vue";
import SyllabusButton from "~/components/SyllabusButton.vue";
import SyllabusList from "~/components/SyllabusList.vue";
import SyllabusStatistics from "~/components/SyllabusStatistics.vue";
import SyllabusSection from "~/components/SyllabusSection.vue";
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
export default function (Vue, { router, isClient, appOptions, head }) {
Vue.component("syllabus-layout", DefaultLayout);
Vue.component("syllabus-button", SyllabusButton);
Vue.component("syllabus-list", SyllabusList);
Vue.component("syllabus-statistics", SyllabusStatistics);
Vue.component("syllabus-section", SyllabusSection);
head.link.push({
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/icon?family=Material+Icons'
})
Vue.use(Vuetify)
appOptions.vuetify = new Vuetify(opts);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment