1// AGPL DN 2 3import { MergeView, unifiedMergeView, updateOriginalDoc, originalDocChangeEffect, getOriginalDoc } from "../../_node/@codemirror/[email protected]/index.a78d03ab.js" 4import { EditorView, basicSetup } from "../../_node/[email protected]/index.81cbd69a.js" 5import { EditorState } from "../../_node/@codemirror/[email protected]/index.66d24d9c.js" 6import { linter, lintGutter } from "../../_node/@codemirror/[email protected]/index.2a3a5ccc.js" 7import { ChangeSet } from "../../_node/@codemirror/[email protected]/index.66d24d9c.js" 8 9import { Text } from "../../_node/@codemirror/[email protected]/index.66d24d9c.js" 10 11import * as eslint from "../../_node/[email protected]/index.9c03d13d.js"; 12import { javascript, esLint, javascriptLanguage } from "../../_node/@codemirror/[email protected]/index.e73c2782.js"; 13import globals from "../../_node/[email protected]/index.d82c0643.js"; 14 15import { introspection as getIntrospection, compile_new, bundleIntoOne, compile, calls_fromDefinition } from "https://cdn.jsdelivr.net/gh/calculang/calculang@all_cul/packages/standalone/index.js" // sync with editor.md 16import { pre_fetch } from "https://cdn.jsdelivr.net/gh/calculang/calculang@all_cul/packages/standalone/pre_fetch.mjs" 17 18import { instance } from "../../_node/@viz-js/[email protected]/index.20a70c76.js"; 19import {html} from "../../_node/[email protected]/index.0caf36e7.js"; 20 21import snippetbuilder from "../../_node/[email protected]/index.f5695b23.js"; 22 23import jssnippetarray from "./snippetarray.24a7d79f.js" 24 25// Alt? import {Inspector} from "observablehq:runtime"; 26// https://github.com/observablehq/framework/blob/main/src/client/inspect.js#L3 27import { Inspector } from "../../_node/@observablehq/[email protected]/index.01e7abcd.js" 28 29 30 31 32const lintConfig = ({ 33 // 'config' in editor.mjs: direct copy 34 // eslint configuration 35 languageOptions: { 36 parserOptions: { 37 ecmaVersion: 2019, // ? 2022 here: https://github.com/UziTech/eslint-linter-browserify/blob/4844787ed5fe4f9173fc694d7df9bc161b15fb46/example/script.js 38 sourceType: "module" 39 }, 40 /*env: { 41 // ? 42 browser: true, 43 node: true 44 },*/ 45 globals: { ...globals.node } 46 }, 47 rules: { 48 //semi: ["warn", "always"], 49 //"no-undef": ["error", "never"], // this is a key rule for calculang, but is easier to use on JS (because of intentional undefined inputs in _in convention) 50 "func-style": ["error", "expression"], 51 "consistent-return": ["error"], // not as good as forcing a return .. 52 // no-unused-expressions works in some cases but not others? 53 // bug whenever a = () => {b()}, but b()*3 works 54 "no-unused-expressions": ["error"], // doesn't catch when there are calls because doesn't know about purity .. 55 "prefer-const": "warn", 56 "no-restricted-syntax": [ 57 // docs https://eslint.org/docs/latest/rules/no-restricted-syntax 58 "error", 59 { 60 message: "calculang: don't pollute the _ namespace", 61 selector: 62 "ImportDeclaration[source.value=/cul_scope_/] > ImportSpecifier[local.name=/_$/]" 63 // converted to esm => match cul_scope_x rather than .cul 64 } // test with import {create as confetti_} from "https://cdn.jsdelivr.net/npm/canvas-confetti/+esm?cul_scope_id=3"; 65 ] 66 67 } 68 // "extends": "eslint:recommended" not working; not sure I want 69}) 70 71 72let doc = ` 73// FizzBuzz https://calculang.dev/examples-viewer?id=fizzbuzz 74 75export const fizz = () => (i() % 3 == 0 ? 'Fizz' : ''); 76export const buzz = () => (i() % 5 == 0 ? 'Buzz' : ''); 77 78export const fizzbuzz = () => { 79 if (fizz() + buzz() != '') 80 return fizz() + buzz(); 81 return i(); 82}; 83 84//export const two_times_fizzbuzz = () => 2 * fizzbuzz(); 85 86// is is an input (by convention): 87export const i = () => i_in; 88 89// change i to a value, like 12 90// then change it back 91// This is input inference working! 92 93// Also infers when an input is SUMMARISED: (notice _in syntax) 94 95//export const fizzbuzz_10 = () => fizzbuzz({ i_in : 10 }); 96// \`fizzbuzz\` depends on i_in, but \`fizzbuzz_10\` is independent of i_in 97 98// another example of recursive formulas: 99// (memoization is a singular provided optimisation) 100 101// export const year = () => year_in; 102 103/*export const balance = () => { 104 if (year() < 0) return 0; 105 return balance({ year_in: year() - 1 }) + 100; 106};*/ 107 108// interesting to compare these formulas to formulas written in spreadsheets! 109 110// Input inference helps us to write more concise, meaningful 111// pure-functional calculations 112 113// Concise is nice! 114// But conciseness is not the purpose... 115 116// (flexibility, reusability â»ï¸ is) 117 118// to appreciate this, we need to look at modularity 119` 120 121let inhibit = false 122 123// https://codemirror.net/try/?example=Merge%20View 124export const a = ({ parent, div }) => new EditorView({ 125 //a: { 126 doc: div.fs['entry.cul.js'], 127 extensions: [ 128 basicSetup, 129 javascript(), 130 lintGutter(), 131 javascriptLanguage.data.of({ 132 autocomplete: snippetbuilder({ 133 source: jssnippetarray 134 }) 135 }), 136 linter(esLint(new eslint.Linter(), lintConfig)), 137 EditorView.updateListener.of(view => { 138 if (view.docChanged) { 139 console.log('change!') 140 //if (inhibit == false) 141 div.fs = ({...div.fs, [div.filename]: view.state.doc.toString() }) 142 div.compile() 143 //div.setFS({ "entry.cul.js": view.state.doc.toString() }) 144 //inhibit = false 145 } 146 }) 147 ], 148 parent 149}) 150 151 152export const b = ({ parent }) => new EditorView({ 153 //a: { 154 doc: '', 155 extensions: [ 156 basicSetup, 157 javascript(), 158 unifiedMergeView({ original: doc, mergeControls: false }) 159 ], 160 /*}, 161 b: { 162 doc: doc,//.replace(/t/g, "T") + "\nSix", 163 extensions: [ 164 basicSetup, 165 //EditorView.editable.of(false), 166 //EditorState.readOnly.of(true) 167 ] 168 },*/ 169 parent//: document.body 170}) 171 172export const ab = () => { 173 const gg = document.createElement('div') 174 gg.id = 'module-relationships' 175 gg.appendChild(html`<h8>ð§âð¤âð§ <span>module relationships</span> â»ï¸`) 176 177 const g = gg.appendChild(html`<div>`) 178 const div = document.createElement('div') 179 180 div.filename = 'entry.cul.js' 181 div.scope = 0 182 183 div.setFS = async (d) => { 184 inhibit = true; 185 if (1) { 186 div.scope = 0 187 div.fs = d;//({"entry.cul.js": d}) 188 // recompile 189 // update a, update ab 190 aa.dispatch(//aa.state.update( 191 { 192 changes: { from: 0, to: aa.state.doc.length, insert: div.fs['entry.cul.js'] } 193 } 194 ) 195 } inhibit = false 196 197 await div.compile() 198 } 199 200 div.setScope = d => { 201 div.scope = d 202 div.filename = [...div.introspection.cul_scope_ids_to_resource.values()][div.scope].split("?")[0] 203 document.getElementById('filename').textContent = div.filename 204 document.getElementById('scope').textContent = 'scope ' + div.scope 205 bb.dispatch(//aa.state.update( 206 { 207 changes: { from: 0, to: bb.state.doc.length, insert: div.compiled[div.scope].code } 208 } 209 ) 210 aa.dispatch(//aa.state.update( 211 { 212 changes: { from: 0, to: aa.state.doc.length, insert: div.fs[div.filename] } 213 } 214 ) 215 console.log('filename', div.filename) 216 217 updateOriginal(div.fs[div.filename]) 218 219 220 221 222 } 223 224 div.setFS({'entry.cul.js': doc}) 225 div.id = 'c' 226 //div.fs = ({'entry.cul.js': doc}) 227 const divA = document.createElement('div') 228 divA.id = 'divA' 229 divA.appendChild(html`<h2>input ð¬</h2><i id="filename">entry.cul.js`) 230 const divB = document.createElement('div') 231 divB.appendChild(html`<h2>â¡</h2><i id="scope">
231scope 0`) 232 divB.id = 'divB' 233 const aa = a({ parent: divA, div }); 234 const bb = b({ parent: divB }); 235 div.appendChild(gg) 236 div.appendChild(divA) 237 div.appendChild(divB) 238 instance().then(viz => { 239 g.appendChild(viz.renderSVGElement("digraph { place -> holder }")) 240 }); 241 242 // todo setFS / scope id 243 // and do syncing ! 244 245 246 247 248 249 div.compile = async () => { 250 251 const packageCalculang_new = async (bundledIntoOne) => { 252 253 let compiled = URL.createObjectURL( 254 new Blob( 255 [bundledIntoOne], 256 { type: "text/javascript" } 257 ) 258 ) 259 260 let ret = await import(compiled) 261 URL.revokeObjectURL(compiled) 262 return ret 263 } 264 265 updateOriginal(div.fs[div.filename]) 266 267 // from s-p 268 const new_fs0 = await pre_fetch(div.fs, 'entry.cul.js') // has all_cul -> all_cul0 269 let new_fs = {...div.fs} 270 Object.entries(new_fs0).forEach(([k,v]) => { 271 if (new_fs[k] == undefined || new_fs[k].length == 0) { 272 new_fs[k] = v 273 console.log('added k', k) 274 } 275 }) 276 div.fs = {...new_fs0} 277 278 279 div.introspection = await getIntrospection("entry.cul.js", div.fs) 280 div.inspector.fulfilled(div.introspection) 281 div.compiled = await compile_new("entry.cul.js", div.introspection.fs0 /*!!! do this for c
281ompile_new*/, div.introspection) 282 283 284 try { 285 div.inspector_compiled.fulfilled(await packageCalculang_new(bundleIntoOne(div.compiled,div.introspection, true))) 286 } catch(e) {console.error('ERR', e)} 287 288 try { 289 div.inspector_compiled2.fulfilled(await bundleIntoOne(div.compiled,div.introspection, true)) 290 } catch(e) {console.error('ERR', e)} 291 292 //debugger; 293 294 const show_query_string = false; 295 296 const scope_id_graph_links = [...div.introspection.cul_scope_ids_to_resource.entries()] 297 .filter(([cul_scope_id]) => cul_scope_id != 0) 298 .map( 299 ([cul_scope_id, resource]) => 300 new URLSearchParams(resource.split("?").pop()).get("cul_scope_id") + 301 " -> " + 302 new URLSearchParams(resource).get("cul_parent_scope_id") 303 ) 304 305 const scope_id_graph_nodes = [ 306 ...div.introspection.cul_scope_ids_to_resource.entries() 307 ].map( 308 (d) => 309 `${d[0]} [${ 310 d[0] == 0 311 ? 'color="green" style="filled" ' 312 : 'color="yellow" style="filled" ' 313 }label="[${d[0]}]: ${ 314 show_query_string 315 ? d[1].replaceAll("-nomemo", "") 316 : d[1].replaceAll("-nomemo", "").split("?")[0] 317 }"]` 318 ) 319 320 instance().then(viz => { 321 g.firstChild.replaceWith(viz.renderSVGElement(`digraph { 322 bgcolor="#90EE90" 323 ${/*rankdir="RL"*/";"} 324 rankdir="BT"; 325 node [shape="box"] 326 ${scope_id_graph_nodes.join("\n")} 327 ${scope_id_graph_links.join("\n")} 328 }`)) 329 330 //debugger;
331 g.querySelectorAll("title").values().forEach((d) => { 332 d.parentElement.onclick = (e) => { 333 console.log(d); 334 if (d.textContent[0] != "%") div.setScope(+d.textContent); 335 e.preventDefault(); 336 }; 337 }); 338 }) 339 340console.log('dn11', div.compiled[div.scope].code) 341 // redundant? 342 bb.dispatch(//aa.state.update( 343 { 344 changes: { from: 0, to: bb.state.doc.length, insert: div.compiled[div.scope].code } 345 } 346 ) 347 } 348 349 350 351 352 353 354let view = bb; 355// Function to update the original document 356function updateOriginal(newContent) { 357 console.log('new', newContent) 358 console.log('new', div.filename) 359 console.log('new', div.fs) 360 // Create a new Text instance with the new content 361 const newDoc = Text.of(newContent.split("\n")); 362 363 // Create a ChangeSet that represents the changes 364 const changes = ChangeSet.of({ 365 from: 0, 366 to: 0,//originalDoc.length, ???????? 367 insert: newContent 368 }); 369 370 // Dispatch the updateOriginalDoc effect 371 view.dispatch({ 372 effects: updateOriginalDoc.of({ doc: newDoc, changes }) 373 }); 374} 375 376//debugger; 377const n = document.createElement('div') 378const n2 = document.createElement('div') 379const n3 = document.createElement('div') 380const n4 = document.createElement('div') 381 382div.inspector = new Inspector(n); 383div.inspector.fulfilled(div.introspection) 384div.inspector_compiled = new Inspector(n2); 385div.inspector_compiled.fulfilled(div.compiled) 386div.inspector_compiled2 = new Inspector(n4); 387div.inspector_compiled2.fulfilled(div.compiled) 388 389n3.appendChild(html`<h2 style="color: lightgray">output ð`) 390n3.appendChild(html`<br/>â¹ï¸ <b>introspection`) 391n3.appendChild(n) 392n3.appendChild(html`<br/>ð« <b><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules">Javascript Module</a> <span style="font-size:0.5em">ð</span>`) 393n3.appendChild(n2) 394 395n3.appendChild(html`<br/>ð <b>Javascript Code`) 396n3.appendChild(n4) 397 398 399div.appendChild(n3) 400//Inspector.into(n).fulfilled({hi: 'world'}) 401 402 403return div 404}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.