Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add migrator #375

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Command line interface for Tuture",
"version": "0.1.0",
"bin": {
"tuture": "./lib/index.js"
"tuture": "./dist/index.js"
},
"type": "module",
"main": "dist/index.js",
Expand All @@ -28,6 +28,7 @@
"fs-extra": "^7.0.0",
"get-port": "^5.1.1",
"inquirer": "^6.0.0",
"isbinaryfile": "^5.0.0",
"micromatch": "^3.1.10",
"open": "^6.4.0",
"prosemirror-markdown": "1.5.1",
Expand All @@ -42,9 +43,9 @@
"@oclif/dev-cli": "^1",
"@types/debug": "^4.1.7",
"@types/inquirer": "^6.5.0",
"@types/prosemirror-markdown": "1.5.2",
"@types/micromatch": "^4.0.1",
"@types/node": "^10",
"@types/prosemirror-markdown": "1.5.2",
"globby": "^10",
"rimraf": "^2.6.2",
"ts-node": "^8"
Expand Down
6 changes: 1 addition & 5 deletions packages/cli/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
Collection,
IMeta,
isCommitEqual,
ArticleNodes,
tutureSchema,
markdownSerializer,
} from '@tuture/core';
Expand Down Expand Up @@ -297,10 +296,7 @@ function articleTmpl(meta: IMeta, steps: any[]) {
.replace(/\n{3,}/g, '\n\n');
}

