Skip to content

Commit

Permalink
Merge pull request #1 from dvd101x/codemirror-6
Browse files Browse the repository at this point in the history
Codemirror 6
  • Loading branch information
dvd101x authored Mar 2, 2024
2 parents 71f6e26 + 9f069c6 commit 1432f52
Show file tree
Hide file tree
Showing 16 changed files with 1,766 additions and 305 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/build-github-pages.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# https://github.com/marketplace/actions/deploy-to-github-pages
name: Build and Deploy to Github Pages

on:
push:
branches:
- main

permissions:
contents: write

jobs:
build-and-deploy:
concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession.
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v3

- name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built.
run: |
npm ci
npm run build
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: dist # The folder the action should deploy.
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# Web Thermodynamics
This is a simple example of how to run CoolProp Javascript wrapper with units handled by mathjs.

This is an example of how to run CoolProp Javascript wrapper with units handled by mathjs, including a code editor.

[![interface](interface.png)](https://dvd101x.github.io/web-thermodynamics/
)

# To-Do
- [ ] Migrate to codemirror 6 with a build tool like Vite
- [x] Migrate to codemirror 6 with a build tool like Vite
- [ ] Migrate the language definition to CM6
- [ ] Scroll outputs into view and highlight them
- [ ] Not only text outputs (allow for latex)
- [x] Scroll outputs into view and highlight them
- [x] Not only text outputs (allow for latex)
- [ ] More efficient math evaluation (only update state when inputs change)
- [ ] Evaluate expression by expression (not necessarly block by block)
- [ ] Use Alpinejs to reduce code
- [x] Use Alpinejs to reduce code
- [ ] Dynamic autocomplete

# Basic example

Expand Down Expand Up @@ -226,12 +228,12 @@ cond_COP = Q_h/W_comp

# # Final results

print('Compressor power : $0 \t$1\t$2', W_comp to [W, BTU/h, TR], 4)
print('Condenser heat out : $0 \t$1\t$2', Q_h to [W, BTU/h, TR], 4)
print('Evaporator heat in : $0 \t$1\t$2', Q_c to [W, BTU/h, TR], 4)
print('Compressor power : $1 \t$2\t$3', W_comp to [W, BTU/h, TR], 4)
print('Condenser heat out : $1 \t$2\t$3', Q_h to [W, BTU/h, TR], 4)
print('Evaporator heat in : $1 \t$2\t$3', Q_c to [W, BTU/h, TR], 4)

