Lingara Lingara Τεκμηρίωση Οδηγοί API Βιβλιοθήκες Εφαρμογές Δημιουργία Ενσωμάτωση Διαδικτυακή εφαρμογή
Γλώσσα: Ελληνικά

Widget ιστότοπου

Αυτή η σελίδα έχει μεταφραστεί από τα αγγλικά. Αν οι δύο διαφέρουν, η αγγλική σελίδα είναι η σωστή. Διαβάστε την αγγλική σελίδα

Σε έναν ιστότοπο, το Lingara εκτελείται ως προσαρμοσμένο στοιχείο, <lingara-embed>. Το στοιχείο σχεδιάζει την εξάσκηση του Lingara σε ένα πλαίσιο που εξυπηρετείται από το Lingara, ώστε η σελίδα σας να μη βλέπει ποτέ τα δεδομένα του μαθητή και η σελίδα του Lingara να μη βλέπει ποτέ τα δικά σας.

Τοποθέτηση του στοιχείου

Εγκαταστήστε το @lingara/embed από το npm ή φορτώστε την έκδοσή του ως module από ένα CDN αν ο ιστότοπός σας δεν έχει bundler. Έπειτα βάλτε το <lingara-embed> στη σελίδα και ορίστε το. Το στοιχείο δέχεται:

  • plan-id, το σχέδιο μαθήματος για εξάσκηση, ένα που ανήκει στον παίκτη·
  • surface, τι θα εμφανίζεται: practice, η προεπιλογή και η μόνη επιφάνεια που υπάρχει·
  • theme, ένα από τα light, dark ή auto·
  • locale, η γλώσσα των κειμένων του ίδιου του πλαισίου, που διαφορετικά ακολουθεί τον μαθητή·
  • title, το προσβάσιμο όνομα του πλαισίου.

Η προσαρμογή της εμφάνισης σταματά στο θέμα. Η σελίδα σας δεν μπορεί να φτάσει μέσα στο πλαίσιο, και το θέμα είναι η μόνη ρύθμιση που προσφέρει.

Παροχή token

Ορίστε το tokenProvider του στοιχείου σε μια συνάρτηση που ζητά token από τον δικό σας διακομιστή. Ο διακομιστής σας το εκδίδει με την προέλευση της σελίδας, χρησιμοποιώντας ένα κιτ διακομιστή, και απαντά με το token και τη λήξη του. Το στοιχείο παραδίδει το token στο πλαίσιο μέσω μηνύματος, και αυτό δεν ταξιδεύει ποτέ σε URL.

Καταχωρίστε κάθε προέλευση στην οποία εκτελείται το widget πριν εκδώσετε token γι’ αυτήν, στις ρυθμίσεις του πελάτη σας στην κονσόλα. Η σελίδα κιτ διακομιστή εξηγεί πώς. Το API απορρίπτει ένα token που εκδόθηκε για οποιαδήποτε άλλη προέλευση, και το πλαίσιο δείχνει σφάλμα αντί για εξάσκηση.

Ένα κιτ διακομιστή μπορεί επίσης να γράψει για εσάς ολόκληρο το απόσπασμα, στοιχείο και πάροχο token μαζί, με το nonce σεναρίου της σελίδας σας αν η πολιτική ασφάλειας περιεχομένου σας χρειάζεται ένα. Το τελευταίο παράδειγμα παρακάτω το δείχνει.

Ακρόαση όσων λέει το πλαίσιο

Το πλαίσιο επικοινωνεί με το στοιχείο μέσω ενός πρωτοκόλλου μηνυμάτων με εκδόσεις, και το στοιχείο μετατρέπει ό,τι χρειάζεται η σελίδα σας σε συμβάντα DOM:

  • lingara:practice-completed όταν ο μαθητής ολοκληρώνει ένα σετ, με τα planId, setNumber, correct και total του·
  • lingara:error όταν το πλαίσιο σταματά, με ένα code και retryable. Ένα σφάλμα με δυνατότητα επανάληψης σημαίνει ότι μια νέα τοποθέτηση μπορεί να πετύχει· το πότε θα δοκιμάσετε ξανά το αποφασίζετε εσείς.

Το αποτέλεσμα της εξάσκησης φτάνει και στον διακομιστή σας, όπως περιγράφεται στα αποτελέσματα εξάσκησης.

npm install @lingara/embed@0.1.0-alpha.6
# No bundler? One module script instead:
# <script type="module" src="https://cdn.jsdelivr.net/npm/@lingara/embed@0.1.0-alpha.6/dist/lingara-embed.min.js"></script>
<!-- plan-id is a lesson plan your server made for this player. -->
<lingara-embed surface="practice" plan-id="0b9d4f2e-3c1a-4e8b-9f6d-2a7c5e1b8d40" theme="auto" title="Practice"></lingara-embed>
<script type="module">
  import { defineLingaraEmbed } from '@lingara/embed'
  defineLingaraEmbed()
