Prepare for Publishing VS Code Extension (#227)

* Changed Wardlt use back to Tldraw. Added some VS Code marketplace categories

* Missed removing one Wardlt mention

* Initial support for esbuild based vscode extension workflow.

* Hacky start of vs code extension build script

* Fixed categories of extension

* Added script for generating VS Code extension installer

* Temp fix for file format change affecting VS Code extension

* Temp fix for file format change issue

* Cleanup, prevent changes from saving pagestates

* Remove logic around saving pageState

* standardize capitalization

* v0.1.8

* Edit readme, scripts

* Update .eslintignore

* v0.1.9

* v0.1.10

* cleans up build scripts, adds publishing notes

* Added VS Code extension implementation references links. start:vscode now auto opens the extension folder in VS Code

* Removed step from VS Code README to manually open the extensions folder

* Removed file

* v0.1.11

* v0.1.12

* Fix empty file

* v0.1.13

* README cleanup

* v0.1.14

* Update TLDrawEditorProvider.ts

* v0.1.15

* Fix types for file extension (sort of) build script for extension

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
pull/258/head
Francois Laberge 2021-11-10 10:35:51 -05:00 zatwierdzone przez GitHub
rodzic c1288363cd
commit a95b581e07
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
42 zmienionych plików z 2506 dodań i 1479 usunięć

Wyświetl plik

@ -1,7 +1,3 @@
**/node_modules/*
**/out/*
**/.next/*
# TODO: Remove these, vscode experiments are based on existing examples and are punting on making eslint happy just yet.
**/integrations/vscode-extension/*
**/integrations/vscode-simple/*

15
.eslintrc 100644
Wyświetl plik

@ -0,0 +1,15 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": [0]
}
}
]
}

Wyświetl plik

@ -1,15 +0,0 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
overrides: [
{
// enable the rule specifically for TypeScript files
files: ['*.ts', '*.tsx'],
rules: {
'@typescript-eslint/explicit-module-boundary-types': [0],
},
},
],
}

6
.prettierrc 100644
Wyświetl plik

@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"singleQuote": true,
"semi": false,
"printWidth": 100
}

Wyświetl plik

@ -11,6 +11,7 @@
"workspaces": [
"electron",
"vscode/editor",
"vscode/extension",
"packages/tldraw",
"example",
"www"
@ -20,7 +21,8 @@
"test:watch": "jest --watchAll",
"lerna": "lerna",
"start:electron": "lerna run start:electron --stream --parallel",
"start:vscode": "lerna run start:vscode --stream --parallel",
"start:vscode": "yarn build:packages && lerna run start:vscode --stream --parallel & code vscode/extension; ",
"build:vscode": "cd vscode/extension && yarn package",
"start": "lerna run start --stream --parallel",
"start:www": "yarn build:packages && lerna run start --parallel & cd www && yarn dev",
"build": "yarn build:packages && cd www && yarn build",
@ -39,6 +41,7 @@
"@types/node": "^15.0.1",
"@types/react": "^17.0.33",
"@types/react-dom": "^17.0.10",
"@types/vscode": "^1.59.0",
"@typescript-eslint/eslint-plugin": "^4.19.0",
"@typescript-eslint/parser": "^4.19.0",
"eslint": "^7.32.0",
@ -54,12 +57,6 @@
"typedoc": "^0.22.3",
"typescript": "^4.4.2"
},
"prettier": {
"trailingComma": "es5",
"singleQuote": true,
"semi": false,
"printWidth": 100
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",

Wyświetl plik

@ -23,7 +23,6 @@
"types": "./dist/types/index.d.ts",
"scripts": {
"start:electron": "yarn start",
"start:vscode": "yarn start",
"start": "node scripts/dev & yarn types:dev",
"build": "node scripts/build && yarn types:build && node scripts/copy-readme",
"types:dev": "tsc -w",
@ -60,4 +59,4 @@
"tsconfig-replace-paths": "^0.0.5"
},
"gitHead": "083b36e167b6911927a6b58cbbb830b11b33f00a"
}
}

Wyświetl plik

@ -293,7 +293,7 @@ export function TLDraw({
return (
<TLDrawContext.Provider value={context}>
<IdProvider>
<InnerTldraw
<InnerTLDraw
key={sId || 'tldraw'}
id={sId}
currentPageId={currentPageId}
@ -324,7 +324,7 @@ interface InnerTLDrawProps {
readOnly: boolean
}
const InnerTldraw = React.memo(function InnerTldraw({
const InnerTLDraw = React.memo(function InnerTLDraw({
id,
currentPageId,
autofocus,

Wyświetl plik

@ -1,15 +1,55 @@
# @tldraw/vscode
This folder contains the source for the tldraw VSCode extension.
This folder contains the source for the tldraw VS Code extension.
## 1. Setup editor project
## Developing
## 1. Install dependencies
- Run `yarn` from the root folder
## 2. Build @tldraw/tldraw
- Run `yarn build:packages` from the root folder.
## 3. Start the editor
In the root folder:
- Run `yarn start:vscode`.
This will start the development server for the `vscode/editor` project and open the `vscode/extension` folder in a new window.
In the `vscode/extension` window, open the terminal and run:
- Open `vscode/editor`
- Install dependencies (`yarn`)
- Start the development server (`yarn start`)
- Start the VS Code debugger (Menu > Run > Start Debugging)
## 2. Start the Extension
Open a `.tldr` file or create a new `.tldr` file from the command palette.
- Open `vscode/extension` in a new VSCode window
- Install dependencies (`yarn`)
- Run the extension (F5)
## Publishing
To publish, chat with the team on the [Discord channel](https://discord.gg/s4FXZ6fppJ).
- Install `vsce` globally
- Run `vsce login tldraw-org` and sign in
In the `vscode/extension` folder:
- Run `yarn vscode:publish`
#### References
- [VS Code Marketplace Manager](https://marketplace.visualstudio.com/manage/)
- [Web Extensions Guide](https://code.visualstudio.com/api/extension-guides/web-extensions)
- [Test Your Web Extension](https://code.visualstudio.com/api/extension-guides/web-extensions#test-your-web-extension)
- [Web Extension Testing](https://code.visualstudio.com/api/extension-guides/web-extensions#web-extension-tests)
- An example custom editor that does work as a Web Extension
- https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio
- https://github.com/hediet/vscode-drawio
- [VS Code Extension API/Landing Page](https://code.visualstudio.com/api)
- [Getting Started](https://code.visualstudio.com/api/get-started/your-first-extension)
- [Custom Editor API](https://code.visualstudio.com/api/extension-guides/custom-editors)
- [github.com/microsoft/vscode-extension-samples](https://github.com/microsoft/vscode-extension-samples)
- [Extensions Guide -> Webviews](https://code.visualstudio.com/api/extension-guides/webview)
- [Publishing Extensions](https://code.visualstudio.com/api/working-with-extensions/publishing-extension)

Wyświetl plik

@ -1,6 +1,9 @@
# @tldraw/tldraw-example
<div style="text-align: center; transform: scale(.5);">
<img src="card-repo.png"/>
</div>
An example for @tldraw/tldraw with a very fast dev server.
# @tldraw/vscode-editor
**Note:** You probably do not need to start the server here: it is started as
part of `yarn start` in the root directory.
The app for the TLDraw VS Code Extension.
See the README at `vscode` for more about this project.

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 63 KiB

Wyświetl plik

@ -17,11 +17,10 @@ async function main() {
incremental: true,
target: 'es6',
define: {
'process.env.NODE_ENV': '"development"',
'process.env.NODE_ENV': '"production"',
},
watch: {
onRebuild(err) {
serve.update()
err ? error('❌ Failed') : log('✅ Updated')
},
},

Wyświetl plik

@ -1,32 +1,44 @@
import * as React from 'react'
import { TLDraw, TLDrawState, TLDrawSnapshot, TLDrawFile } from '@tldraw/tldraw'
import { TLDraw, TLDrawState, TLDrawFile, TLDrawDocument } from '@tldraw/tldraw'
import { vscode } from './utils/vscode'
import { eventsRegex } from './utils/eventsRegex'
import { defaultDocument } from './utils/defaultDocument'
import { UI_EVENT } from './types'
import './styles.css'
import { sanitizeDocument } from 'utils/sanitizeDocument'
// Will be placed in global scope by extension
declare let currentFile: TLDrawFile
export default function App(): JSX.Element {
const rTLDrawState = React.useRef<TLDrawState>()
const rInitialDocument = React.useRef<TLDrawDocument>(
currentFile ? currentFile.document : defaultDocument
)
// When the editor mounts, save the state instance in a ref.
const handleMount = React.useCallback((tldr: TLDrawState) => {
rTLDrawState.current = tldr
const handleMount = React.useCallback((state: TLDrawState) => {
rTLDrawState.current = state
}, [])
// When the editor's document changes, post the stringified document to the vscode extension.
const handlePersist = React.useCallback((tldr: TLDrawState) => {
vscode.postMessage({ type: UI_EVENT.TLDRAW_UPDATED, text: JSON.stringify(tldr.document) })
const handlePersist = React.useCallback((state: TLDrawState) => {
const initialDocument = rInitialDocument.current
vscode.postMessage({
type: UI_EVENT.TLDRAW_UPDATED,
text: JSON.stringify({
...currentFile,
document: sanitizeDocument(initialDocument, state.document),
assets: {},
}),
})
}, [])
return (
<div className="tldraw">
<TLDraw
id={currentFile.document.id}
document={currentFile.document ?? defaultDocument}
id={rInitialDocument.current.id}
document={rInitialDocument.current}
onMount={handleMount}
onPersist={handlePersist}
autofocus

Wyświetl plik

@ -3,5 +3,5 @@ export enum UI_EVENT {
}
export enum EXTENSION_EVENT {
LOCAL_FILE_UPDATED = 'LOCAL_FILE_UPDATED',
FILE_UPDATED = 'FILE_UPDATED',
}

Wyświetl plik

@ -1,7 +1,9 @@
import type { TLDrawDocument } from '@tldraw/tldraw'
import { TLDrawDocument, TLDrawState } from '@tldraw/tldraw'
export const defaultDocument: TLDrawDocument = {
id: 'doc',
name: 'New Document',
version: TLDrawState.version,
pages: {
page: {
id: 'page',

Wyświetl plik

@ -1,4 +0,0 @@
// A regex to detect event types that we should send to the extension. We only want to send
// events that change the document and that would be committed to the undo/redo stack; not
// all the smaller patches or transient changes from sessions.
export const eventsRegex = /command|undo|redo/

Wyświetl plik

@ -0,0 +1,17 @@
import type { TLDrawDocument } from '@tldraw/tldraw'
export function sanitizeDocument(prev: TLDrawDocument, next: TLDrawDocument): TLDrawDocument {
return next
// // Don't save changes to page state?
// const final = { ...next, pageStates: { ...next.pageStates } }
// Object.values(prev.pageStates).forEach((pageState) => {
// if (next.pages[pageState.id] !== undefined) {
// final.pageStates[pageState.id] = pageState
// }
// })
// return final
}

Wyświetl plik

@ -1,6 +1,6 @@
dist
editor
node_modules
.vscode-test-web/
*.vsix
editor-build
.DS_Store

Wyświetl plik

@ -16,8 +16,7 @@
],
"outFiles": [
"${workspaceFolder}/dist/web/**/*.js"
],
"preLaunchTask": "npm: watch-web"
]
},
{
"name": "Extension Tests in VS Code",
@ -31,8 +30,7 @@
],
"outFiles": [
"${workspaceFolder}/dist/web/**/*.js"
],
"preLaunchTask": "npm: watch-web"
]
}
]
}

