Skip to content

Instantly share code, notes, and snippets.

@chr5tphr
Created April 12, 2023 15:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chr5tphr/d00988e172aab8bcc824c320b4bb344a to your computer and use it in GitHub Desktop.
Save chr5tphr/d00988e172aab8bcc824c320b4bb344a to your computer and use it in GitHub Desktop.
Package a static webpage as a single-entry IMS Content Package (for use with Moodle etc.)
#!/usr/bin/env python
import os
from zipfile import ZipFile
import click
from jinja2 import Template
MANIFEST = r'''
<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"
xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
identifier="IMS-CP"
xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd
http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd">
<metadata>
<imsmd:lom>
<imsmd:general>
<imsmd:identifier>metadata-id</imsmd:identifier>
<imsmd:title>
<imsmd:langstring xml:lang="en">Simple IMS 1.1.4 Content Package</imsmd:langstring>
</imsmd:title>
</imsmd:general>
</imsmd:lom>
</metadata>
<organizations default="index_1">
<organization identifier="index_1" structure="hierarchical">
<title>Pages</title>
<item identifier="ITEM-1" isvisible="true" identifierref="INDEX-1">
<title>Index</title>
</item>
</organization>
</organizations>
<resources>
<resource identifier="INDEX-1" type="webcontent" href="index.html">
{% for file in include_files -%}
<file href="{{ file }}" />
{% endfor -%}
</resource>
</resources>
</manifest>
'''
@click.command()
@click.argument('target', type=click.Path(dir_okay=False, writable=True))
@click.argument('sourcedir', type=click.Path(file_okay=False))
def main(target, sourcedir):
rootfd = os.open(sourcedir, os.O_RDONLY)
blacklist = ['imsmanifest.xml']
include_files = [
os.path.join(root, fname)[2:]
for root, _, fnames, _ in os.fwalk('.', dir_fd=rootfd)
for fname in fnames
if fname not in blacklist
]
os.close(rootfd)
manifest = Template(MANIFEST).render(include_files=include_files)
with ZipFile(target, 'w') as zfd:
for fname in include_files:
zfd.write(os.path.join(sourcedir, fname), arcname=fname)
with zfd.open('imsmanifest.xml', 'w') as fd:
fd.write(manifest.encode())
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment