npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ng-scorm-player

v1.0.0

Published

Lecteur SCORM 1.2 et SCORM 2004 pour Angular : joue un paquet SCORM et remonte progression, score, temps passé et données de reprise.

Readme

ng-scorm-player

Lecteur SCORM pour Angular. Il joue un paquet SCORM 1.2 ou SCORM 2004, expose l'API d'exécution que le contenu attend, et vous rend un résultat exploitable : progression, score, temps passé, données de reprise.

npm licence MIT


Installation

npm install ng-scorm-player

Angular 20 ou supérieur. La bibliothèque a besoin de HttpClient pour lire imsmanifest.xml.

Démarrage

import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { provideNgScormPlayer } from 'ng-scorm-player';

bootstrapApplication(App, {
  providers: [
    provideHttpClient(),
    provideNgScormPlayer({ learnerName: 'Dupont, Marie', learnerId: '42' }),
  ],
});
import { Component } from '@angular/core';
import { NgScormPlayerComponent, ScormResult } from 'ng-scorm-player';

@Component({
  selector: 'app-cours',
  imports: [NgScormPlayerComponent],
  template: `
    <ng-scorm-player
      urlDirSco="/assets/paquets/securite-incendie"
      (finished)="enregistrer($event)"
      (committed)="enregistrer($event)"
    />
  `,
})
export class CoursComponent {
  enregistrer(resultat: ScormResult) {
    // resultat.completed, resultat.scorePercent, resultat.suspendData…
  }
}

Le composant occupe toute la hauteur de son conteneur : donnez-lui un parent dimensionné.

Entrées

| Entrée | Type | Description | | --- | --- | --- | | urlDirSco | string | Dossier du paquet décompressé. Le manifeste y est lu pour trouver la page de lancement. | | urlLaunchPage | string | Page de lancement directe. Le manifeste n'est alors pas lu. | | openInNewWindow | boolean | Ouvre le contenu dans une fenêtre séparée au lieu du cadre intégré. |

Donnez urlDirSco ou urlLaunchPage. Si les deux sont fournis, urlLaunchPage l'emporte.

Sorties

| Sortie | Émise quand | | --- | --- | | initialized | le contenu appelle Initialize / LMSInitialize | | valueChanged | à chaque SetValue | | committed | à chaque Commit — c'est ici qu'il faut enregistrer | | finished | le contenu appelle Terminate / LMSFinish | | loadError | la page de lancement n'a pas pu être déterminée |

Écoutez committed autant que finished : beaucoup de contenus enregistrent régulièrement sans jamais terminer proprement, et un apprenant qui ferme son navigateur ne déclenche pas Terminate.

Le résultat

interface ScormResult {
  version: '1.2' | '2004';
  timeSpent: number;          // secondes, session en cours
  totalTime: number;          // secondes, cumul avec les sessions précédentes
  progression: number | null; // 0 à 100, null si le contenu ne le remonte pas
  completed: boolean;
  passed: boolean | null;     // null tant que le contenu ne tranche pas
  completedOn: Date | null;
  score: number | null;
  scoreMin: number | null;
  scoreMax: number | null;
  scorePercent: number | null;
  location: string;           // signet de reprise
  suspendData: string;        // état interne du contenu
  exit: string;
  runtimeData: Record<string, string>;
}

null signifie « le contenu n'a rien remonté », ce qui n'est pas la même chose que zéro. Un module sans quiz laisse score à null ; un quiz raté remonte score: 0.

Reprise de session

Rendez au contenu ce qu'il vous avait confié :

provideNgScormPlayer({
  initialData: {
    'cmi.suspend_data': resultatPrecedent.suspendData,
    'cmi.location': resultatPrecedent.location,
    'cmi.total_time': 'PT0H20M0S',
  },
});

cmi.entry passe automatiquement à resume, ce que le contenu vérifie avant de proposer de reprendre. En SCORM 1.2, utilisez les clés cmi.core.lesson_location et cmi.core.total_time.

Configuration

| Option | Défaut | Description | | --- | --- | --- | | debug | false | Trace tous les échanges avec le contenu dans la console. | | strict | false | Applique les règles d'accès de la spécification (erreur 404 sur écriture en lecture seule). Utile pour valider un paquet, à laisser désactivé en production. | | learnerId / learnerName | '' | Identité rendue au contenu. | | initialData | — | Modèle de données d'une session précédente. | | openInNewWindow | false | Fenêtre séparée plutôt que cadre intégré. | | iframeTitle | 'Contenu SCORM' | Titre accessible du cadre. |