</script>
// Your own endpoint, on your own server. It mints with this page's origin and
// returns exactly { token, expires_at }: the token (lgr_et_…) never touches a URL.
widget.tokenProvider = async () => {
  const response = await fetch('/lingara/token', { method: 'POST', credentials: 'same-origin' })
  if (!response.ok) throw new Error(`token endpoint answered ${response.status}`)
  return response.json()
}
widget.addEventListener('lingara:practice-completed', (event) => {
  const { planId, setNumber, correct, total } = (event as CustomEvent).detail
  console.log(`set ${setNumber} of ${planId}: ${correct}/${total}`)
})
widget.addEventListener('lingara:error', (event) => {
  const { code, retryable } = (event as CustomEvent).detail
  // `retryable` means a remount may succeed; when to try is yours to decide.
  if (retryable) setTimeout(() => widget.reload(), 30_000)
  else console.warn('Lingara practice stopped:', code)
})
Γλώσσα παραδείγματος κώδικα

TypeScript

// The page that mounts the widget: the token never appears in it.
export function practicePage(planId: string, cspNonce: string): string {
  const widget = widgetSnippet({ planId, tokenEndpoint: '/lingara/token', theme: 'auto', locale: 'fr', title: 'Pratique', nonce: cspNonce })
  return `<!doctype html><title>Practice</title>${widget}`
}

Rust

// The element, its script build and a token provider that POSTs to your
// token route. The token never appears in the markup.
let html = widget_snippet(&SnippetOptions {
    locale: Some("fr".into()),
    nonce: Some(csp_nonce.into()), // your page's CSP nonce, for a strict script-src
    ..SnippetOptions::new(plan_id, "/lingara/token")
})?;

Go

// The plan your server made for this player, and the token route above.
// Pass the request's CSP nonce when your script-src allows no inline
// script; the token itself never appears in the markup.
theme := "auto"
html, err := lingaraembed.WidgetSnippet(lingaraembed.SnippetOptions{
	PlanID:        planID,
	TokenEndpoint: "/lingara/token",
	Theme:         &theme,
	Nonce:         &cspNonce,
})
if err != nil {
	return "", err // a *lingaraembed.SnippetError names the refused option
}
return template.HTML(html), nil // already escaped by the kit

Java

// planId is the lesson plan your server made for this player. The element
// POSTs to tokenEndpoint with same-origin cookies: the token never appears
// in the markup. Pass this request's CSP nonce if your page sets one.
String html =
    WidgetSnippet.render(
        SnippetOptions.builder(planId, "/lingara/token").locale("fr").nonce(cspNonce).build());

Kotlin

// planId is the lesson plan your server made for this player. The element
// POSTs to tokenEndpoint with same-origin cookies: the token never appears
// in the markup. Pass this request's CSP nonce if your page sets one.
val html =
    widgetSnippet(
        SnippetOptions(planId, tokenEndpoint = "/lingara/token").apply {
            locale = "fr"
            nonce = cspNonce
        },
    )

Ruby

# The plan your server made for this player, rendered into your page.
# nonce: your page's CSP nonce, when its script-src allows no inline script.
def self.widget(plan_id, csp_nonce)
  Lingara::Embed.widget_snippet(plan_id: plan_id, token_endpoint: "/lingara/token", locale: "fr", nonce: csp_nonce)
end

PHP

use Lingara\Embed\SnippetOptions;
use Lingara\Embed\WidgetSnippet;

// In your page's template: the plan your server made for this player, and
// your token route. Pass the request's CSP nonce if your script-src allows
// no inline script. A bad option throws SnippetException naming its field.
function practiceWidget(string $planId, string $cspNonce): string
{
    return WidgetSnippet::render(new SnippetOptions(
        planId: $planId,
        tokenEndpoint: '/lingara/token',
        theme: 'auto',
        nonce: $cspNonce,
    ));
}

C#

app.MapGet("/practice/{planId}", (string planId, HttpContext http) =>
{
    var widget = WidgetSnippet.Render(new SnippetOptions
    {
        PlanId = planId,                              // the plan your server made for this player
        TokenEndpoint = "/lingara/token",             // same origin: the element sends this page's cookies
        Nonce = http.Items["csp-nonce"] as string,     // your CSP's nonce, if script-src has one
    });
    return Results.Content($"<!doctype html><title>Practice</title>\n{widget}", "text/html");
}).RequireAuthorization();