Skip to content

Commit

Permalink
Merge branch 'gh-pages' of https://github.com/LivelyKernel/lively4-core
Browse files Browse the repository at this point in the history
… into gh-pages
  • Loading branch information
phischdev committed Jul 18, 2024
2 parents 7345849 + ef80945 commit 4e33d8c
Show file tree
Hide file tree
Showing 19 changed files with 437 additions and 478 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Number of AST Nodes


<script>
import sloc from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'

function countNodes(srcCode) {
let nodeCount = 0
srcCode.traverseAsAST({
enter(path) {
nodeCount++;
}
})
return nodeCount
}

// const srcURL = lively4url + '/../active-expressions/src/';
// function skip(fileURL) {
// return fileURL.endsWith('utils.js')
// }
// const srcURL = lively4url + '/../aexpr-ticking/src/';
// function skip(fileURL) {
// return fileURL.endsWith('utils.js')
// }
const srcURL = lively4url + '/../aexpr-interpretation/src/';
function skip(fileURL) {
return false && fileURL.includes('babelsberg') || fileURL.endsWith('utils.js')
}
// const srcURL = lively4url + '/../aexpr-source-transformation-propagation/src/';
// function skip(fileURL) {
// return false
// }
// const srcURL = lively4url + '/../babel-plugin-aexpr-source-transformation/';
// function skip(fileURL) {
// return !fileURL.endsWith('./index.js')
// }
const { contents: files } = await fetch(srcURL, {
method: "OPTIONS",
headers: {filelist: "true"}
}).then(r => r.json())

// lively.files.visualizeFileTreeMap(srcURL)


const metrics = []
for (let file of files) {
const fileURL = srcURL + file.name;
if (fileURL.endsWith('.js') && !skip(fileURL)) {
const code = await fileURL.fetchText();
const numNodes = countNodes(code)
const sLoc = sloc(code, 'js').source
metrics.push([fileURL, `${numNodes} (${sLoc})`])
}
}

<table>{...metrics.map(([file, numNodes]) => <tr><td>{file}</td><td>{numNodes}</td></tr>)}</table>
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Convention
- ast nodes 136 = 18 + 118
- sloc (29) = (1) + (28)

