)
}
}
// -------------->> {{fileName}}.css
.main {}
// -------------->> __test__/{{fileName}}.test.tsx
import * as React from 'react';
it('{{fileName}} - render', () => {
// render(<{{fileName}} />);
// expect(...);
});
================================================
FILE: .editorconfig
================================================
# EditorConfig: http://EditorConfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .gitignore
================================================
out
node_modules
.vscode-test/
*.vsix
configViewer/configViewer.js
================================================
FILE: .prettierrc.yml
================================================
---
printWidth: 120
tabWidth: 2
useTabs: false
semi: true
singleQuote: true
trailingComma: none
bracketSpacing: true
jsxBracketSameLine: false
arrowParens: avoid
================================================
FILE: .vscodeignore
================================================
.vscode/**
.vscode-test/**
out/test/**
src/**
.gitignore
vsc-extension-quickstart.md
**/tsconfig.json
**/tslint.json
**/*.map
**/*.ts
================================================
FILE: CHANGELOG.md
================================================
# Change Log
## [0.3.0] - 2021-05-24
- Task title supports markdown now for styling, hyperlinks, simple html or even img tags.
- New Task Action: move a task to the column on the right.
## [0.2.27] - 2020-03-28
- Task Board - support multiple task lists defined in user's settings.json.
- Task Board - refresh button to reload file content.
- Task Board - checkbox is now optional (if task title doesn't have it).
- Task Board - support sub-task (task title starts with 2-space indentation).
- Task Board - task menu for: toggling sub-task; inserting emojis;
- Task Board - respect theme colors.
## [0.2.12] - 2020-03-21
- Task Board - search box
- Task Board - autofocus when creating a new task.
- Task Board - checkmark to mark a task as complete.
- Task Board Doc
## [0.2.3] - 2020-03-15
- Task Board - manage tasks and save them as TODO.md - a simple plain text file. The syntax is compatible with [Github Markdown](https://bit.ly/2wBp1Mk)
## [0.1.4] - 2020-03-10
- Output can be edited before generating files.
## [0.1.3]
- Initial release
- Follow this format - Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Duc Nguyen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Todo Kanban Board
Todo Kanban Board manages tasks and save them as [TODO.md](https://bit.ly/2JdEuET) - a simple plain text file.
## Features
- The syntax is compatible with [Github Markdown](https://bit.ly/2wBp1Mk)
- TODO.md file is portable and can be committed with Pull Requests (PRs) to git repositories.
- Support custom file name, multiple task lists.
- Checkboxes are optional (if your task titles don't have them).
- Task title can also have markdown for styling, hyperlinks, simple html or even img tags.
- Task menu: to insert a sub-task, emoji icons (like bug 🐞 blocked ❌ party 🎉 etc.).
- See also: Documentation / Guides
## Usage:
- Open Coddx Task Board:
- Bring up the Command Palette (F1), type and select: Coddx: Task Board.
- When interacting with the Task Board, TODO.md will be created or updated automatically.
- Vice versa, TODO.md can be edited manually, Task Board will load it every time (click the Refresh icon).
## Support
- For Feedbacks, Bug Reports: https://github.com/coddx-hq/coddx-alpha/issues
- Documentation: Documentation / Guides
- CHANGELOG
## Next milestone:
- Feedbacks, suggestions or ideas are welcome! Thanks.
- Check out [TODO.md](TODO.md)
================================================
FILE: TODO.md
================================================
# TODO.md Kanban Board
TODO.md Kanban Board
[TODO.md spec & Kanban Board](https://bit.ly/3fCwKfM)
### Todo
- [ ] Publish on open-vsx.org
- [ ] Get Todo\*.md files for the dropdown
- [ ] Rename Git Repos
- [ ] Update Readme, Docs
- [ ] Update all URLs
- [ ] Animate Search Input
- [ ] Support Task description
- [ ] Markdown links for File or URL
- [ ] Press _Enter_ to add the next task
### In Progress
- [ ] Task menu: add hyperlinks ?
- [ ] Smart positioning for Task Menu
- [ ] Change icon on Marketplace
- [ ] 🐞 Fix sub-task toggling for a new task
- [ ] 🐞 Bug: it flashes the default data, then loads the real data
### Done ✓
- [x] Markdown text formats 05/21/2021
- [x] New task should be at the top 05/20/2021
- [x] Dropdown option to help about adding more todo files 05/19/2021
- [x] Respect theme colors
- [x] Task menu: Insert Emojis 😊
- [x] Task menu: Toggle sub-task
- [x] Rename to Todo.md Kanban Board
- [x] Support sub-task
- [x] Optional checkbox in task title
- [x] Default to the 1st Task List
- [x] Add Help link
- [x] Multiple task lists
- [x] Add Search Box
- [x] Auto save for Task Re-ordering
- [x] Add Open File link
- [x] Split to different Doc Topics
- [x] Auto focus on New Task 2020-03-18
- [x] Check mark to mark as Done 2020-03-18
- [x] Setup coddx mailbox
================================================
FILE: docs/documentation.md
================================================
# Documentation
### Task Board - TODO.md
[Task Board Doc](task-board.md)
### Generate Files
[Generate Files Doc](generate-files.md)
================================================
FILE: docs/generate-files.md
================================================
# Generate Files
### Features
- Work with any programming languages.
- Templating syntax.
- Store templates as a single file (can be committed to git, shared with others).
- Auto-create sub-directories.
- Built-in params (fileName, date, time, etc.).
- Custom params.
- Context menu to generate files/directories from anywhere.
#### Usage:
- Open Coddx panel:
- Bring up the Command Palette (F1), type and select: Coddx: Generate Files.
- Or: right-click on a directory, select: Generate files.
- Verify Template to suit your needs. (See Docs for syntax)
- Verify the output path (relative to Project root), a new directory will be created if not existed.
- Enter the new file name to generate file(s).
### How does it work?
Coddx uses Mozilla's Templating Engine called nunjucks. Nunjucks is a powerful library, supports more advanced use cases like parameters, custom filters, etc.
### Templating Syntax
Example:
```
// -------------->> {{fileName}}.tsx
// created time: {{YYYY}}-{{MM}}-{{DD}} {{HH}}:{{mm}}
// file1 content...
// -------------->> __test__/{{fileName}}.test.tsx
// file2 content... (sub-directory will be created)
```
Built-in Template Variables:
- {{fileName}} - will be replace with the value of "File Name" field.
- {{YYYY}}, {{MM}}, {{DD}}, {{HH}}, {{mm}} - year, month, day, hours (24), minutes.
Read more: Nunjucks Templating Syntax
### Custom Variables
You can declare custom variables (Params field) in JSON format, for example:
- { "myVar": "value" } - declare `myVar`, then use it in your template like `{{myVar}}`
### Custom filters
(Coming soon)
================================================
FILE: docs/task-board.md
================================================
# Todo Kanban Board
Todo Kanban Board manages tasks and save them as [TODO.md](https://bit.ly/2JdEuET) - a simple plain text file.
## Features
- The syntax is compatible with [Github Markdown](https://bit.ly/2wBp1Mk)
- TODO.md file is portable and can be committed with Pull Requests (PRs) to git repositories.
- Support custom file name, multiple task lists.
- Checkboxes are optional (if your task titles don't have them).
- Task title can also have markdown for styling, hyperlinks, simple html or even img tags.
- Task menu: to insert a sub-task, emoji icons (like bug 🐞 blocked ❌ party 🎉 etc.).
- See also: Documentation / Guides
## TODO.md
- Tasks are synced to the markdown file using [TODO.md format](https://bit.ly/2JdEuET).
- Task Board is a bit strict about the format.
- Please follow the typical structure like in the example so it can work properly. If it fails to open, please revert or re-generate your TODO.md file to make it work again.
- For now, after making changes to TODO.md file, please click the Refresh icon (next to the board title) to reload.
- [Example of a TODO.md file](https://github.com/todomd/todo.md/blob/master/TODO.md)
## Settings
- Multiple TODO files:
- In your workspace settings.json file, add this: `"coddx.taskBoard.fileList": "TODO.md, folder/TODO-name.md"` (comma separated, use your file names)
## Tips & Tricks
- In the task title:
- You can type `#bug` or `#feat` to classify your task.
- You can type a name like `@john`, `@jane`.
- Date format can be yyyy-mm-dd
- Use the Search Box to filter for types, names, etc.
================================================
FILE: package.json
================================================
{
"name": "coddx-alpha",
"displayName": "TODO.md Kanban Board",
"description": "Coddx - a collection of tools that help developers program efficiently. Some useful features like: Kanban Board to manage project tasks in TODO.md, generating multiple files from templates quickly.",
"version": "0.2.55",
"publisher": "coddx",
"license": "MIT",
"homepage": "https://github.com/coddx-hq",
"repository": {
"type": "git",
"url": "https://github.com/coddx-hq/coddx-alpha.git"
},
"keywords": [
"todo",
"todolist",
"kanban",
"task",
"project",
"management",
"generate",
"generator",
"template",
"webdev",
"snippet",
"file"
],
"icon": "docs/media/logo.png",
"engines": {
"vscode": "^1.29.0"
},
"categories": [
"Extension Packs",
"Programming Languages",
"Snippets",
"Other"
],
"activationEvents": [
"onCommand:extension.viewconfig",
"onCommand:extension.taskboard"
],
"main": "./out/extension.js",
"contributes": {
"languages": [],
"commands": [
{
"command": "extension.viewconfig",
"title": "Generate files",
"category": "Coddx"
},
{
"command": "extension.taskboard",
"title": "TODO.md Kanban Task Board",
"category": "Coddx"
}
],
"menus": {
"explorer/context": [
{
"command": "extension.viewconfig"
}
]
}
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "npm-run-all compile:*",
"watch": "npm-run-all -p watch:*",
"compile:extension": "rm -rf out && tsc --jsx react -p ./",
"compile:views": "webpack --mode development",
"watch:extension": "tsc --jsx react -watch -p ./",
"watch:views": "webpack --watch --mode development",
"postinstall": "node ./node_modules/vscode/bin/install",
"test": "npm run compile && node ./node_modules/vscode/bin/test"
},
"devDependencies": {
"@types/marked": "^2.0.2",
"@types/mocha": "^2.2.42",
"@types/node": "^10.12.21",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"css-loader": "^3.0.0",
"npm-run-all": "^4.1.5",
"style-loader": "^0.23.1",
"ts-loader": "^6.0.4",
"tslint": "^5.12.1",
"typescript": "^3.3.1",
"vscode": "^1.1.37",
"webpack": "^4.35.2",
"webpack-cli": "^3.3.5"
},
"dependencies": {
"marked": "^2.0.4",
"nunjucks": "^3.2.0",
"prismjs": "^1.19.0",
"react": "^16.13.0",
"react-autosize-textarea": "^7.0.0",
"react-beautiful-dnd": "^13.0.0",
"react-dom": "^16.13.0",
"react-select": "^3.1.0",
"react-simple-code-editor": "^0.11.0",
"styled-components": "^5.0.1"
}
}
================================================
FILE: src/.editorconfig
================================================
# EditorConfig: http://EditorConfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: src/.gitignore
================================================
out
node_modules
.vscode-test/
*.vsix
configViewer/configViewer.js
================================================
FILE: src/.prettierrc.yml
================================================
---
printWidth: 120
tabWidth: 2
useTabs: false
semi: true
singleQuote: true
trailingComma: none
bracketSpacing: true
jsxBracketSameLine: false
arrowParens: avoid
================================================
FILE: src/.vscodeignore
================================================
.vscode/**
.vscode-test/**
out/test/**
src/**
.gitignore
vsc-extension-quickstart.md
**/tsconfig.json
**/tslint.json
**/*.map
**/*.ts
================================================
FILE: src/extension.ts
================================================
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
// import { telemetry } from './view/app/Utils';
import ViewLoader from './view/ViewLoader';
import TaskBoardLoader from './view/TaskBoardLoader';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
// console.log('Congratulations, your extension "vscode-react" is now active!');
// context.subscriptions.push(telemetry);
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand('extension.viewconfig', (uri: vscode.Uri) => {
// let openDialogOptions: vscode.OpenDialogOptions = {
// canSelectFiles: true,
// canSelectFolders: false,
// canSelectMany: false,
// filters: {
// Json: ["json"]
// }
// };
// vscode.window
// .showOpenDialog(openDialogOptions)
// .then(async (uri: vscode.Uri[] | undefined) => {
// if (uri && uri.length > 0) {
// const view = new ViewLoader(uri[0], context.extensionPath);
// } else {
// vscode.window.showErrorMessage("No valid file selected!");
// return;
// }
// });
const view = new ViewLoader(context.extensionPath, uri);
// telemetry.sendTelemetryEvent('init-file-generator');
return view;
});
context.subscriptions.push(disposable);
let taskBoardCmd = vscode.commands.registerCommand('extension.taskboard', (uri: vscode.Uri) => {
const view = new TaskBoardLoader(context.extensionPath, uri);
// telemetry.sendTelemetryEvent('init-task-board');
return view;
});
context.subscriptions.push(taskBoardCmd);
}
// this method is called when your extension is deactivated
export function deactivate() {
// telemetry.dispose();
}
================================================
FILE: src/test/extension.test.ts
================================================
//
// Note: This example test is leveraging the Mocha test framework.
// Please refer to their documentation on https://mochajs.org/ for help.
//
// The module 'assert' provides assertion methods from node
import * as assert from 'assert';
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
// import * as vscode from 'vscode';
// import * as myExtension from '../extension';
// Defines a Mocha test suite to group tests of similar kind together
suite("Extension Tests", function () {
// Defines a Mocha unit test
test("Something 1", function() {
assert.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
});
================================================
FILE: src/test/index.ts
================================================
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testsRoot: string, clb: (error: Error, failures?: number) => void): void
// that the extension host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.
import * as testRunner from 'vscode/lib/testrunner';
// You can directly control Mocha options by configuring the test runner below
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options
// for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
useColors: true // colored output from test results
});
module.exports = testRunner;
================================================
FILE: src/view/TaskBoardLoader.ts
================================================
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { IConfig, ICommand, CommandAction } from './app/model';
import { deepFind, VER } from './app/Utils';
let __panel = null;
let selectedFile = '';
export default class ViewLoader {
private readonly _panel: vscode.WebviewPanel | undefined;
private readonly _extensionPath: string = '';
private _disposables: vscode.Disposable[] = [];
constructor(extensionPath: string, uri: vscode.Uri) {
// load "coddx.taskBoard.fileList" from config (settings):
const configuration = vscode.workspace.getConfiguration();
const fileList: string = configuration.get('coddx.taskBoard.fileList') || 'TODO.md';
const filesArr = fileList.split(',').map(str => str.trim());
selectedFile = filesArr[0];
this._extensionPath = extensionPath;
const column = vscode.window.activeTextEditor
? vscode.ViewColumn.Two // vscode.window.activeTextEditor.viewColumn vscode.ViewColumn.Two
: undefined;
// let config = this.getFileContent();
// if (config) {
this._panel = vscode.window.createWebviewPanel('configView', 'Task Board', column || vscode.ViewColumn.Two, {
enableScripts: true,
localResourceRoots: [vscode.Uri.file(path.join(extensionPath, 'configViewer'))]
});
// get base path (from the user's workspace path):
const rootPath = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + '/';
// const templateFilePath = rootPath + '/TODO.md';
let basePath = ''; // relative
if (uri && uri.fsPath) {
// path from Context Menu
basePath = uri.fsPath.replace(rootPath, ''); // get relative path
}
// const fileUri = vscode.Uri.file(templateFilePath);
const todoStr = ''; // this.getFileContent(fileUri);
this._panel.webview.html = this.getWebviewContent({
basePath,
templateString: todoStr || '',
fileList,
selectedFile,
rootPath
});
__panel = this._panel;
this._panel.webview.onDidReceiveMessage(
(command: ICommand) => {
switch (command.action) {
case CommandAction.ShowMessage:
vscode.window.showInformationMessage(command.content.description);
return;
case CommandAction.OpenFile:
const rootPath2 = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + '/';
const filePath2 = rootPath2 + (selectedFile || 'TODO.md');
vscode.window.showTextDocument(vscode.Uri.file(filePath2));
return;
case CommandAction.Save:
this.saveFileContent(command.content);
return;
case CommandAction.Load:
selectedFile = command.content.description || 'TODO.md';
const rootPath3 = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + '/';
const filePath3 = rootPath3 + selectedFile;
const fileUri = vscode.Uri.file(filePath3);
const todoStr = this.getFileContent(fileUri);
this._panel.webview.html = this.getWebviewContent({
basePath,
templateString: todoStr || '',
fileList,
selectedFile,
rootPath
});
// __panel.webview.postMessage({ command: 'load', content }); // Doesn't work ???
return;
// case CommandAction.GetListFiles:
// load config (settings)
// vscode.window.showInformationMessage(`👍 Config:`, JSON.stringify(filesArr));
// WORKS!
// const workspace = vscode.workspace.workspaceFolders[0];
// if (workspace) {
// vscode.workspace
// .findFiles(new vscode.RelativePattern(workspace, '**/*/TODO.md'), '**/node_modules/**')
// .then(results => {
// console.log('results: ', results);
// });
// }
// return;
}
},
undefined,
this._disposables
);
// }
}
private getWebviewContent({ basePath, templateString, fileList, selectedFile, rootPath }): string {
// Local path to main script run in the webview
const reactAppPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'configViewer', 'configViewer.js'));
const reactAppUri = reactAppPathOnDisk.with({ scheme: 'vscode-resource' });
// const configJson = JSON.stringify(config);
const fullPath = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + `/${selectedFile}`;
// rootPathBase64 = toBase64(rootPathBase64);
return `
Task Board
`;
}
private getFileContent(fileUri: vscode.Uri) {
//: IConfig | undefined {
if (fs.existsSync(fileUri.fsPath)) {
let content = fs.readFileSync(fileUri.fsPath, 'utf8');
// let config: IConfig = JSON.parse(content);
// return config;
return content;
}
return undefined;
}
private saveFileContent(config: IConfig) {
const content = config.description;
const rootPath = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + '/';
const filePath = rootPath + (selectedFile || 'TODO.md');
const uri = vscode.Uri.file(filePath);
fs.writeFileSync(uri.fsPath, content);
// vscode.window.showInformationMessage(`👍 TODO.md saved!`);
}
}
================================================
FILE: src/view/ViewLoader.ts
================================================
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { IConfig, ICommand, CommandAction } from './app/model';
import { deepFind, VER } from './app/Utils';
export default class ViewLoader {
private readonly _panel: vscode.WebviewPanel | undefined;
private readonly _extensionPath: string = '';
private _disposables: vscode.Disposable[] = [];
constructor(extensionPath: string, uri: vscode.Uri) {
this._extensionPath = extensionPath;
const column = vscode.window.activeTextEditor
? vscode.ViewColumn.Two // vscode.window.activeTextEditor.viewColumn
: undefined;
// let config = this.getFileContent();
// if (config) {
this._panel = vscode.window.createWebviewPanel(
'configView',
'Coddx - Generate Files',
column || vscode.ViewColumn.Two,
{
enableScripts: true,
localResourceRoots: [vscode.Uri.file(path.join(extensionPath, 'configViewer'))]
}
);
// get base path (from the user's workspace path):
const rootPath = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + '/';
const templateFilePath = rootPath + '/.coddx-template';
let basePath = ''; // relative
if (uri && uri.fsPath) {
// path from Context Menu
basePath = uri.fsPath.replace(rootPath, ''); // get relative path
}
// if (uri.fsPath) {
// basePath = uri.fsPath;
// } else if (vscode.workspace.workspaceFolders) {
// basePath = vscode.workspace.workspaceFolders[0].uri.fsPath;
// }
// load template file:
// const filePath = '/Users/duc/Documents/downloads/coddx-ext/.coddx-template';
const fileUri = vscode.Uri.file(templateFilePath);
const templateString = this.getFileContent(fileUri);
this._panel.webview.html = this.getWebviewContent(basePath, templateString || '');
this._panel.webview.onDidReceiveMessage(
(command: ICommand) => {
switch (command.action) {
case CommandAction.Save:
const fileUri = vscode.Uri.file(templateFilePath);
this.saveFileContent(fileUri, command.content);
return;
case CommandAction.GenerateFiles:
this.generateFiles(command.content);
return;
}
},
undefined,
this._disposables
);
// }
}
// constructor(fileUri: vscode.Uri, extensionPath: string) {
// this._extensionPath = extensionPath;
// const column = vscode.window.activeTextEditor
// ? vscode.ViewColumn.Two // vscode.window.activeTextEditor.viewColumn
// : undefined;
// let config = this.getFileContent(fileUri);
// if (config) {
// this._panel = vscode.window.createWebviewPanel(
// "configView",
// "Config View",
// column || vscode.ViewColumn.Two,
// {
// enableScripts: true,
// localResourceRoots: [
// vscode.Uri.file(path.join(extensionPath, "configViewer"))
// ]
// }
// );
// this._panel.webview.html = this.getWebviewContent(config);
// this._panel.webview.onDidReceiveMessage(
// (command: ICommand) => {
// switch (command.action) {
// case CommandAction.Save:
// this.saveFileContent(fileUri, command.content);
// return;
// }
// },
// undefined,
// this._disposables
// );
// }
// }
private getWebviewContent(basePath: string, templateString: string): string {
// Local path to main script run in the webview
const reactAppPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'configViewer', 'configViewer.js'));
const reactAppUri = reactAppPathOnDisk.with({ scheme: 'vscode-resource' });
// const configJson = JSON.stringify(config);
return `
Coddx - Generate Files
`;
}
private getFileContent(fileUri: vscode.Uri) {
//: IConfig | undefined {
if (fs.existsSync(fileUri.fsPath)) {
let content = fs.readFileSync(fileUri.fsPath, 'utf8');
// let config: IConfig = JSON.parse(content);
// return config;
return content;
}
return undefined;
}
private saveFileContent(fileUri: vscode.Uri, config: IConfig) {
// if (fs.existsSync(fileUri.fsPath)) {}
fs.writeFileSync(fileUri.fsPath, config.description || '');
vscode.window.showInformationMessage(`👍 Template saved to .coddx-template`);
}
private mkDirByPathSync(targetDir: string, { baseDir = '', isRelativeToScript = false } = {}) {
const sep = path.sep;
const initDir = path.isAbsolute(targetDir) ? sep : '';
// const baseDir = isRelativeToScript ? __dirname : '.';
return targetDir.split(sep).reduce((parentDir, childDir) => {
const curDir = path.resolve(baseDir, parentDir, childDir);
try {
fs.mkdirSync(curDir);
} catch (err) {
if (err.code === 'EEXIST') {
// curDir already exists!
return curDir;
}
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
if (err.code === 'ENOENT') {
// Throw the original parentDir error on curDir `ENOENT` failure.
throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`);
}
const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
if (!caughtErr || (caughtErr && curDir === path.resolve(targetDir))) {
throw err; // Throw if it's just the last created dir.
}
}
return curDir;
}, initDir);
}
private generateFiles(config: IConfig) {
const { path, files } = JSON.parse(config.description || '');
let counter = 0;
const rootPath = deepFind(vscode, 'workspace.workspaceFolders[0].uri.fsPath', '') + '/';
if (!fs.existsSync(rootPath + path)) {
this.mkDirByPathSync(path, { baseDir: rootPath });
}
Object.keys(files).forEach(itemKey => {
const item = files[itemKey];
if (item.checked === true) {
const fileName = item.fileName; // itemKey.trim()
const filePath = rootPath + (path + '/' + fileName).trim();
if (fileName.indexOf('/') > 0) {
// create directories, e.g. __test__/mocks
const dirPath = fileName.substr(0, fileName.lastIndexOf('/'));
this.mkDirByPathSync(dirPath, { baseDir: rootPath + path });
}
const fileUri = vscode.Uri.file(filePath);
fs.writeFileSync(fileUri.fsPath, item.fileContent);
counter++;
}
});
vscode.window.showInformationMessage(`👍 ${counter} files generated.`);
}
}
================================================
FILE: src/view/app/Utils.ts
================================================
import nunjucks from 'nunjucks';
import { ICommand, CommandAction } from './model';
export const VER = '0.2.55'; // TODO: get this from package.json.
// const TelemetryReporter = require('vscode-extension-telemetry');
// const extensionId = 'coddx-alpha';
// const extensionVersion = '0.2.11';
// const key = '';
// export const telemetry = new TelemetryReporter(extensionId, extensionVersion, key); // TODO: this crashed!
export interface FilesInterface {
checked?: boolean;
fileMarker?: string;
fileeName?: string;
fileContent?: string;
}
export const FILE_SEPARATOR = '--->>';
export const DefaultTemplateString = `// -------------->> {{fileName}}.tsx
// created time: {{YYYY}}-{{MM}}-{{DD}} {{HH}}:{{mm}}
import * as React from 'react';
import './{{fileName}}.css';
export default class {{fileName}} extends React.Component {
render() {
return (
{
// can't use onClick as it will close the menu without coming here.
ev.preventDefault();
task.level = (task.level + 1) % 2;
onChangeTask(task.id, task);
closeMenu();
}}
>
Toggle Task / Sub-task
{
// can't use onClick as it will close the menu without coming here.
ev.preventDefault();
setMenuActive('EMOJI');
}}
>
Insert Emoji Icon
{" "}
{this.state.config.description}
{this.renderUsers(this.state.config.users)}
this.saveConfig()}
/>
);
}
saveConfig() {
let command: ICommand = {
action: CommandAction.Save,
content: this.state.config
};
this.props.vscode.postMessage(command);
}
}
================================================
FILE: src/view/app/index.css
================================================
:root {
/* --text-color: #eee; */
/* --bg-color: #1d1e1d; */
--button-bg-color: rgb(3, 0, 150);
--button-text-color: #777;
}
html,
body {
background-color: var(--bg-color); /* Dracula+ Dark Theme */
}
a {
text-decoration: none;
color: darkslategray;
}
li {
margin-bottom: 15px;
}
input {
margin-left: 10px;
}
.save {
margin-top: 10px;
}
.__reactSelect .__select__control {
background-color: var(--vscode-tab-background);
border: none;
margin-top: 5px;
min-height: 30px;
}
.__reactSelect .__select__input {
color: var(--button-text-color);
}
.__reactSelect .__select__single-value {
color: var(--button-text-color);
padding: 0;
}
.__reactSelect .__select__option {
color: var(--button-text-color);
}
.__reactSelect .__select__indicator-separator {
background-color: var(--vscode-tab-inactiveBackground);
}
.__reactSelect .__select__indicator {
color: var(--button-text-color);
}
.__reactSelect .__select__option--is-selected {
background-color: var(--vscode-tab-inactiveBackground);
}
================================================
FILE: src/view/app/index.tsx
================================================
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './index.css';
import { IConfig } from './model';
// import Config from "./config";
import MainView from './components/CodeGen/MainView';
import TaskBoard from './components/TaskBoard/TaskBoard';
declare global {
interface Window {
acquireVsCodeApi(): any;
initialData: IConfig;
}
}
const vscode = window.acquireVsCodeApi();
if (window.initialData.name === 'TaskBoard') {
ReactDOM.render(
,
document.getElementById('root')
);
} else {
ReactDOM.render(
,
document.getElementById('root')
);
}
================================================
FILE: src/view/app/model.ts
================================================
export interface IConfig {
name: string;
description?: string;
users?: IUser[];
}
export interface IUser {
name: string;
active: boolean;
roles: string[];
}
export interface ICommand {
action: CommandAction;
content: IConfig;
}
export enum CommandAction {
ShowMessage,
Save,
Load,
OpenFile,
GenerateFiles
}
================================================
FILE: src/view/app/tsconfig.json
================================================
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"target": "es6",
"outDir": "configViewer",
"lib": [
"es6",
"dom"
],
"jsx": "react",
"sourceMap": true,
"rootDir": "..",
"noUnusedLocals": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules"
]
}
================================================
FILE: src/webpack.config.js
================================================
const path = require("path");
module.exports = {
entry: {
configViewer: "./src/view/app/index.tsx"
},
output: {
path: path.resolve(__dirname, "configViewer"),
filename: "[name].js"
},
devtool: "eval-source-map",
resolve: {
extensions: [".js", ".ts", ".tsx", ".json"]
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: "ts-loader",
options: {}
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
}
]
}
]
},
performance: {
hints: false
}
};
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "out",
"lib": [
"es6", "dom"
],
"sourceMap": false,
"rootDir": "src",
// "strict": true /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
},
"exclude": [
"node_modules",
".vscode-test",
"**/view/app/index.css",
"**/view/app/index.tsx",
"**/view/app/tsconfig.json",
"**/view/app/config.tsx"
]
}
================================================
FILE: tslint.json
================================================
{
"rules": {
"no-string-throw": true,
"no-unused-expression": true,
"no-duplicate-variable": true,
"curly": true,
"class-name": true,
"semicolon": [
true,
"always"
],
"triple-equals": true
},
"defaultSeverity": "warning"
}
================================================
FILE: vsc-extension-quickstart.md
================================================
# Welcome to your VS Code Extension
## What's in the folder
* This folder contains all of the files necessary for your extension.
* `package.json` - this is the manifest file in which you declare your extension and command.
* The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
* The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
* We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
## Get up and running straight away
* Press `F5` to open a new window with your extension loaded.
* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
* Set breakpoints in your code inside `src/extension.ts` to debug your extension.
* Find output from your extension in the debug console.
## Make changes
* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
## Explore the API
* You can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`.
## Run tests
* Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`.
* Press `F5` to run the tests in a new window with your extension loaded.
* See the output of the test result in the debug console.
* Make changes to `test/extension.test.ts` or create new test files inside the `test` folder.
* By convention, the test runner will only consider files matching the name pattern `**.test.ts`.
* You can create folders inside the `test` folder to structure your tests any way you want.
## Go further
* Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/testing-extension).
* [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace.
* Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).
================================================
FILE: webpack.config.js
================================================
const path = require("path");
module.exports = {
entry: {
configViewer: "./src/view/app/index.tsx"
},
output: {
path: path.resolve(__dirname, "configViewer"),
filename: "[name].js"
},
devtool: "eval-source-map",
resolve: {
extensions: [".js", ".ts", ".tsx", ".json"]
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: "ts-loader",
options: {}
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
}
]
}
]
},
performance: {
hints: false
}
};