├── .github └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── package.json ├── pnpm-lock.yaml ├── site ├── app │ ├── layout.tsx │ └── page.tsx ├── next-env.d.ts ├── styles.css ├── tsconfig.json └── ui │ ├── codesandbox.css │ ├── codesandbox.tsx │ └── file-tab.tsx ├── src ├── core.ts ├── index.ts ├── module.ts └── render.tsx └── tsconfig.json /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - "v*" 9 | pull_request: 10 | 11 | jobs: 12 | install: 13 | runs-on: ubuntu-latest 14 | timeout-minutes: 5 15 | 16 | name: Node 17 | steps: 18 | - name: Checkout Code 19 | uses: actions/checkout@v4 20 | 21 | - uses: pnpm/action-setup@v4 22 | 23 | - name: Use Node 18 and pnpm 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: 20 27 | cache: 'pnpm' 28 | registry-url: 'https://registry.npmjs.org' 29 | 30 | - name: Install Dependencies 31 | run: pnpm install --frozen-lockfile 32 | 33 | release: 34 | runs-on: ubuntu-latest 35 | needs: [install] 36 | if: startsWith(github.ref, 'refs/tags/') 37 | env: 38 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | 40 | steps: 41 | - name: Checkout Code 42 | uses: actions/checkout@v4 43 | 44 | - uses: pnpm/action-setup@v4 45 | 46 | - name: Use Node 18 and pnpm 47 | uses: actions/setup-node@v4 48 | with: 49 | node-version: 20 50 | cache: 'pnpm' 51 | registry-url: 'https://registry.npmjs.org' 52 | 53 | - name: Determine tag 54 | id: determine_tag 55 | run: | 56 | echo "tag=$(echo $GITHUB_REF | grep -Eo 'alpha|beta|rc')" >> $GITHUB_OUTPUT 57 | 58 | - name: Add auth token to npmrc 59 | run: | 60 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 61 | 62 | - name: Publish to versioned tag 63 | if: steps.determine_tag.outputs.tag != '' 64 | run: | 65 | echo "Publishing to ${{ steps.determine_tag.outputs.tag }} tag" 66 | pnpm publish --tag ${{ steps.determine_tag.outputs.tag }} --no-git-check 67 | 68 | - name: Publish to latest 69 | if: steps.determine_tag.outputs.tag == '' 70 | run: | 71 | echo "Publishing to latest" 72 | pnpm install --frozen-lockfile 73 | pnpm publish --no-git-check -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .next 2 | node_modules 3 | dist 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # devjar 2 | > live code runtime for your react project in browser 3 | 4 | 5 | ![image](https://repository-images.githubusercontent.com/483779830/55bf67ee-fcc6-4a12-ad0c-5221a5f78c26) 6 | 7 | ### Introduction 8 | 9 | devjar is a library that enables you to live test and share your code snippets and examples with others. devjar will generate a live code editor where you can run your code snippets and view the results in real-time based on the provided code content of your React app. 10 | 11 | Notice: devjar only works for browser runtime at the moment. It will always render the default export component in `index.js` as the app entry. 12 | 13 | ### Install 14 | 15 | ```sh 16 | pnpm add devjar 17 | ``` 18 | 19 | 20 | ### Usage 21 | 22 | #### `` 23 | 24 | `DevJar` is a react component that allows you to develop and test your code directly in the browser, using a CDN to load your dependencies. 25 | 26 | **Props** 27 | 28 | * `files`: An object that specifies the files you want to include in your development environment. 29 | * `getModuleUrl`: A function that maps module names to CDN URLs. 30 | * `onError`: Callback function of error event from the iframe sandbox. By default `console.log`. 31 | 32 | 33 | ```jsx 34 | import { DevJar } from 'devjar' 35 | 36 | const CDN_HOST = 'https://esm.sh' 37 | 38 | const files = { 39 | 'index.js': `export default function App() { return 'hello world' }` 40 | } 41 | 42 | function App() { 43 | return ( 44 | { 47 | return `${CDN_HOST}/${m}` 48 | }} 49 | /> 50 | ) 51 | } 52 | ``` 53 | 54 | #### `useLiveCode(options)` 55 | 56 | **Parameters** 57 | 58 | * `options` 59 | * `getModulePath(module)`: A function that receives the module name and returns the CDN url of each imported module path. For example, import React from 'react' will load React from skypack.dev/react. 60 | 61 | **Returns** 62 | 63 | * `state` 64 | * `ref`: A reference to the iframe element where the live coding will be executed. 65 | * `error`: An error message in case the live coding encounters an issue. 66 | * `load(codeFiles)`: void: Loads code files and executes them as live code. 67 | 68 | ```jsx 69 | import { useLiveCode } from 'devjar' 70 | 71 | function Playground() { 72 | const { ref, error, load } = useLiveCode({ 73 | // The CDN url of each imported module path in your code 74 | // e.g. `import React from 'react'` will load react from skypack.dev/react 75 | getModulePath(modPath) { 76 | return `https://cdn.skypack.dev/${modPath}` 77 | } 78 | }) 79 | 80 | // logging failures 81 | if (error) { 82 | console.error(error) 83 | } 84 | 85 | // load code files and execute them as live code 86 | function run() { 87 | load({ 88 | // `index.js` is the entry of every project 89 | 'index.js': `export default function App() { return 'hello world' }`, 90 | 91 | // other relative modules can be used in the live coding 92 | './mod': `export default function Mod() { return 'mod' }`, 93 | }) 94 | } 95 | 96 | // Attach the ref to an iframe element for runtime of code execution 97 | return ( 98 |
99 | 100 |