function generateTutorials(
collection: Collection,
articleNodes: ArticleNodes[],
) {
function generateTutorials(collection: Collection) {
const {
name,
articles,
Expand Down
12 changes: 12 additions & 0 deletions packages/cli/src/commands/destroy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Command } from 'commander';
import inquirer from 'inquirer';
import debug from 'debug';
import {
loadCollection,
deleteDocs,
deleteCollection,
} from '@tuture/local-server';

import logger from '../utils/logger.js';

Expand Down Expand Up @@ -35,6 +40,13 @@ async function doDestroy(options: DestroyOptions) {
}
}

const collection = loadCollection();
const articleIds = collection.articles.map((article) => article.id);
d('delete article ids: %o', articleIds);
await deleteDocs(articleIds);

await deleteCollection(collection.id);

logger.log('success', 'Tutorial has been destroyed!');
}

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async function doInit(options: InitOptions) {
d('cwd: %s', process.cwd());
d('options: %o', options);

const item = await getInventoryItemByPath(process.cwd());
const item = getInventoryItemByPath(process.cwd());
d('inventory item: %o', item);
if (item) {
logger.log('success', 'Tuture tutorial has already been initialized!');
Expand Down Expand Up @@ -120,8 +120,8 @@ async function doInit(options: InitOptions) {
collection.version = SCHEMA_VERSION;
d('init collection: %O', collection);

await saveToInventory(process.cwd(), collection);
await saveCollection(collection);
saveToInventory(process.cwd(), collection);
saveCollection(collection);

logger.log('success', 'Tuture tutorial has been initialized!');
}
Expand Down
62 changes: 27 additions & 35 deletions packages/cli/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,34 @@ export async function initNodes(ignoredFiles?: string[]): Promise<INode[]> {
// filter out commits whose commit message starts with 'tuture:'
.filter(({ message }) => !message.startsWith('tuture:'));

const nodeProms: Promise<INode[]>[] = logs.map(
async ({ message, hash }, index) => {
const files = await readDiff(hash);
const delimiterAttrs = { commit: hash };
const stepAttrs = {
id: randHex(32),
name: message,
const nodeProms: Promise<INode[]>[] = logs.map(async ({ message, hash }) => {
const files = await readDiff(hash);
const delimiterAttrs = { commit: hash };
const fileNodes = await Promise.all(
files.map(async (diffFile) => {
const hidden = ignoredFiles?.some((pattern) =>
mm.isMatch(diffFile.to!, pattern),
);
return await newEmptyFile(hash, diffFile, Boolean(hidden));
}),
);
return [
{ type: 'step_start', attrs: delimiterAttrs, content: [] },
newStepTitle(hash, [{ type: 'text', text: message }]),
newEmptyExplain({
level: 'step',
pos: 'pre',
commit: hash,
order: index,
};
const fileNodes = await Promise.all(
files.map(async (diffFile) => {
const hidden = ignoredFiles?.some((pattern) =>
mm.isMatch(diffFile.to!, pattern),
);
return await newEmptyFile(hash, diffFile, Boolean(hidden));
}),
);
return [
{ type: 'step_start', attrs: delimiterAttrs, content: [] },
newStepTitle(hash, [{ type: 'text', text: message }]),
newEmptyExplain({
level: 'step',
pos: 'pre',
commit: hash,
}),
...fileNodes.flat(),
newEmptyExplain({
level: 'step',
pos: 'post',
commit: hash,
}),
{ type: 'step_end', attrs: delimiterAttrs, content: [] },
];
},
);
}),
...fileNodes.flat(),
newEmptyExplain({
level: 'step',
pos: 'post',
commit: hash,
}),
{ type: 'step_end', attrs: delimiterAttrs, content: [] },
];
});

const nodes = await Promise.all(nodeProms);
return nodes.flat();
Expand Down
24 changes: 23 additions & 1 deletion packages/cli/src/utils/node.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import debug from 'debug';
import { isBinaryFile } from 'isbinaryfile';
import {
IText,
INode,
Expand All @@ -11,7 +12,6 @@ import {
getHiddenLines,
Collection,
Article,
isStepTitle,
} from '@tuture/core';
import { readFileAtCommit } from '@tuture/local-server';

Expand Down Expand Up @@ -47,6 +47,7 @@ export async function newEmptyFile(
diffFile: DiffFile,
hidden: boolean,
): Promise<INode[]> {
// TODO: handle delete case (the file no longer exists!)
const file = diffFile.to!;
const diffBlock: IDiffBlock = {
type: 'diff_block',
Expand All @@ -62,6 +63,27 @@ export async function newEmptyFile(
hiddenLines: getHiddenLines(diffFile),
},
};

if (await isBinaryFile(file)) {
// Binary files are hidden by default.
diffBlock.attrs.hidden = true;
} else {
const code = diffFile.deleted
? ''
: (await readFileAtCommit(commit, file)) || '';
const originalCode = diffFile.new
? ''
: (await readFileAtCommit(`${commit}~1`, file)) || '';

// Skip files with too lengthy diff
// TODO: Add it to the config
if (code.length <= 10000 || originalCode.length <= 10000) {
// If not binary, try reading diff.
diffBlock.attrs.code = code;
diffBlock.attrs.originalCode = originalCode;
}
}

d('diffBlock: %o', diffBlock);
const delimiterAttrs = {
commit,
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './interfaces.js';
export * from './compat.js';
export * from './utils.js';
export * from './diff.js';
export * from './version.js';
Expand Down
30 changes: 30 additions & 0 deletions packages/core/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,36 @@ export const tutureSchema = new Schema({
},
},

ordered_list: {
attrs: {
order: {
default: 1,
},
},
content: 'list_item+',
group: 'block',
parseDOM: [{ tag: 'ol' }],
toDOM: (node) =>
node.attrs.order === 1
? ['ol', 0]
: ['ol', { start: node.attrs.order }, 0],
},

bullet_list: {
content: 'list_item+',
group: 'block',
parseDOM: [{ tag: 'ul' }],
toDOM: () => ['ul', 0],
},

list_item: {
content: 'paragraph block*',
defining: true,
draggable: false,
parseDOM: [{ tag: 'li' }],
toDOM: () => ['li', 0],
},

explain: {
content: 'block+',
group: 'block',
Expand Down
2 changes: 1 addition & 1 deletion packages/editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
"smooth-scroll-into-view-if-needed": "^1.1.32",
"tiptap": "1.32.2",
"tiptap-extensions": "1.35.2",
"v-code-diff": "^0.3.8",
"vue": "^2.6.11",
"vue-code-diff": "^1.2.0",
"vue-demi": "^0.7.4",
"vue-router": "^3.2.0",
"vuex": "^3.4.0",
Expand Down
9 changes: 6 additions & 3 deletions packages/editor/src/editor/components/DiffView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
class="whitespace-normal"
:old-string="originalCode"
:new-string="code"
:file-name="filename"
:output-format="outputFormat"
:context="10"
:fileName="filename"
:outputFormat="outputFormat"
/>
<a-modal :visible="false">
<MonacoEditor
Expand All @@ -33,13 +34,15 @@

<script setup>
import { defineComponent } from 'vue-demi';
import CodeDiff from 'vue-code-diff';

// import { CodeDiff } from 'v-code-diff';
import MonacoEditor from './MonacoEditor.vue';

export default defineComponent({
props: ['node', 'updateAttrs', 'view', 'editor'],
components: {
// CodeDiff,
CodeDiff,
MonacoEditor,
},
data() {
Expand Down
3 changes: 0 additions & 3 deletions packages/editor/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import {
faArrowRight,
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import CodeDiff from 'v-code-diff';

import App from './App.vue';
import router from './router';
Expand Down Expand Up @@ -120,8 +119,6 @@ Vue.use(Switch);
Vue.use(Popover);
Vue.use(Popconfirm);

Vue.use(CodeDiff);

Vue.prototype.$message = message;

// 捕获 monaco 的 unhandledrejection
Expand Down
20 changes: 3 additions & 17 deletions packages/local-server/src/utils/collection.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import debug from 'debug';
import fs from 'fs-extra';
import path from 'path';
import { INode, Collection, SCHEMA_VERSION } from '@tuture/core';
import { Collection } from '@tuture/core';
import { LowSync, JSONFileSync } from 'lowdb';

import { getCollectionsRoot } from './path.js';
import { getInventoryItemByPath } from './inventory.js';
import { getInventoryItemByPath, removeFromInventory } from './inventory.js';

const d = debug('tuture:local-server:collection');

Expand Down Expand Up @@ -54,21 +54,6 @@ export function getCollectionDb(collectionId?: string) {
*/
export function loadCollection(collectionId?: string) {
const db = getCollectionDb(collectionId);

// if (collection.version !== 'v1' && collection.version !== SCHEMA_VERSION) {
// throw new Error(
// 'incompatible collection version, please contact [email protected] to fix it',
// );
// }

// if (collection.version === 'v1') {
// let [collectionV2, stepDocs] = convertV1ToV2(collection);
// collection = collectionV2;
// collection.version = SCHEMA_VERSION;

// Object.entries(stepDocs).forEach(([id, doc]) => saveStepSync(id, doc));
// }

return db.data!;
}

Expand All @@ -84,4 +69,5 @@ export function saveCollection(collection: Collection) {

export async function deleteCollection(collectionId: string) {
await fs.remove(getCollectionPath(collectionId));
removeFromInventory(collectionId);
}
6 changes: 4 additions & 2 deletions packages/local-server/src/utils/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export async function saveDoc(doc: any) {
await ldb.destroy();
}

export async function deleteDoc(docId: string) {
export async function deleteDocs(docIds: string[]) {
const ldb = getDocPersistence();
await ldb.clearDocument(docId);
await Promise.all(
docIds.map(async (docId) => await ldb.clearDocument(docId)),
);
await ldb.destroy();
}
Loading