Wyświetl plik

@ -14,16 +14,6 @@
"$ts-webpack",
"$tslint-webpack"
]
},
{
"type": "npm",
"script": "watch-web",
"group": "build",
"isBackground": true,
"problemMatcher": [
"$ts-webpack-watch",
"$tslint-webpack-watch"
]
}
]
}

Wyświetl plik

@ -0,0 +1,3 @@
## 0.1.0
- Launched!

Wyświetl plik

@ -1,110 +0,0 @@
### VS Code Extension
This folder contains code implementing a VS Code extension for working with tldraw within VS Code. Files are saved locally and thus play well with version control. Target use case is developer documentation.
### Todos
- Get live reloading working while extension developing (debug launched)
- Watching and rebuilding is working, it's just hot-updating the running editor instances that's failing
- It currently at least updates every time you open a new editor, currently it's the websocket
needed for the live reloading logic that is failing to connect.
- Backlog
- Make sure extension works in Codespaces (when one of us gets into the beta)
- [Supporting Remote Development and GitHub Codespaces](https://code.visualstudio.com/api/advanced-topics/remote-extensions)
## Test Cases
Here's a list of functionality and behavior we'd like working for an initial beta.
- Saving
- Save (Command+S or menu) should work
- Save As (menu or shortcut)
- Undo/Redo
- Should reflect correctly in VS Code menus (can/can't do it based on stack)
- Create new file using either of these methods
- Use VS Code's "New File", name the file with a .tldr extension
- Use the Tldraw extensions registered command to create a blank .tldr file
- Opening an
- The editor should communicate that a file isn't valid when loading it
- Detect and prevent multiple instances of the editor (For now)
Things we're cutting
- Distinguishing app state from user state (selection, zoom, pan, etc)
## Running The Extension
- Setup/Run the editor (a create react app that houses the tldraw component)
- `cd integrations/vscode/editor`
- `yarn`
- `yarn start`
- To setup/run the extension
- In a new terminal
- Install dependencies
- `yarn`
- Open just the extension folder in VS Code (necessary to use it's launch.json)
- `cd integrations/vscode/extension`
- `code .`
- Run the extension using F5 (the launch.json setups watching too)
- This will open a new VS Code window where the extension is installed in memory
- Open a folder containing some .tldr files. Ex. tldraw/integrations/extension/examples
- Select a .tldr file to test
- You'll have to toggle between the extension/editor/debug VS Code instances to change things and see the results
- NOTE: Hot reloading doesn't work right now for the editor's create-react-app workflow. I have yet to figure out how to set the websocket host, which currently assumes it's housed on the same host as the page it's loaded in (which for the extension is some weird custom protocol)
- If you close and reopen a .tldr file, it will load the latest change though
## Publishing/Packaging Extensions
**This stuff needs to be fully automated!!! We're not quite there yet.**
- Make sure you have the vsce command line tool installed
- `npm install -g vsce`
- Build the editor static site
- `cd integrations/vscode/editor`
- `yarn build`
- This will build a static version of the create react app and put it into `integrations/vscode/editor`.
- Bump the package.json version
- Just do this manually in the file
- Change the code in `integrations/vscode/extension/src/get-html.ts` so it uses the production path. It should look like this:
//return getDevModeHTML(context, webview, documentContent);
return getProductionModeHTML(context, webview, documentContent);
- Run script that copies over the latest static file path hashes
- **TODO**: Find this script. It seems to have gone missing and I can't find it in history
- The manual version is to look at the latest editor-build/index.html and copy/reference it into get-html.ts
- Compile the extension in production mode
- `npm run package-web`
- Package up the extension as an extension installer .vsix
- `vsce package`
- A file with a name like: `wardlt-0.8.0.vsix` will now be put in the extension root
- TODO: Make this get build to a proper temp directory like dist
- Before publishing test using the .vsix based installation workflow available in VS Code Desktop
- Use the Web UI to publish the latest extension by uploading the .vsix file
- https://marketplace.visualstudio.com/manage/publishers/Wardlt
- Click on the elipse button and choose Update, then select the .vsix we just generated
- It should take a few minutes to go through some automated validation the VS Code Marketplace does
- Now test it quickly
- Desktop
- github.dev
- Go here and then press '.' https://github.com/tldraw/tldraw/tree/vscode-extension-v1/integrations/vscode/extension/examples
- Try one of the .tldr files
- Codespaces
- Go here: https://github.com/conveyhq/codespaces-test
- Select Code -> main or go straight there via link: https://seflless-conveyhq-codespaces-test-x76jf9xq7.github.dev/
- I have a test code space here with a .tldr file already included
- Read more about this topic here: [Publishing Extensions](https://code.visualstudio.com/api/working-with-extensions/publishing-extension)
#### Good References
- [VS Code Marketplace Manager](https://marketplace.visualstudio.com/manage/)
- [Web Extensions Guide](https://code.visualstudio.com/api/extension-guides/web-extensions)
- [Test Your Web Extension](https://code.visualstudio.com/api/extension-guides/web-extensions#test-your-web-extension)
- [Web Extension Testing](https://code.visualstudio.com/api/extension-guides/web-extensions#web-extension-tests)
- An example custom editor that does work as a Web Extension
- https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio
- https://github.com/hediet/vscode-drawio
- [VS Code Extension API/Landing Page](https://code.visualstudio.com/api)
- [Getting Started](https://code.visualstudio.com/api/get-started/your-first-extension)
- [Custom Editor API](https://code.visualstudio.com/api/extension-guides/custom-editors)
- [github.com/microsoft/vscode-extension-samples](https://github.com/microsoft/vscode-extension-samples)
- [Extensions Guide -> Webviews](https://code.visualstudio.com/api/extension-guides/webview)
- [Publishing Extensions](https://code.visualstudio.com/api/working-with-extensions/publishing-extension)

Wyświetl plik

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Stephen Ruiz Ltd
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.

Wyświetl plik

@ -1,13 +1,34 @@
# Wardlt
This is an awesome sketch/diagramming extension for making doodles and diagrams of system. It allows you to naturally create informal but legible diagrams, designed to be version controlled along side your code.
## Introduction
TLDraw extends VS Code with support for [TLDraw](https://tldraw.com) files.
[TLDraw](https://tldraw.com) is a free drawing and diagramming tool with a hand-drawn style and convenient features such as smart arrows, snapping, and sticky notes. With the TLDraw extension for VS Code, your TLDraw files can be version controlled alongside your code.
> **Tip:** The files you create or edit here can also be opened in the TLDraw [web app](https://tldraw.com).
## Installation
You can install TLDraw from the Visual Studio Code Marketplace or by searching within VS Code.
## Features
1. Hand drawn style
2. Built in shapes like rectangles and ovals
3. Add text elements
4. Has smart arrows that support smart connecting between shapes/text for easy to make flow charts.
5. Supports dashed strokes on all shapes.
1. View, edit and save TLDraw files (`.tldr`)
## Usage
Create a new file by either creating a blank .tldr file or by using the provided command: "Tldraw: Create a new .tldr file".
- To view an existing TLDraw file, open a file with the `.tldr` extension in VS Code.
- To create a new TLDraw file, use the provided command: "TLDraw: New TLDraw File".
## Release Notes
For full release notes, see the [changelog](https://github.com/tldraw/tldraw).
## Community
### Support
Need help? Please [open an issue](https://github.com/tldraw/tldraw/issues/new) for support.
### Discussion
Want to connect with other devs? Visit the [Discord channel](https://discord.gg/s4FXZ6fppJ).

Wyświetl plik

@ -3,6 +3,7 @@
"fileHandle": {},
"document": {
"id": "doc",
"name": "New Document",
"version": 13,
"pages": {
"page": {
@ -17,8 +18,8 @@
"parentId": "page",
"childIndex": 1,
"point": [
258.7,
246.85
268.18,
247.52
],
"rotation": 0,
"style": {
@ -1095,9 +1096,7 @@
-220.86
],
"zoom": 2.462934947049924
},
"editingId": null,
"hoveredId": "60a83a6a-6477-45ff-3cd9-5c705c210c3a"
}
}
}
},

Plik binarny nie jest wyświetlany.

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 354 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 68 KiB

Wyświetl plik

@ -1,15 +1,33 @@
{
"name": "wardlt",
"displayName": "Wardlt Editor",
"description": "The wardlt editor for VS Code",
"version": "0.10.0",
"publisher": "Wardlt",
"repository": "https://github.com/microsoft/vscode-extension-samples/helloworld-web-sample",
"name": "tldraw-vscode",
"displayName": "TLDraw",
"description": "The TLDraw Extension for VS Code.",
"version": "0.1.15",
"license": "MIT",
"publisher": "tldraw-org",
"repository": {
"type": "git",
"url": "https://github.com/tldraw/tldraw"
},
"engines": {
"vscode": "^1.59.0"
},
"keywords": [
"diagram",
"draw",
"drawing",
"sketch",
"design",
"documentation",
"tldraw"
],
"icon": "icon.png",
"galleryBanner": {
"color": "#1d1d1d",
"theme": "dark"
},
"categories": [
"Other"
"Visualization"
],
"activationEvents": [
"onCustomEditor:tldraw.tldr",
@ -25,7 +43,7 @@
"customEditors": [
{
"viewType": "tldraw.tldr",
"displayName": "Tldr Editor",
"displayName": "TLDraw",
"selector": [
{
"filenamePattern": "*.tldr"
@ -36,35 +54,31 @@
"commands": [
{
"command": "tldraw.tldr.new",
"title": "Create a new .tldr file",
"category": "Tldraw"
"title": "New TLDraw File",
"category": "TLDraw"
}
]
},
"scripts": {
"test": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. --extensionTestsPath=dist/web/test/suite/index.js",
"start:vscode": "node scripts/dev & yarn types:dev",
"types:dev": "tsc -w",
"web": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=.",
"pretest": "npm run compile-web",
"vscode:prepublish": "npm run package-web",
"compile-web": "webpack",
"watch-web": "webpack --watch",
"package-web": "webpack --mode production --devtool hidden-source-map",
"package": "cd ../editor && yarn build && cd ../extension && node scripts/build && node scripts/package",
"vscode:publish": "yarn version && yarn package && vsce publish",
"lint": "eslint src --ext ts"
},
"dependencies": {},
"peerDependencies": {},
"devDependencies": {
"@types/vscode": "^1.59.0",
"@types/mocha": "^9.0.0",
"eslint": "^7.32.0",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"mocha": "^9.1.1",
"typescript": "^4.4.3",
"@vscode/test-web": "^0.0.12",
"ts-loader": "^9.2.5",
"webpack": "^5.52.1",
"webpack-cli": "^4.8.0",
"@types/webpack-env": "^1.16.2",
"assert": "^2.0.0",
"process": "^0.11.10"
"eslint": "^7.32.0",
"mocha": "^9.1.1",
"process": "^0.11.10",
"ts-loader": "^9.2.5",
"typescript": "^4.4.3",
"vsce": "^2.2.0"
}
}
}

Wyświetl plik

@ -0,0 +1,53 @@
/* eslint-disable */
const fs = require('fs')
const esbuild = require('esbuild')
const { gzip } = require('zlib')
const pkg = require('../package.json')
async function main() {
if (fs.existsSync('./dist')) {
fs.rmSync('./dist', { recursive: true }, (e) => {
if (e) {
throw e
}
})
}
try {
const esmResult = esbuild.buildSync({
entryPoints: ['./src/extension.ts'],
outdir: 'dist/web',
minify: true,
bundle: true,
format: 'cjs',
target: 'es6',
define: {
'process.env.NODE_ENV': '"production"',
},
tsconfig: './tsconfig.json',
external: Object.keys(pkg.dependencies).concat(Object.keys(pkg.peerDependencies)).concat(["vscode"]),
metafile: true,
})
let esmSize = 0
Object.values(esmResult.metafile.outputs).forEach((output) => {
esmSize += output.bytes
})
fs.readFile('./dist/web/index.js', (_err, data) => {
gzip(data, (_err, result) => {
console.log(
`${pkg.name}: Built pkg. ${(esmSize / 1000).toFixed(2)}kb (${(
result.length / 1000
).toFixed(2)}kb minified)`
)
})
})
} catch (e) {
console.log(`× ${pkg.name}: Build failed due to an error.`)
console.log(e)
}
}
main()

Wyświetl plik

@ -0,0 +1,54 @@
/* eslint-disable */
const fs = require('fs')
const esbuild = require('esbuild')
const { gzip } = require('zlib')
const pkg = require('../package.json')
async function main() {
if (fs.existsSync('./dist')) {
fs.rmSync('./dist', { recursive: true }, (e) => {
if (e) {
throw e
}
})
}
try {
const esmResult = esbuild.buildSync({
entryPoints: ['./src/extension.ts'],
outdir: 'dist/web',
minify: true,
bundle: true,
format: 'cjs',
target: 'es6',
define: {
'process.env.NODE_ENV': '"development"',
},
tsconfig: './tsconfig.json',
external: Object.keys(pkg.dependencies)
.concat(Object.keys(pkg.peerDependencies))
.concat(['vscode']),
metafile: true,
})
let esmSize = 0
Object.values(esmResult.metafile.outputs).forEach((output) => {
esmSize += output.bytes
})
fs.readFile('./dist/web/index.js', (_err, data) => {
gzip(data, (_err, result) => {
console.log(
`${pkg.name}: Built pkg. ${(esmSize / 1000).toFixed(2)}kb (${(
result.length / 1000
).toFixed(2)}kb minified)`
)
})
})
} catch (e) {
console.log(`× ${pkg.name}: Build failed due to an error.`)
console.log(e)
}
}
main()

Wyświetl plik

@ -0,0 +1,37 @@
/* eslint-disable */
//const version = require('../../../lerna.json').version
const pkg = require('../package.json')
const { exec } = require('child_process')
const fs = require('fs')
const dir = './temp'
async function main() {
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true }, (e) => {
if (e) {
throw e
}
})
}
fs.mkdirSync(dir)
try {
exec(
`cp -r ../editor/dist editor; vsce package; mv ${pkg.name}-${pkg.version}.vsix ${dir}`,
(error, stdout, stderr) => {
if (error) {
throw new Error(error.message)
}
if (stderr && stderr.search('warning') !== 0) {
throw new Error(stderr)
}
}
)
} catch (e) {
console.log(`× ${pkg.name}: Build failed due to an error.`)
console.log(e)
}
}
main()

Wyświetl plik

@ -1,25 +1,27 @@
import * as vscode from 'vscode'
import { getHtmlForWebview } from './get-html'
import { TLDrawFile } from '@tldraw/tldraw'
import { getHtmlForWebview } from './getHtmlForWebview'
import { EXTENSION_EVENT, UI_EVENT } from './types'
import { sanitizeDocument } from './utils'
/**
* The Tldraw extension's editor uses CustomTextEditorProvider, which means
* The TLDraw extension's editor uses CustomTextEditorProvider, which means
* it's underlying model from VS Code's perspective is a text file. We likely
* will switch to CustomEditorProvider which gives us more control but will require
* more book keeping on our part.
*/
export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
export class TLDrawEditorProvider implements vscode.CustomTextEditorProvider {
private document?: vscode.TextDocument
// When the tldraw.tldr.new command is triggered, we need to provide a file
// name when generating a new .tldr file. newTldrawFileId's current value is
// name when generating a new .tldr file. newTLDrawFileId's current value is
// added to the end of the file to make it unique, and then incremented.
//
// While there is probably a more thoughtful way of creating suggested file names,
// this name is only the temporary name for the new file. The file is still only in memory
// and hasn't been saved to an actual underlying file. If we suggest a name that turns
// out to already exist, VS Code will prevent it from being used in it's save dialogs.
private static newTldrawFileId = 1
private static newTLDrawFileId = 1
// This is called one time by the main extension entry point. See 'extension.ts'.
// We register commands here and register our custom editor's provider telling VS Code
@ -28,33 +30,20 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
// This makes a new command show up in the Command Palette that will
// create a new empty .tldr. The file will actually start out
// as an empty text file, which is fine as the editor treats
// blank text files as an empty Tldraw file. Once any change is made
// blank text files as an empty TLDraw file. Once any change is made
// and the file saved it will be in a proper JSON format.
//
// The command shows up as: "Tldraw: Create a new .tldr file".
vscode.commands.registerCommand('tldraw.tldr.new', () => {
// This was included in the example CustomTextEditorProvider. It
// doesn't seem like we should need a workspace to be within to edit
// .tldr files, but I want to punt on digging into this.
// TODO: Test/decide if it is necessary to need a workspace.
// I can't think of why we'd want a concept of a global scope
// for editing .tldr files.
const workspaceFolders = vscode.workspace.workspaceFolders
if (!workspaceFolders) {
vscode.window.showErrorMessage(
'Creating new Tldraw Editor files currently requires opening a workspace'
)
return
}
// The command shows up as: "TLDraw: Create a new .tldr file".
vscode.commands.registerCommand('tldraw.tldr.new', () => {
// Create a placeholder name for the new file. A new file isn't actually
// created on disk yet, so this is just an in memory temporary name.
const uri = vscode.Uri.joinPath(
workspaceFolders[0].uri,
`drawing ${TldrawEditorProvider.newTldrawFileId++}.tldr`
).with({
scheme: 'untitled',
})
const id = TLDrawEditorProvider.newTLDrawFileId++
const name = id > 1 ? `New Document ${id}.tldr` : `New Document.tldr`
// Create a placeholder file path for the folder. Use the workspace folder
// if one exists, otherwise make up an empty one.
const workspaceFolders = vscode.workspace.workspaceFolders
const path = workspaceFolders ? workspaceFolders[0].uri : vscode.Uri.parse('')
// This triggers VS Code to open our custom editor to edit the file.
// Note: Multiple editors can register to support certain files, so
@ -62,15 +51,19 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
// we are explicitly saying to launch our editor so we're streamlined. It
// may awkwardly ask if they want to use our editor or a text editor when
// first using our extension.
vscode.commands.executeCommand('vscode.openWith', uri, TldrawEditorProvider.viewType)
vscode.commands.executeCommand(
'vscode.openWith',
vscode.Uri.joinPath(path, name).with({ scheme: 'untitled' }),
TLDrawEditorProvider.viewType
)
})
// This registers our editor provider, indicating to VS Code that we can
// handle files with the .tldr extension.
const provider = new TldrawEditorProvider(context)
const provider = new TLDrawEditorProvider(context)
const providerRegistration = vscode.window.registerCustomEditorProvider(
TldrawEditorProvider.viewType,
TLDrawEditorProvider.viewType,
provider,
{
webviewOptions: {
@ -85,7 +78,7 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
// I'm not sure about the exact semantics about this one. I'm going to leave it in though as
// it sounds right for our needs. I think this ensures we get a unique instance of our provider
// per Tldraw editor tab, vs it being shared. It would be really cool if we could support
// per TLDraw editor tab, vs it being shared. It would be really cool if we could support
// multiple tabs sharing the same document state, but separate editor state (like zoom/pan/selection),
// but this will likely be a lot of work.
//
@ -147,9 +140,9 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
// being if the file changed on disk, say from git pull that pulls down a change
// to a .tldr file you have open in a tab.
const changeDocumentSubscription = vscode.workspace.onDidSaveTextDocument((e) => {
const changeDocumentSubscription = vscode.workspace.onDidSaveTextDocument(() => {
webviewPanel.webview.postMessage({
type: EXTENSION_EVENT.LOCAL_FILE_UPDATED,
type: EXTENSION_EVENT.FILE_UPDATED,
text: document.getText(),
})
})
@ -165,8 +158,14 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
webviewPanel.webview.onDidReceiveMessage((e) => {
switch (e.type) {
case UI_EVENT.TLDRAW_UPDATED: {
// Synchronize the TextDocument with the tldraw components document state
this.synchronizeTextDocument(document, JSON.parse(e.text))
// Synchronize the TextDocument with the tldraw components document state
const prevFile = JSON.parse(document.getText()) as TLDrawFile
const nextFile = JSON.parse(e.text) as TLDrawFile
nextFile.document = sanitizeDocument(prevFile.document, nextFile.document)
this.synchronizeTextDocument(document, nextFile)
break
}
}
@ -178,7 +177,7 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
// the extension isn't actually an enclosing web page.
webviewPanel.webview.postMessage({
type: EXTENSION_EVENT.INITIAL_DOCUMENT,
type: EXTENSION_EVENT.OPENED_FILE,
text: document.getText(),
})
}
@ -189,7 +188,7 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
* VS Code will handle detecting if the in memory content and the on disk
* content are different, and then mark/unmark the tab as saved/unsaved
*/
private synchronizeTextDocument(document: vscode.TextDocument, json: any) {
private synchronizeTextDocument(document: vscode.TextDocument, nextFile: TLDrawFile) {
// Just replace the entire document every time for this example extension.
// A more complete extension should compute minimal edits instead.
// TODO: Make sure to keep an eye on performance problems, as this may be the
@ -201,7 +200,7 @@ export class TldrawEditorProvider implements vscode.CustomTextEditorProvider {
edit.replace(
document.uri,
new vscode.Range(0, 0, document.lineCount, 0),
JSON.stringify(json, null, 2)
JSON.stringify(nextFile, null, 2)
)
return vscode.workspace.applyEdit(edit)

Wyświetl plik

@ -1,9 +1,9 @@
import * as vscode from 'vscode'
import { TldrawEditorProvider } from './tldraw-editor'
import { TLDrawEditorProvider } from './TLDrawEditorProvider'
// This is the extension entry point. This is called once on the first
// time a .tldr extension is opened/created.
export function activate(context: vscode.ExtensionContext) {
// Register our custom editor providers
context.subscriptions.push(TldrawEditorProvider.register(context))
context.subscriptions.push(TLDrawEditorProvider.register(context))
}

Wyświetl plik

@ -23,8 +23,12 @@ export function getHtmlForWebview(
documentContent = 'null'
}
return getDevModeHTML(context, webview, documentContent)
// return getProductionModeHTML(context, webview, documentContent);
if(process.env.NODE_ENV === 'production'){
return getProductionModeHTML(context, webview, documentContent);
} else {
return getDevModeHTML(context, webview, documentContent)
}
}
/**
@ -85,13 +89,15 @@ function getProductionModeHTML(
documentContent: string
): string {
const cssUrl = webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, 'editor-build/static/css', 'index.css')
vscode.Uri.joinPath(context.extensionUri, 'editor/', 'index.css')
)
const jsUrl = webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, 'editor-build/', 'index.js')
vscode.Uri.joinPath(context.extensionUri, 'editor/', 'index.js')
)
console.log("production mode");
return `
<!DOCTYPE html>
<html lang="en">

Wyświetl plik

@ -0,0 +1,8 @@
export enum UI_EVENT {
TLDRAW_UPDATED = 'TLDRAW_UPDATED',
}
export enum EXTENSION_EVENT {
OPENED_FILE = 'OPENED_FILE',
FILE_UPDATED = 'FILE_UPDATED',
}

Wyświetl plik

@ -0,0 +1,21 @@
import type { TLDrawDocument } from '@tldraw/tldraw'
export function getNonce() {
let text = ''
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length))
}
return text
}
export function sanitizeDocument(prev: TLDrawDocument, next: TLDrawDocument): TLDrawDocument {
Object.values(prev.pageStates).forEach((pageState) => {
// Ensure that the previous page state is preserved, if possible
if (next.pages[pageState.id] !== undefined) {
next.pageStates[pageState.id] = pageState
}
})
return next
}

Wyświetl plik

@ -1,29 +0,0 @@
// imports mocha for the browser, defining the `mocha` global.
require('mocha/mocha')
export function run(): Promise<void> {
return new Promise((c, e) => {
mocha.setup({
ui: 'tdd',
reporter: undefined,
})
// bundles all files in the current directory matching `*.test`
const importAll = (r: __WebpackModuleApi.RequireContext) => r.keys().forEach(r)
importAll(require.context('.', true, /\.test$/))
try {
// Run the mocha test
mocha.run((failures) => {
if (failures > 0) {
e(new Error(`${failures} tests failed.`))
} else {
c()
}
})
} catch (err) {
console.error(err)
e(err)
}
})
}

Wyświetl plik

@ -1,12 +0,0 @@
export enum UI_EVENT {
TLDRAW_UPDATED = 'TLDRAW_UPDATED',
}
export enum EXTENSION_EVENT {
INITIAL_DOCUMENT = 'INITIAL_DOCUMENT',
LOCAL_FILE_UPDATED = 'LOCAL_FILE_UPDATED',
}
export type UIMessage = MessageEvent<{ type: UI_EVENT; text: string }>
export type ExtensionMessage = MessageEvent<{ type: EXTENSION_EVENT; text: string }>

Wyświetl plik

@ -1,9 +0,0 @@
export function getNonce() {
let text = ''
const possible =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length))
}
return text
}

Wyświetl plik

@ -1,67 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
//@ts-check
/** @typedef {import('webpack').Configuration} WebpackConfig **/
const path = require('path');
const webpack = require('webpack');
const webExtensionConfig = /** @type WebpackConfig */ {
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
target: 'webworker', // extensions run in a webworker context
entry: {
extension: './src/web/extension.ts', // source of the web extension main file
'test/suite/index': './src/web/test/suite/index.ts', // source of the web extension test runner
},
output: {
filename: '[name].js',
path: path.join(__dirname, './dist/web'),
libraryTarget: 'commonjs',
},
resolve: {
mainFields: ['browser', 'module', 'main'], // look for `browser` entry point in imported node modules
extensions: ['.ts', '.js'], // support ts-files and js-files
alias: {
// provides alternate implementation for node module and source files
},
fallback: {
// Webpack 5 no longer polyfills Node.js core modules automatically.
// see https://webpack.js.org/configuration/resolve/#resolvefallback
// for the list of Node.js core module polyfills.
assert: require.resolve('assert'),
},
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
},
],
},
],
},
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser', // provide a shim for the global `process` variable
}),
],
externals: {
vscode: 'commonjs vscode', // ignored because it doesn't exist
},
performance: {
hints: false,
},
devtool: 'nosources-source-map', // create a source map that points to the original source file
};
module.exports = [webExtensionConfig];

1124
yarn.lock

Plik diff jest za duży Load Diff