Editor TOML
Apri l'editor

Integrare l'editor TOML nel tuo sito web

Per sviluppatori: come inserire l'editor TOML nella tua pagina - in un iframe, in una finestra a sé o in sola lettura - e come documenti, salvataggi e risultati di un'IA passano tra l'editor e il tuo server. Non servono né registrazione né chiavi da parte nostra.

Qualsiasi pagina https (e localhost) può integrare l'editor con un <iframe> e ?embed=1 - senza registrazione, senza chiave. Integrato, l'editor nasconde il testo della pagina e mostra un pulsante Salva. Ci sono quattro modi per far entrare e uscire il documento.

1. Aprire un file da un link, salvare sul tuo server

src= apre un file (il tuo server deve consentire CORS), webhook= fa sì che «Salva» (Ctrl+S) invii il documento a quell'indirizzo. Aggiungi &auto per salvare dopo ogni modifica.

<iframe src="https://toml.giit.ch/it/?embed=1&src=https://your-site.com/config/app.toml&webhook=https://your-site.com/save.php"
        allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>

Il webhook riceve un POST con JSON { editor: "toml", event: "save", id, name, content, updated }. Un link non contiene token (finirebbe nei log del server e nella cronologia del browser), quindi un webhook nell’indirizzo è adatto a un indirizzo di salvataggio che non ne richiede uno, per esempio su localhost o nella tua intranet. Per un server pubblico, passa il webhook con un token in tomleditor:load (hook: { url, token }) e verifica il token, come fa questo piccolo script PHP:

<?php
header('Access-Control-Allow-Origin: https://toml.giit.ch');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Methods: POST, OPTIONS');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') exit;
if (($_SERVER['HTTP_AUTHORIZATION'] ?? '') !== 'Bearer SECRET') { http_response_code(403); exit; }
$d = json_decode(file_get_contents('php://input'), true);
$name = preg_replace('/[^\w\- ]/u', '_', $d['name']);
file_put_contents(__DIR__ . "/config/$name.toml", $d['content']);
echo '{"ok":true}';

2. La tua pagina custodisce il documento (postMessage)

L'editor dice tomleditor:ready, la tua pagina risponde con tomleditor:load, l'editor segnala tomleditor:loaded, tomleditor:change alle modifiche reali e tomleditor:save quando l'utente salva. La tua pagina può inviare tomleditor:get (lo stato attuale) o tomleditor:save (premi Salva). Il salvataggio passa così dal tuo login e dalla tua sessione.

<iframe id="ed" src="https://toml.giit.ch/it/?embed=1" allow="clipboard-write" style="width:100%;height:800px;border:0"></iframe>
<script>
const ed = document.getElementById('ed');
const ORIGIN = 'https://toml.giit.ch';

addEventListener('message', async e => {
  if (e.source !== ed.contentWindow || e.origin !== ORIGIN) return;
  const m = e.data;
  if (m.type === 'tomleditor:ready') {              // l'editor è pronto: passagli il documento
    ed.contentWindow.postMessage({
      type: 'tomleditor:load',
      name: 'Settings',
      content: await (await fetch('/config/app.toml')).text()
    }, ORIGIN);
  }
  if (m.type === 'tomleditor:change') document.title = '● not saved';   // una modifica reale
  if (m.type === 'tomleditor:save') {               // l'utente ha fatto clic su "Salva"
    await fetch('/api/save', { method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: m.name, content: m.content }) });
    document.title = 'Saved';
  }
});

// Un pulsante Salva sulla tua pagina: la risposta arriva come tomleditor:save
function saveNow() { ed.contentWindow.postMessage({ type: 'tomleditor:get' }, ORIGIN); }
</script>

Assistente IA nella tua pagina: funziona anche nel riquadro. Con allow="clipboard-write" sull'iframe, «Copia il prompt» usa direttamente gli appunti (altrimenti l'editor ricorre al vecchio comando di copia, o mostra il prompt da copiare a mano). Un link inviato dall'IA non può raggiungere un editor dentro un altro sito web, quindi l'editor dice all'IA e all'utente di incollare invece l'intera risposta dell'IA nell'editor - oppure di aprire l'editor in una finestra propria.