print('COP(cooling) : $0', [evap_COP], 3)
print('COP(heating) : $0', [cond_COP], 3)
print('COP(cooling) : $1', [evap_COP], 3)
print('COP(heating) : $1', [cond_COP], 3)
```
Shall return:

Expand All @@ -253,7 +255,7 @@ COP(heating) : 3.57
Here is a similar project [Engineering-Solver](https://github.com/dvd101x/Engineering-Solver) that includes additional features:

* Saves in the browser (you can continue where you left off)
* 9 workspaces, so you can try different things
* 20 workspaces, so you can try different things
* Uses a webworker to avoid freezing during big calculaitons
* A few more examples focused on the many features of mathjs

Expand All @@ -265,7 +267,7 @@ Uses the following js libraries
* [Mathjs](https://mathjs.org/)
* [CoolProp](http://www.coolprop.org/)
* Editing
* [CodeMirror 5](https://codemirror.net/5/)
* [CodeMirror](https://codemirror.net/)
* Rendering results
* [Markdown-it](https://github.com/markdown-it/markdown-it)
* [markdown-it-katex](https://github.com/waylonflinn/markdown-it-katex)
Expand Down
18 changes: 10 additions & 8 deletions fluidProperties.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {number, unit} from 'mathjs'

// List of units from coolprop
const propUnit = {
'': '',
Expand Down Expand Up @@ -253,12 +255,12 @@ function calcPropUnits(prop) {
}
}

// This is created only bacuse math.number(value,'') is not valid as '' can't be the unit
toValue = (v, u) => u ? math.number(v, u) : math.number(v)
// This is crate only becous math.unit(value,'') is not valid as '' can't be the unit
toUnit = (v, u) => u ? math.unit(v, u) : math.unit(v)
// This is created only because number(value,'') is not valid as '' can't be the unit
const toValue = (v, u) => u ? number(v, u) : number(v)
// This is crate only because unit(value,'') is not valid as '' can't be the unit
const toUnit = (v, u) => u ? unit(v, u) : unit(v)

function props(desiredProperty, fluidName, fluidProperties) {
export function props(desiredProperty, fluidName, fluidProperties) {
const calcPropUnit = calcPropUnits(desiredProperty)
let prop = Object.keys(fluidProperties).slice(0,2)
let value = Object.values(fluidProperties).slice(0,2)
Expand All @@ -280,7 +282,7 @@ function props(desiredProperty, fluidName, fluidProperties) {
return toUnit(calcValue, calcPropUnit)
}

function HAprops(calcProp, fluidProperties) {
export function HAprops(calcProp, fluidProperties) {
const calcPropUnit = HApropUnit[calcProp]
const arrayProperties = Object.entries(fluidProperties)

Expand All @@ -304,8 +306,8 @@ function HAprops(calcProp, fluidProperties) {
return toUnit(calcValue, calcPropUnit)
}

function phase(fluid, fluidProperties) {
export function phase(fluid, fluidProperties) {
return phases[props('Phase',
fluid,
fluidProperties)]
}
}
59 changes: 59 additions & 0 deletions getExpressions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { parse } from 'mathjs'

/**
* Extracts parsable expressions from a multiline string.
*
* @param {string} str - The multiline string containing expressions.
* @returns {Array<{from: number, to: number, source: string}>} An array of objects,
* where each object represents a parsable expression and contains:
* - from: The starting line number of the expression within the original string.
* - to: The ending line number of the expression within the original string.
* - source: The actual string content of the expression.
*/
export default function getExpressions(str) {
const lines = str.split('\n');
let nextLineToParse = 0;
const result = [];

for (let lineID = 0; lineID < lines.length; lineID++) {
const linesToTest = lines.slice(nextLineToParse, lineID + 1).join('\n');
if (canBeParsed(linesToTest)) {
if (!isEmptyString(linesToTest)) {
result.push({ from: nextLineToParse, to: lineID, source: linesToTest });
}
// Start the next parsing attempt from the line after the successfully parsed expression.
nextLineToParse = lineID + 1;
}
}
// Handle any remaining lines that couldn't be parsed as expressions.
const linesToTest = lines.slice(nextLineToParse).join('\n');
if (!isEmptyString(linesToTest)) {
result.push({ from: nextLineToParse, to: lines.length - 1, source: linesToTest });
}
return result;
}

/**
* Determines whether a given expression can be successfully parsed.
*
* @param {string} expression - The expression to parse.
* @returns {boolean} True if the expression can be parsed, false otherwise.
*/
function canBeParsed(expression) {
try {
parse(expression)
return true
} catch (error) {
return false
}
}

/**
* Checks if a given string is empty or only contains whitespace characters.
*
* @param {string} str - The string to check.
* @returns {boolean} True if the string is empty or only contains whitespace, false otherwise.
*/
function isEmptyString(str) {
return str.trim() === ""
}
150 changes: 26 additions & 124 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,125 +1,27 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web thermodynamics</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown-light.min.css"
integrity="sha512-zb2pp+R+czM7GAemdSUQt6jFmr3qCo6ikvBgVU6F5GvwEDR0C2sefFiPEJ9QUpmAKdD5EqDUdNRtbOYnbF/eyQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.4/katex.min.css"
integrity="sha512-mQwom8Ns4op+H29oDkD/LXO/OsXPvCFfkgZkFAVrhhePzRLU8NUI3Nkm43NhWUSmj3p5Cca2HTEkMQmXQRwDQQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.4/katex.min.js"
integrity="sha512-sHSNLECRJSK+BFs7E8DiFc6pf6n90bLI85Emiw1jhreduZhK3VXgq9l4kAt9eTIHYAcuQBKHL01QKs4/3Xgl8g=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.1/markdown-it.min.js"
integrity="sha512-SYfDUYPg5xspsG6OOpXU366G8SZsdHOhqk/icdrYJ2E/WKZxPxze7d2HD3AyXpT7U22PZ5y74xRpqZ6A2bJ+kQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/markdown-it-texmath/css/texmath.min.css">
<script src="https://cdn.jsdelivr.net/npm/markdown-it-texmath/texmath.min.js"></script>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/codemirror.min.css"
integrity="sha512-uf06llspW44/LZpHzHT6qBOIVODjWtv4MxCricRxkzvopAlSWnTf6hpZTFxuuZcuNE9CBQhqE0Seu1CoRk84nQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/fold/foldgutter.min.css"
integrity="sha512-YwkMTlTHn8dBnwa47IF+cKsS00HPiiVhQ4DpwT1KF2gUftfFR7aefepabSPLAs6zrMyD89M3w0Ow6mQ5XJEUCw=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/dialog/dialog.min.css"
integrity="sha512-Vogm+Cii1SXP5oxWQyPdkA91rHB776209ZVvX4C/i4ypcfBlWVRXZGodoTDAyyZvO36JlTqDqkMhVKAYc7CMjQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/theme/blackboard.min.css"
integrity="sha512-KnHAkH0/78Cyjs1tjV9/+00HK8gu1uKRCCKcWFxX0+rehRh9SYJqiG/2fY4St7H8rPItOsBkgQjN0m4rL5Wobw=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/hint/show-hint.min.css"
integrity="sha512-W/cvA9Wiaq79wGy/VOkgMpOILyqxqIMU+rkneDUW2uqiUT53I6DKmrF4lmCbRG+/YrW0J69ecvanKCCyb+sIWA=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/codemirror.min.js"
integrity="sha512-t5Lcu24FbQybGnoIbv1GXDx633tW0Hd4reBUx74EIq/2Q39FzskADNbjc605pQA9kkojC+8bRXhHKEXoKJs3rw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/selection/active-line.min.js"
integrity="sha512-TsecZtfqEhbHwO6rluZPT1HwhmvJ6XdhKYF+lfdRy82b5dLkf7WA++o1yOKMn/gLapbdWH+wJRInq1VYlLOhuw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/fold/foldcode.min.js"
integrity="sha512-9pu1V/0h+OfpTNLbCZnMalfd2Iinys+euBVsq0Jghp1U5KJAkTYx1OIyEsrtyhuR/SI5k91k4+VUHDAGd5TMEQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/fold/foldgutter.min.js"
integrity="sha512-VloKQ3escS4gyLRZoLPu3n5NwRp019gN3bxgriGmyWeICdMpUOV/jINpE+Zt3GJiRmyBrKNZtcNlmJrffPY/ig=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/fold/brace-fold.min.js"
integrity="sha512-GA5i/fHXry75tEFjUUImNRApI18Qchichl6UWrGtv19OPufCrfbtCGFGygNCe1OWaPr9ubvcSLoPD01uAx/9vw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/search/searchcursor.min.js"
integrity="sha512-NvqB4zhyjudFSZLywSPayM4MO3/OS1zyCD/qSAlCaEuhXxo0SWIiTGqXl/eUvmMEABvsloZfQ8G8qbhv4E7OLA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/search/search.min.js"
integrity="sha512-nVG8Yf3YjbBC5bjc8P0Vg/NLsWuShgNVMHbGanq/u4js7d71GVld/u2JKKU9MOk+nDRZV4Pl6PuGb93a4Oyt0w=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/search/jump-to-line.min.js"
integrity="sha512-cFdaiExVrVnsHaQhcn3wR9zyndnXI6w7diUSonYbGoV6v/PgBEGZevVC4gvg+Jz5yfO3K0/r1ZMk3+IcdEl+pQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/search/matchesonscrollbar.min.css"
integrity="sha512-h4gYceFQpTbeHoczmjo5uOd3MIEXhf1k7LTrsPLIDrOUGu0fiT0SXB6JfoR2iAg8ml7c0cN8Eq4pvD56LLaZGw=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/search/matchesonscrollbar.min.js"
integrity="sha512-QewO4zKWKKWZu8gL0GixoMAG4zzOz73cag2hKO8yOrByXXt/81xnYKYICWcRsm/wzZ+Cz3+VzfUFbQQGDRktaw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/search/match-highlighter.min.js"
integrity="sha512-SDFirmFEmyAmjoeQZv8oWUQP5iN766YScVH5VH3ReX+wOMlzP8PwRoxs9OSJKTzi4pVjoxlnkSBS/AkZsYlREA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/scroll/annotatescrollbar.min.js"
integrity="sha512-mx9ARmXHJ6yAR17uFSPIShDGmztByux77pLiFqSvmYDHiUqCgRp0NZ9djRBFmbu3bUw5LTqgYtLqHjtfqmsUlg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/dialog/dialog.min.js"
integrity="sha512-wORgIxiT2jtk5rkEfkQekASddOaXrblQLaFU0ls+KdpzJuy6RCjh/7DVv1haiIVQ88kae4hoWqj6BmXf7n9G5Q=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/edit/matchbrackets.min.js"
integrity="sha512-TKAAM4/TMGtdnRL3xqxukcysizlz2XB3h14u0EnEHdLbjpgYLvpquHchWQFs45se/+MLg6GhE0YIb9j4yYpx5g=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/edit/closebrackets.min.js"
integrity="sha512-Lk91mciLnDGIrESA4dHaDkw8uedEePZZKC+C3qqWgPtEywRhVlUAzipWUFhEECTrfb23ztNUdY1eaB4+Cg08hA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/hint/show-hint.min.js"
integrity="sha512-WxU3IAcP5emKYNYiItg4dn5aYPdhnjyqWV8eqaMbUjOPhl2U9XKyC3bkuo07HELMKM3fnoo5wLRdt3Zo50alXQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/hint/anyword-hint.min.js"
integrity="sha512-wdYOcbX/zcS4tP3HEDTkdOI5UybyuRxJMQzDQIRcafRLY/oTDWyXO+P8SzuajQipcJXkb2vHcd1QetccSFAaVw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/comment/comment.min.js"
integrity="sha512-XAwPTTgFChIGLMBUTHMBsZdVSQoJOT0r2ICrNhgg5dLJgF+GYZh51Fq3E4L7wuPADPB+9HHSmXDdxIaA9MQznw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/addon/display/panel.min.js"
integrity="sha512-kmBUVpJQ38pwt2t8qM1ICtmpxJm+F6qCez/NR2eg6BX5c6VZR/APrJJ8k3kdty5uXGLz6pHg9WmIwHCefYs8tw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.14/keymap/sublime.min.js"
integrity="sha512-U1BUDokxSNXBwAwiGC+s1dR+iqZo8Bb1EcDutBLLCnTEOfc8xc4UFeuysDT9Py4GCE8U73PCxvrH+p1wp7GQ1A=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!--
-->
<script src="mathjs.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.11.0/math.min.js" integrity="sha512-VMIzok05yICztVJ0Pu2ZXHHz6Pe+fNONIcepOD3kzgL0SJG3GH4IO3DmBRO766hIWUOHIS/IWdSqRGWWzgzqRw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="coolprop.js"></script>
<script src="fluidProperties.js"></script>
<script src="mathSetup.js"></script>
</head>

<body>
<main>
<textarea id="editor"></textarea>
<article id="output" class="markdown-body">
<h1>Type and get results - just like that!</h1>
</article>
</main>
<script src="script.js" defer></script>
</body>

</html>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web thermodynamics</title>
<script src="/coolprop.js"></script>
</head>
<body>
<main x-data="app">
<div id="editor" @doc-changed.camel.debounce="calcExpressions"
@selection-changed.camel="getCurrentLine"
></div>
<article id="output" class="markdown-body">
<template x-for="expression in expressions">
<div class="results"
:class=" (currentLine >= expression.from) && (currentLine <= expression.to) ? 'highligted' : ''"
x-html="expression.outputs" x-show="expression.visible"
x-effect="if((currentLine >= expression.from) && (currentLine <= expression.to)) $el.scrollIntoView({ block: 'nearest', inline: 'start'})">
</div>
</template>
</article>
</main>
<script type="module" src="/main.js"></script>
</body>
</html>
Loading

0 comments on commit 1432f52

Please sign in to comment.