Le contenu doit être servi depuis la même origine

Un SCO cherche son API en remontant la hiérarchie des cadres : window.parent.API. Si le contenu est servi depuis une autre origine, le navigateur bloque cet accès et SCORM ne fonctionne pas — ce n'est pas une limite de cette bibliothèque, c'est la politique de même origine.

Le sandbox appliqué au cadre est :

allow-scripts allow-forms allow-same-origin allow-modals allow-popups allow-downloads

Il n'est pas configurable, et ce n'est pas un oubli : Angular refuse toute liaison dynamique sur cet attribut (erreur NG0910), parce qu'une valeur calculée pourrait en retirer silencieusement les restrictions. allow-top-navigation, présent en 0.1.x, en est retiré — il permettait à un contenu tiers de rediriger la page entière de votre application.

Un seul lecteur par page

Le contenu cherche window.parent.API, qui est un point d'entrée unique. Deux composants ng-scorm-player sur la même page se disputent ce nom ; le second écrase le premier et un avertissement est émis dans la console. Si vous avez besoin d'afficher deux modules simultanément, isolez-les dans des cadres distincts.

Utilitaires exportés

Les fonctions internes sont exportées, elles servent aussi hors du composant :

import { parseScormDuration, resolveLaunchHref, scormErrorString } from 'ng-scorm-player';

parseScormDuration('00:05:32'); // 332   (SCORM 1.2)
parseScormDuration('PT1H30M5S'); // 5405 (SCORM 2004)
resolveLaunchHref(xmlDuManifeste); // { href, resourceId, resolvedBy }
scormErrorString(403); // 'Data model element value not initialized'

Applications organisées en NgModule

Le composant est autonome. Pour du code existant, NgScormPlayerModule.forRoot(config) reste disponible, marqué déprécié.


Migrer depuis la 0.1.x

La 1.0 corrige des écarts à la spécification qui changent le comportement observable. Les points à vérifier :

Les fonctions de l'API renvoient des chaînes. SCORM impose "true" et "false", pas des booléens. Si vous appeliez le service directement, adaptez vos comparaisons.

ScormResult a changé de forme. score et scoreMax, déclarés mais jamais renseignés en 0.1.x, le sont désormais. completed est un vrai booléen. Les nouveaux champs totalTime, passed, location, suspendData, exit et version s'ajoutent. Les champs non renseignés valent null plutôt qu'undefined.

L'entrée scormResult a disparu. Elle ne servait à rien : le résultat sort du composant, il n'y entre pas. Pour la reprise, utilisez initialData.

Le module n'est plus obligatoire. NgScormPlayerModule fonctionne toujours, mais provideNgScormPlayer() est la voie recommandée.

Ce qui est corrigé

| | 0.1.x | 1.0 | | --- | --- | --- | | Temps passé en SCORM 1.2 | perdu — le format HH:MM:SS n'était pas reconnu, l'exception était avalée | lu correctement | | Résultat sur un paquet SCORM 1.2 | vide — seules les clés SCORM 2004 étaient lues | les deux modèles sont lus | | score et scoreMax | jamais renseignés | renseignés | | scorePercent | seulement si le contenu remontait score.scaled | calculé aussi depuis raw, min et max | | Codes d'erreur | inventés (1 à 6) | codes normalisés SCORM | | GetLastError | renvoyait la première erreur, à jamais | renvoie la dernière, remise à zéro après un appel réussi | | Valeur de retour | booléens JavaScript | chaînes "true" / "false" | | Appels hors séquence | acceptés silencieusement | refusés avec le code attendu (103, 112, 122, 132…) | | Valeurs initiales | modèle de données vide | valeurs par défaut de la spécification | | _children et _count | absents | fournis et tenus à jour | | Page de lancement | première ressource du manifeste, souvent la mauvaise | suit l'organisation par défaut et identifierref | | xml:base du manifeste | ignoré | appliqué | | Reprise de session | impossible | initialData | | Cadre ciblé par getElementById | collision entre instances | référence locale au composant | | API laissée sur window | après destruction du composant | retirée proprement | | allow-top-navigation | activé | retiré |


Licence

MIT — voir LICENSE.

Développé et maintenu par Geduk, plateforme de formation en ligne française.