3. In una finestra propria

window.open("https://toml.giit.ch/it/?embed=window", "tomleditor-17") apre l'editor completo in una finestra propria e usa gli stessi messaggi con window.opener. Lì lo raggiungono i link di un'IA. tomleditor:load può portare anche context: { host, title, rules } - il prompt per l'IA dice allora a chi appartiene il documento e segue le tue regole - e hook: { url, token }, un webhook solo per questo documento che non viene mai salvato. Chiudere la finestra con modifiche non salvate invia tomleditor:closing.

4. IA tramite il tuo server

Passa all'editor il tuo prompt, un indirizzo sul tuo sito e una chiave per questa sessione dell'editor. La finestra dell'IA mostra allora «Connesso a» il tuo sito, ciò che dici all'IA e la scelta modificare il documento attuale o crearne uno nuovo; Copia il prompt mette tutto insieme. L'IA invia il risultato con la chiave al tuo server, e la tua pagina lo apre nell'editor - un nuovo documento si apre separatamente e resta nel browser dell'utente. Una chiave per sessione dell'editor: resta valida finché l'editor è aperto, e solo finché non ne ha una l'editor la chiede con tomleditor:key-request. L'editor non invia mai la chiave di sua iniziativa e non la salva mai; l'indirizzo deve essere https sul tuo host o su un suo sottodominio.

const key = async () => (await fetch('/api/ai-key.php?doc=17')).json();   // una chiave per sessione dell'editor
const k = await key();
ed.contentWindow.postMessage({ type: 'tomleditor:load', name: 'Settings', content, ai: {
  label: 'My Site', prompt: 'Keep every key and every comment.',
  endpoint: 'https://your-site.com/api/ai-result.php', key: k.key } }, ORIGIN);
// ricorda l'id da tomleditor:loaded e ignora change/save/closing con un altro id
// solo finché l'editor non ha una chiave:
if (m.type === 'tomleditor:key-request') { const k = await key(); ed.contentWindow.postMessage({ type: 'tomleditor:ai', key: k.key }, ORIGIN); }
// finché l'editor è aperto, avvisa il tuo server ogni minuto; chiudere l'editor o la pagina annulla la chiave
setInterval(() => fetch('/api/ai-key.php?alive=' + k.key.slice(0, 8)), 60000);
// il tuo server ha un risultato (polling, SSE …): target è "current" o "new"
ed.contentWindow.postMessage({ type: 'tomleditor:load', name: 'Settings', content: draft, from: 'ai', target }, ORIGIN);

Crea chiavi con almeno 128 bit casuali, salvane solo l'hash, lega ciascuna all'utente connesso, al documento e a questa sessione dell'editor, creane una per sessione, mantienila valida solo finché la tua pagina segnala la sessione come aperta, e annullala quando l'editor o la pagina si chiude.

L'intero protocollo è in llms.txt - dallo a un'IA e costruirà il collegamento per il tuo sistema. Gli altri editor giit funzionano allo stesso modo, ciascuno con il proprio prefisso - editors.giit.ch.

Mostrare un documento in sola lettura (visualizzatore)

?viewer=1 mostra solo il documento finito: niente codice, niente strumenti, nulla può essere modificato e nulla viene salvato nel browser. Il documento arriva da un link (#b64=, ?src=), dalla tua pagina con tomleditor:load o via POST come normale modulo verso post.php: il campo content come testo o b64 come base64, facoltativamente name, al massimo 20 MB di testo.

<form method="post" action="https://toml.giit.ch/post.php?viewer=1" target="_blank">
  <input type="hidden" name="lang" value="it">
  <input type="hidden" name="name" value="Report">
  <input type="hidden" name="b64" value="…">
  <button>Open</button>
</form>

Senza viewer=1 il documento si apre nell’editor normale. In ogni caso resta solo in memoria: non viene salvato sul server e non entra in "I miei documenti". Aperto direttamente, il visualizzatore indica che il contenuto proviene da terzi.