[aexpr-ticking](https://github.com/active-expressions/aexpr-ticking.git)
e9b4034
e9b4034606dd286ac494f20293cf7e7e9649e0ac

- https://lively-kernel.org/lively4/aexpr/../aexpr-ticking/src/./aexpr-ticking.js 18 (1)
- https://lively-kernel.org/lively4/aexpr/../aexpr-ticking/src/./ticking/ticking-active-expressions.js 118 (28)

# Interpretation
- ast nodes 787 = 12+182+224+369
- sloc (170) = (1)+(43)+(51)+(75)

[aexpr-interpretation](https://github.com/active-expressions/aexpr-interpretation.git)
46d1d17
46d1d175b4cb040bda636fe871ef5d2f70f5e3e8

- https://lively-kernel.org/lively4/aexpr/../aexpr-interpretation/src/./aexpr-interpretation.js 12 (1)
- https://lively-kernel.org/lively4/aexpr/../aexpr-interpretation/src/./interpretation/property-accessor.js 182 (43)
- https://lively-kernel.org/lively4/aexpr/../aexpr-interpretation/src/./interpretation/listener.js 224 (51)
- https://lively-kernel.org/lively4/aexpr/../aexpr-interpretation/src/./interpretation/interpretation-active-expressions.js 369 (75)

# Compilation
- ast nodes 2281 = 730+1551
- sloc (471) = (169)+(302)

[aexpr-source-transformation-propagation](https://github.com/active-expressions/aexpr-source-transformation-propagation.git)
3154d05
3154d05af0ce410b041eb312ba57f7d32a6e7672

- https://lively-kernel.org/lively4/aexpr/../aexpr-source-transformation-propagation/src/./aexpr-source-transformation-propagation.js 730 (169)

[babel-plugin-aexpr-source-transformation](https://github.com/active-expressions/babel-plugin-aexpr-source-transformation.git)
54a712a
54a712a45175f98c0f0a627770ae811759b195da

- https://lively-kernel.org/lively4/aexpr/../babel-plugin-aexpr-source-transformation/./index.js 1551 (302)

---

---

2820 + null

all ref
5794 = 1707 + 1267 + 2820

all aexpr
3038 = 274 + 672 + 2092

interpret aexpr
926 = 787 + 139

sum aexprs
3964 = 3038 + 926

1707 - 274
1267 - 672
2820 - 2092

subsec:impl_comparison
subsec:impl_complexity
subsec:impl_qualitative_analysis
subsec:impl_quantitative_analysis


3018 = 2092 + 787 + 139
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions demos/stefan/jspdf-complex-use-case.js
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ const tapSVG = do {
const C_FRONTCARD_FILL = "black";
const C_FRONTCARD_STROKE = "black";

const svg = (<svg id='tap-icon-ubg' xmlns="http://www.w3.org/2000/svg" version="1.1"
const svg = (<svg id='tap-icon-ubg1' xmlns="http://www.w3.org/2000/svg" version="1.1"
style="background: transparent; border: 3px solid palegreen;"
width="200"
height="200" viewBox={rectToViewBox(TAP_VIEWBOX)}>
Expand All @@ -627,7 +627,7 @@ svg
};

{
const hedronTemp = document.getElementById('tap-icon-ubg')
const hedronTemp = document.getElementById('tap-icon-ubg1')
if (hedronTemp) {
hedronTemp.remove()
}
Expand Down
2 changes: 1 addition & 1 deletion demos/stefan/untitled-board-game/ubg-cards-exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class CardExporter {
const title = document.title

try {
await Promise.race([fn(), lively.sleep(10000)])
await Promise.race([fn(), lively.sleep(5 * 60 * 1000)])

document.querySelectorAll('lively-notification-list').forEach(list => list.remove())
const mutationIndicator = document.querySelector('#mutationIndicator')
Expand Down
99 changes: 99 additions & 0 deletions doc/journal/2024-07-18.md/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
## 2024-07-18 Handwritten Text Recognition using AI
*Author: @onsetsu*

<script>
const normalURL = lively4url + '/demos/stefan/handwritten-text-recognition/eng_bw.png';
const scribblyURL = lively4url + '/demos/stefan/handwritten-text-recognition/htr-test.png';

function textareaFor(text) {
return <textarea style='width: 500px; height: 150px;'>{text}</textarea>
}
</script>

### Using OpenAI

<script>
import OpenAI from "demos/openai/openai.js"

async function textFromImageOpenAI(url) {
let prompt = {
"model": "gpt-4o",
"max_tokens": 500,
"temperature": 1,
"top_p": 1,
"n": 1,
"stream": false,
"stop": "VANILLA",
"messages": [
{ "role": "system", "content": "You are a system for handwritten text recognition (htr). Given an image, extract the text in it and only answer with this text." },
{ "role": "user", "content": [
{
"type": "image_url",
"image_url": {
"url": url,
"detail": "low" // high
}
}
]}
]
}

let json = await OpenAI.openAIRequest(prompt).then(r => r.json())
return json.choices[0].message.content
}

</script>

![alt text](http://tesseract.projectnaptha.com/img/eng_bw.png "Handwritten Text"){width=400}

<script>
const text = await textFromImageOpenAI(normalURL)
textareaFor(text)
</script>

![alt text](./../../../demos/stefan/handwritten-text-recognition/htr-test.png "Handwritten Text"){width=400}

<script>
const text2 = await textFromImageOpenAI(scribblyURL)
textareaFor(text2)
</script>

### Using the OCR lib tesseract.js

- Good for OCR, not for HTR
- Has fine-grained feedback on where Words, lines, etc. are

```javascript
import { createWorker } from 'https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'

const worker = await createWorker('eng');
const ret = await worker.recognize(lively4url + '/demos/stefan/htr-test.png');
await worker.terminate();
ret.data.text
```

<script>
import { createWorker } from 'https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'

async function textFromURL(url) {
const worker = await createWorker('eng');
const ret = await worker.recognize(url);
await worker.terminate();
return ret
}
</script>

Good for OCR-friendly text:

<script>
const ret = await textFromURL(normalURL)
textareaFor(ret.data.text)
</script>

Bad for handwritten notes:

<script>
const ret = await textFromURL(scribblyURL)
textareaFor(ret.data.text)
</script>

3 changes: 3 additions & 0 deletions doc/journal/2024-07-18.md/index.md.l4a
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{"type":"Reference","version":"156251caf7bed39b90b263003775f7d9efb574f3","content":"## 2024-07-18 Handwritten Text Recognition using AI\n*Author: @onsetsu*\n\n<script>\nconst normalURL = lively4url + '/demos/stefan/handwritten-text-recognition/eng_bw.png';\nconst scribblyURL = lively4url + '/demos/stefan/handwritten-text-recognition/htr-test.png';\n\nfunction textareaFor(text) {\n return <textarea style='width: 500px; height: 150px;'>{text}</textarea>\n}\n</script>\n\n### Using OpenAI\n\n<script>\nimport OpenAI from \"demos/openai/openai.js\"\n \nasync function textFromImageOpenAI(url) {\n let prompt = {\n \"model\": \"gpt-4o\", \n \"max_tokens\": 500,\n \"temperature\": 1,\n \"top_p\": 1,\n \"n\": 1,\n \"stream\": false,\n \"stop\": \"VANILLA\",\n \"messages\": [\n { \"role\": \"system\", \"content\": \"You are a system for handwritten text recognition (htr). Given an image, extract the text in it and only answer with this text.\" },\n { \"role\": \"user\", \"content\": [\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": url,\n \"detail\": \"low\" // high\n }\n }\n ]}\n ]\n }\n\n let json = await OpenAI.openAIRequest(prompt).then(r => r.json())\n return json.choices[0].message.content\n}\n\n</script>\n\n![alt text](http://tesseract.projectnaptha.com/img/eng_bw.png \"Handwritten Text\"){width=400}\n\n<script>\nconst text = await textFromImageOpenAI(normalURL)\ntextareaFor(text)\n</script>\n\n![alt text](./../../../demos/stefan/handwritten-text-recognition/htr-test.png \"Handwritten Text\"){width=400}\n\n<script>\nconst text2 = await textFromImageOpenAI(scribblyURL)\ntextareaFor(text2)\n</script>\n\n### Using the OCR lib tesseract.js\n\n- Good for OCR, not for HTR\n- Has fine-grained feedback on where Words, lines, etc. are\n\n```javascript\nimport { createWorker } from 'https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'\n\nconst worker = await createWorker('eng');\nconst ret = await worker.recognize(lively4url + '/demos/stefan/htr-test.png');\nawait worker.terminate();\nret.data.text\n```\n\n<script>\nimport { createWorker } from 'https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'\n\nasync function textFromURL(url) {\n const worker = await createWorker('eng');\n const ret = await worker.recognize(url);\n await worker.terminate();\n return ret\n}\n</script>\n\nGood for OCR-friendly text:\n\n<script>\nconst ret = await textFromURL(normalURL)\ntextareaFor(ret.data.text)\n</script>\n\nBad for handwritten notes:\n\n<script>\nconst ret = await textFromURL(scribblyURL)\ntextareaFor(ret.data.text)\n</script>\n\n"}
{"from":1552,"to":1552,"name":"color","color":"#9ecae1"}
{"from":1138,"to":1138,"name":"color","color":"#9ecae1"}
Original file line number Diff line number Diff line change
@@ -1,56 +1,23 @@
console.log(123)
export default function ({ template, types: t }) {
return {
name: 'sample data bindings (<~)',
visitor: {
Program(program) {
// handle squiggly arrow operator
function leftRightOfSquigglyArrow(path) {
if (!path.isBinaryExpression()) { return [] }
if (path.node.operator !== '<') { return [] }

let right
const expression = path.get('right')
if (expression.isUnaryExpression() && expression.node.operator === '~') {
right = expression.get('argument')
} else {
expression.traverse({
UnaryExpression(unary) {
if (unary.node.operator !== '~') { return }
if (expression.node.loc.start.index !== unary.node.loc.start.index) { return }
unary.stop()
unary.replaceWith(unary.get('argument').node)
right = expression
}
})
}
debugger
if (!right) { return [] }

const left = path.get('left')
if (!left.isLVal()) {
throw left.buildCodeFrameError("Unassignable left-hand side of data binding")
}

return [left, right]
}

program.traverse({
ExpressionStatement(expressionStatementPath) {
const path = expressionStatementPath.get('expression');
ExpressionStatement(stmt) {
const path = stmt.get('expression');
const [left, right] = leftRightOfSquigglyArrow(path);
if (!left || !right) {
// path.replaceWith(t.numberLiteral(123))
return
}

const valueName = right.scope.generateUidIdentifier('value')
const bindingTemplate = template(`aexpr(() => EXPRESSION)
.dataflow(${valueName.name} => REFERENCE = ${valueName.name})`)
path.replaceWith(bindingTemplate({
REFERENCE: left.node,
EXPRESSION: right.node,
}))
if (!left || !right) { return }

// path.replaceWith(t.numberLiteral(123))

// const name = path.scope.generateUidIdentifier('value').name;
// const db = template(`ae(EXPR).onChange(${name} => REF = ${name})`)({
// EXPR: right,
// REF: left
// });
// path.replaceWith(db)
}
})
}
Expand All @@ -59,7 +26,35 @@ export default function ({ template, types: t }) {
}


function leftRightOfSquigglyArrow(path) {
if (!path.isBinaryExpression()) { return [] }
if (path.node.operator !== '<') { return [] }

let right
const expression = path.get('right')
if (expression.isUnaryExpression() && expression.node.operator === '~') {
right = expression.get('argument')
} else {
expression.traverse({
UnaryExpression(unary) {
if (unary.node.operator !== '~') { return }
if (expression.node.loc.start.index !== unary.node.loc.start.index) { return }
unary.stop()
unary.replaceWith(unary.get('argument').node)
right = expression
}
})
}
if (!right) { return [] }

const left = path.get('left')
if (!left.isLVal()) {
throw left.buildCodeFrameError("Unassignable left-hand side of data binding")
}

console.warn('squiggly arrow found')
return [left.node, right.node]
}



Expand All @@ -68,10 +63,8 @@ export default function ({ template, types: t }) {



// const valueName = right.scope.generateUidIdentifier('value')
// const bindingTemplate = template(`aexpr(() => EXPRESSION)
// .dataflow(${valueName.name} => REFERENCE = ${valueName.name})`)
// path.replaceWith(bindingTemplate({
// REFERENCE: left.node,
// EXPRESSION: right.node,
// }))
// const db = template(`aexpr(() => SOURCE).dataflow(v => TARGET = v)`)({
// SOURCE: right,
// TARGET: left,
// });
// path.replaceWith(db)
12 changes: 12 additions & 0 deletions src/client/reactive/babel-plugin-sample-data-bindings/scribbles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const target = document.getElementById('target');

target.style.width <~ that.style.width






ae(that.style.width).onChange(v => target.style.width = v)
import { AExprRegistry } from 'src/client/reactive/active-expression/ae-registry.js'
AExprRegistry.allAsArray().last.dispose()
Loading

0 comments on commit 4e33d8c

Please sign in to comment.