diff --git a/package-lock.json b/package-lock.json
index a25330e..5ebd4c4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"boxicons": "^2.1.4",
"core-js": "^3.8.3",
"crypto-js": "^4.1.1",
+ "marked": "^11.1.1",
"node-uuid": "^1.4.8",
"vue": "^3.2.13",
"vue-router": "^4.2.5",
@@ -7695,6 +7696,17 @@
"node": ">=8"
}
},
+ "node_modules/marked": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-11.1.1.tgz",
+ "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/mdn-data": {
"version": "2.0.14",
"resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz",
diff --git a/package.json b/package.json
index af74c25..fbf0bf4 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"boxicons": "^2.1.4",
"core-js": "^3.8.3",
"crypto-js": "^4.1.1",
+ "marked": "^11.1.1",
"node-uuid": "^1.4.8",
"vue": "^3.2.13",
"vue-router": "^4.2.5",
diff --git a/src/App.vue b/src/App.vue
index bbad2e2..2f07fca 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,8 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/js/history.js b/src/js/history.js
new file mode 100644
index 0000000..09bb0b5
--- /dev/null
+++ b/src/js/history.js
@@ -0,0 +1,52 @@
+const limit = 10;
+export default class _history{
+ constructor(){
+ this.histories = [];
+ let histories = localStorage.getItem("histories");
+ if (histories) {
+ this.histories = JSON.parse(histories);
+ }
+ }
+ save(){
+ localStorage.setItem('historties',JSON.stringify(this.histories));
+ }
+ get length(){
+ return this.histories.length;
+ }
+ get top(){
+ return this.histories[this.histories.length-1];
+ }
+ use(index) {
+ if(this.histories.length > index){
+ let history = this.histories.splice(index,1);
+ this.histories = [history].concat(this.histories);
+ return true;
+ }
+ else return false;
+ }
+ del(index){
+ this.histories.splice(index,1);
+ }
+ add(localsets,onlinesets,settings){
+ let data = {
+ localsets,onlinesets,settings,
+ current:0
+ };
+ if(settings.shuffle){
+ data.settings.seed = (new Date()).getTime();
+ }
+ this.histories = [data].concat(this.histories);
+ }
+ count(){
+ if(this.histories.length>0){
+ this.histories[0].current++;
+ }
+ }
+ async init_recite(callback){
+ if(typeof callback === 'function'){
+ callback();
+ }
+ }
+}
+
+// {"checkedSets":[],"onlineSets":["d8dbc5a0-7d63-11ee-b3a5-cdb8688a6b1b"],"seed":1704712586455}
\ No newline at end of file
diff --git a/src/js/wordsets.js b/src/js/wordsets.js
new file mode 100644
index 0000000..ca63dd3
--- /dev/null
+++ b/src/js/wordsets.js
@@ -0,0 +1,154 @@
+import uuid from 'node-uuid';
+
+export default class _wordset {
+ constructor() {
+ this.sets = {};
+ let wordsets = localStorage.getItem("wordsets");
+ if (wordsets) {
+ this.sets = JSON.parse(wordsets);
+ }
+ }
+ save() {
+ localStorage.setItem("wordsets", JSON.stringify(this.sets));
+ }
+ get _inner() {
+ return this.sets;
+ }
+ get _firstClass(){
+ return Object.keys(this.sets)[0] || null;
+ }
+ get _allclass(){
+ return Object.keys(this.sets);
+ }
+ get _allsets(){
+ return Object.values(this.sets);
+ }
+ getClass(class_name) {
+ if (this.sets[class_name]) {
+ return this.sets[class_name];
+ }
+ else return null;
+ }
+ getSetStatus(class_name,id){
+ let set_class = this.getClass(class_name);
+ if(set_class){
+ for(let i of set_class){
+ if(i.id === id){
+ return i;
+ }
+ }
+ }
+ return null;
+ }
+ getSet(id) {
+ let sets = JSON.parse(localStorage.getItem(id));
+ if (sets) {
+ return sets;
+ }
+ else return [];
+ }
+ delSet(class_name, index) {
+ let set_class = this.sets[class_name];
+ if (set_class) {
+ if (set_class[index]) {
+ localStorage.removeItem(set_class[index].id);
+ this.sets[class_name].splice(index, 1);
+ if (!this.sets[class_name].length) {
+ delete this.sets[class_name];
+ }
+ localStorage.setItem("wordsets", JSON.stringify(this.sets));
+ return true;
+ }
+ }
+ return false;
+ }
+ addSet(class_name,name) {
+ if (!this.sets[class_name]) {
+ this.sets[class_name] = [];
+ }
+ let id = uuid.v1();
+ let time = (new Date()).getTime()
+ this.sets[class_name].push({
+ name: name,
+ id: id,
+ created: time,
+ });
+ localStorage.setItem(id, JSON.stringify([]));
+ this.save();
+ return;
+ }
+ saveSet(id,data){
+ localStorage.setItem(id, JSON.stringify(data));
+ }
+ renameSet(class_name,id,new_name){
+ let set_class = this.getClass(class_name);
+ if(set_class){
+ for(let i of set_class){
+ if(i.id === id){
+ i.name = new_name;
+ this.save();
+ return;
+ }
+ }
+ }
+ }
+ async import_set(callback){
+ let [fileHandle] = await window.showOpenFilePicker({
+ types: [
+ {
+ description: "JSON file",
+ accept: {
+ 'text/json': ['.json'],
+ },
+ },
+ ],
+ });
+ let file = await fileHandle.getFile();
+ let data = JSON.parse(await file.text());
+ let cnt = 0;
+ for (let i of Object.keys(data.wordsets)) {
+ for (let j of data.wordsets[i]) {
+ if (!localStorage.getItem(j.id)) {
+ if (!this.sets[i]) this.sets[i] = [];
+ this.sets[i].push(j);
+ localStorage.setItem(j.id, data.words[j.id]);
+ cnt++;
+ }
+ }
+ }
+ this.save();
+ if(typeof callback === "function"){
+ callback(cnt);
+ }
+ }
+ async export_set(callback) {
+ let fileHandle = await window.showSaveFilePicker({
+ types: [
+ {
+ description: "JSON file",
+ accept: {
+ 'text/json': ['.json'],
+ },
+ },
+ ],
+ });
+ let writestream = await fileHandle.createWritable();
+ let data = {
+ wordsets: this.sets,
+ words: {}
+ };
+ let cnt = 0;
+ for (let i of Object.values(this.sets)) {
+ for (let j of i) {
+ let temp = localStorage.getItem(j.id);
+ data.words[j.id] = temp;
+ cnt++;
+ }
+ }
+ writestream.write(JSON.stringify(data));
+ writestream.close();
+ if(typeof callback === "function"){
+ callback(cnt);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/router.js b/src/router.js
index 54cf53a..5b09868 100644
--- a/src/router.js
+++ b/src/router.js
@@ -2,14 +2,16 @@ import {createRouter,createWebHashHistory} from 'vue-router'
const manage = ()=>import('./components/Manage.vue');
const editor = ()=>import('./components/manage/Editor.vue');
const home = ()=>import("./components/Home.vue");
-const recite = ()=>import('./components/Recite.vue');
+const recite = ()=>import('./components/recite/recite.vue');
const setlist = ()=>import('./components/manage/SetList.vue');
const newset = ()=>import('./components/manage/NewSet.vue');
const display = ()=>import('./components/manage/Display.vue');
+const select = ()=>import('./components/recite/select.vue')
const routes = [
{ path: '/', component: home },
- { path: '/recite', component: recite },
+ { path: '/select',component:select},
+ { path:'/recite',component:recite},
{ path: '/manage', component: manage,
children:[
{path: '',component:setlist},