{"_id":"@elmy-org/gift-pegjs","_rev":"3-cced1bd6dfee787dcaf8387bb9a842b7","name":"@elmy-org/gift-pegjs","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.2":{"name":"@elmy-org/gift-pegjs","version":"1.0.2","author":{"name":"Saiid El Hajj Chehade"},"license":"MIT","_id":"@elmy-org/gift-pegjs@1.0.2","maintainers":[{"name":"saiid_hc","email":"saidhajjchehade@gmail.com"}],"homepage":"https://elmy-org.github.io/GIFT-grammar-PEG.js/","bugs":{"url":"https://github.com/elmy-org/GIFT-grammar-PEG.js/issues"},"dist":{"shasum":"8a8754fbcb5f42f15f0d32910d2dce66cc46cb1c","tarball":"https://registry.npmjs.org/@elmy-org/gift-pegjs/-/gift-pegjs-1.0.2.tgz","fileCount":9,"integrity":"sha512-XV5PbOT7HXjFhLgJC1v/f2NNd2Fwulkeb4CA8VcI6Yof9VbS/1JMEENyGr5wEWhGkEoJ6JZTj2WqN+bZtfj/Xw==","signatures":[{"sig":"MEUCIQDozRWsPRl72a8kZ8UcU7Ek5cwkwmmcpHbdhnbxP6Z5mgIgCyhUcO70iWz0Ppt7BYni4oBajdmiBjNhb5FHGv2/keQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":522673},"main":"pegjs-gift.js","types":"index.d.ts","gitHead":"2bd1d20d704ef2cd860f21fea23dc9fb5c8cca71","scripts":{"test":"jest --colors","build":"pegjs --format globals --export-var giftParser -o lib/gift-parser-globals.js GIFT.pegjs && cp lib/gift-parser-globals.js pegjs-gift-globals.js && pegjs -o lib/gift-parser.js GIFT.pegjs && cp lib/gift-parser.js pegjs-gift.js && bash makeHTML.sh && cp GIFT.pegjs docs/editor/lib/","start":"node server.js"},"_npmUser":{"name":"saiid_hc","actor":{"name":"saiid_hc","type":"user","email":"saidhajjchehade@gmail.com"},"email":"saidhajjchehade@gmail.com"},"repository":{"url":"git+https://github.com/elmy-org/GIFT-grammar-PEG.js.git","type":"git"},"_npmVersion":"11.3.0","description":"Parser of GIFT question format based on PEG.js","directories":{},"_nodeVersion":"24.2.0","dependencies":{"pegjs":"^0.10.x"},"_hasShrinkwrap":false,"devDependencies":{"glob":"^11.0.0","jest":"^29.7.0","connect":"^3.6.6","@types/node":"^22.5.5","serve-static":"^1.16.2","pegjs-backtrace":"^0.2.1"},"_npmOperationalInternal":{"tmp":"tmp/gift-pegjs_1.0.2_1750641184510_0.5615622774546343","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@elmy-org/gift-pegjs","version":"1.0.3","author":{"name":"Saiid El Hajj Chehade"},"license":"MIT","_id":"@elmy-org/gift-pegjs@1.0.3","maintainers":[{"name":"saiid_hc","email":"saidhajjchehade@gmail.com"}],"homepage":"https://elmy-org.github.io/GIFT-grammar-PEG.js/","bugs":{"url":"https://github.com/elmy-org/GIFT-grammar-PEG.js/issues"},"dist":{"shasum":"01d97fe78471fffcb83aedcfdf5097aa67e41825","tarball":"https://registry.npmjs.org/@elmy-org/gift-pegjs/-/gift-pegjs-1.0.3.tgz","fileCount":9,"integrity":"sha512-ZgEv93kYdOz6tp11t5B7+fqsfez/X3bE64GyX7xCvzJbuiFV6zhgdSybdZuMstrgOtJJnbyuhyFRT6VQea6Hag==","signatures":[{"sig":"MEQCIB+12PsdQC6RuYirpJ9CQ/KKyCLDhNFsF7QO7jUB9GdQAiAgtCBKl3O//wg6Ow0MHM7Zfh87lwLYoBA5ciiadiwMEA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":522663},"main":"pegjs-gift.js","types":"index.d.ts","gitHead":"069b8547000bd72764b9bef6eeab41885178b095","scripts":{"test":"jest --colors","build":"pegjs --format globals --export-var giftParser -o lib/gift-parser-globals.js GIFT.pegjs && cp lib/gift-parser-globals.js pegjs-gift-globals.js && pegjs -o lib/gift-parser.js GIFT.pegjs && cp lib/gift-parser.js pegjs-gift.js && bash makeHTML.sh && cp GIFT.pegjs docs/editor/lib/","start":"node server.js"},"_npmUser":{"name":"saiid_hc","actor":{"name":"saiid_hc","type":"user","email":"saidhajjchehade@gmail.com"},"email":"saidhajjchehade@gmail.com"},"repository":{"url":"git+https://github.com/elmy-org/GIFT-grammar-PEG.js.git","type":"git"},"_npmVersion":"11.3.0","description":"Parser of GIFT question format based on PEG.js","directories":{},"_nodeVersion":"24.2.0","dependencies":{"pegjs":"^0.10.x"},"_hasShrinkwrap":false,"devDependencies":{"glob":"^11.0.0","jest":"^29.7.0","connect":"^3.6.6","@types/node":"^22.5.5","serve-static":"^1.16.2","pegjs-backtrace":"^0.2.1"},"_npmOperationalInternal":{"tmp":"tmp/gift-pegjs_1.0.3_1750642145003_0.8332513625615463","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@elmy-org/gift-pegjs","version":"1.0.4","description":"Parser of GIFT question format based on PEG.js","main":"pegjs-gift.js","types":"index.d.ts","dependencies":{"pegjs":"^0.10.x"},"devDependencies":{"@types/node":"^22.5.5","connect":"^3.6.6","glob":"^11.0.0","jest":"^29.7.0","pegjs-backtrace":"^0.2.1","serve-static":"^1.16.2"},"scripts":{"build":"pegjs --format globals --export-var giftParser -o lib/gift-parser-globals.js GIFT.pegjs && cp lib/gift-parser-globals.js pegjs-gift-globals.js && pegjs -o lib/gift-parser.js GIFT.pegjs && cp lib/gift-parser.js pegjs-gift.js && bash makeHTML.sh && cp GIFT.pegjs docs/editor/lib/","test":"jest --colors","start":"node server.js"},"repository":{"type":"git","url":"git+https://github.com/elmy-org/GIFT-grammar-PEG.js.git"},"author":{"name":"Saiid El Hajj Chehade"},"license":"MIT","bugs":{"url":"https://github.com/elmy-org/GIFT-grammar-PEG.js/issues"},"homepage":"https://elmy-org.github.io/GIFT-grammar-PEG.js/","_id":"@elmy-org/gift-pegjs@1.0.4","gitHead":"8f26b2fed1d4b181ea0198a499fb5b3ffe1d6bdb","_nodeVersion":"24.2.0","_npmVersion":"11.3.0","dist":{"integrity":"sha512-2k/MK/c6Czf6tFtFzAMXk0WyDxhAOu/xUcvtF3pce5PjRRlK2mmwXrbXXs9r976h1JpAOTAocgx5zH0krkGixA==","shasum":"7f239ae5615e4431f9d53eddfe6294e28407aa07","tarball":"https://registry.npmjs.org/@elmy-org/gift-pegjs/-/gift-pegjs-1.0.4.tgz","fileCount":9,"unpackedSize":533838,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFRvTMrPTXkmwoEDJgK22QAkaeaqJsVc2SGwuAW/MaThAiB+lvBZj5c2yl8mDXolwKj3hhyR+4PyCf15KVNM8yOs7w=="}]},"_npmUser":{"name":"saiid_hc","email":"saidhajjchehade@gmail.com"},"directories":{},"maintainers":[{"name":"saiid_hc","email":"saidhajjchehade@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/gift-pegjs_1.0.4_1767811756205_0.01975147623699791"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-23T01:13:04.398Z","modified":"2026-01-07T18:49:16.705Z","1.0.2":"2025-06-23T01:13:04.726Z","1.0.3":"2025-06-23T01:29:05.201Z","1.0.4":"2026-01-07T18:49:16.476Z"},"bugs":{"url":"https://github.com/elmy-org/GIFT-grammar-PEG.js/issues"},"author":{"name":"Saiid El Hajj Chehade"},"license":"MIT","homepage":"https://elmy-org.github.io/GIFT-grammar-PEG.js/","repository":{"type":"git","url":"git+https://github.com/elmy-org/GIFT-grammar-PEG.js.git"},"description":"Parser of GIFT question format based on PEG.js","maintainers":[{"name":"saiid_hc","email":"saidhajjchehade@gmail.com"}],"readme":"# GIFT-grammar-PEG.js\n\n<img src=\"https://www.etsmtl.ca/getmedia/36ccff85-3834-443c-b78f-992c2b998915/Logo_ETS_SansTypo_EN\" width=\"100\">\n\n### Status\n\n[![Node.js CI](https://github.com/fuhrmanator/GIFT-grammar-PEG.js/actions/workflows/nodejs.yml/badge.svg)](https://github.com/fuhrmanator/GIFT-grammar-PEG.js/actions/workflows/nodejs.yml)\n\nDevelopment of PEG grammar to parse [GIFT (quiz question) file format](https://en.wikipedia.org/wiki/GIFT_(file_format)). The goal is to find an intuitive and fun way to create quiz questions.\n\nInitial hacking done using [peggyjs.org/online](https://peggyjs.org/online). The GIFT.pegjs file goes on the left and the test GIFT goes on the right. Note that nothing is saved in this environment (you must copy-paste back to your own files).\n\n## GIFT parser (npm package gift-pegjs) \n\nThe PEG.js grammar in this repo is used to generate a parser for GIFT. You can see how it works in this [online editor](https://fuhrmanator.github.io/GIFT-grammar-PEG.js/editor/editor.html).\n\n## Software using the parser\n\n- [GIFT Format Extension For Visual Studio Code](https://github.com/ethan-ou/vscode-gift/) by Ethan Ou.\n- Validate GIFT questions with this [online GIFT editor](https://fuhrmanator.github.io/GIFT-grammar-PEG.js/editor/editor.html) (generated on this repo via GitHub pages from the /docs directory).\n- Create quizzes in Google Forms using the [GIFT Quiz Editor (Google Forms add-on)](https://gsuite.google.com/marketplace/app/gift_quiz_editor/1038395345285). It's possible to export questions from Moodle in GIFT format and re-use them in Google Forms, or you can create your own questions in GIFT to save clicking in the Google interface. Google Quizzes are not able to support all GIFT question types, however.\n\n## For developers\n\n### Install\n\nFor simple web applications, copy the [`pegjs-gift.js`](https://raw.githubusercontent.com/fuhrmanator/GIFT-grammar-PEG.js/master/pegjs-gift.js) file into your project.\n\nFor modern Javascript development, install the library using npm:\n\n```\nnpm install gift-pegjs\n```\n\n### Usage\n\nImporting the NPM library in ES6+ Javascript (recommended):\n```javascript\nimport { parse } from \"gift-pegjs\";\n\nconst question = \"What is the value of pi (to 3 decimal places)? {#3.141..3.142}.\"\n\nconst quiz = parse(question)\n```\n\nImporting the library for simple web applications:\n```javascript\nimport { parse } from \"./pegjs-gift\"; // Change path depending on where the file is copied.\n\nconst question = \"What is the value of pi (to 3 decimal places)? {#3.141..3.142}.\"\n\nconst quiz = parse(question)\n```\n\nImporting the NPM library in CommonJS (for use in Node.js applications):\n```javascript\nconst parse = require(\"gift-pegjs\");\n\nconst question = \"What is the value of pi (to 3 decimal places)? {#3.141..3.142}.\"\n\nconst quiz = parse(question)\n```\n\nUsing the optional Typescript types:\n```typescript\nimport { parse, GIFTQuestion } from \"gift-pegjs\";\n\nconst question: string = \"What is the value of pi (to 3 decimal places)? {#3.141..3.142}.\"\n\nconst quiz: GIFTQuestion[] = parse(question)\n```\n\n### Example\n\n```javascript\nimport { parse } from \"gift-pegjs\";\n\nlet sampleQuestion = `\nIs this True? {T}\n\nMahatma Gandhi's birthday is an Indian holiday on {\n~15th\n~3rd\n=2nd\n} of October.\n\nSince {\n  ~495 AD\n  =1066 AD\n  ~1215 AD\n  ~ 43 AD\n} the town of Hastings England has been \"famous with visitors\".\n\nWhat is the value of pi (to 3 decimal places)? {#3.141..3.142}.\n`;\n\nconst quizQuestions = parse(sampleQuestion);\nconsole.log(quizQuestions);\n\n```\n\n### Tests\nThere are easily extendible tests from sample GIFT/JSON files in `./test/questions/`.\n\nTo be able to run the tests, you must set up your environment:\n- [Install node.js](https://nodejs.org/)\n- Clone this repo.\n- Install the node.js dependencies for this project. Inside the root directory of this repo, type: \n\n        npm install .\n\n- Run the regression tests with the following command: \n \n        npm test\n\n- Output will look something like this:\n\n\t\t> gift-pegjs@0.2.4 test\n\t\t> jest --colors\n\t\t\n\t\t PASS  tests/all-questions-harness.js\n\t\t  GIFT question types\n\t\t    √ parses GIFT (./tests/questions/): category1.gift (4 ms)\n\t\t    √ parses GIFT (./tests/questions/): categorySpecialCharacter.gift (1 ms)\n\t\t    √ parses GIFT (./tests/questions/): description1.gift (2 ms)\n\t\t    √ parses GIFT (./tests/questions/): descriptionTitleEscapedColon.gift (1 ms)\n\t\t    √ parses GIFT (./tests/questions/): descriptionWithID.gift (1 ms)\n\t\t    ...\n\t\t    √ parses GIFT (./tests/questions/): type_inferred_multiline_markdown.gift\n\t\t\n\t\tTest Suites: 1 passed, 1 total\n\t\tTests:       51 passed, 51 total\n\t\tSnapshots:   0 total\n\t\tTime:        2.415 s, estimated 3 s\n\t\tRan all test suites.\n\n- To create a new test GIFT file, just name it `foo.gift` in `./test/questions/`. The corresponding JSON file `foo.json` should exist (expected output) and can be easily generated from the output at https://peggyjs.org/online (you have to paste the `GIFT.pegjs` file into the grammar on the left first). Note: any `undefined` values from that output must be declared as `null` in the JSON file.\n\n## GIFT format\n\n*General Import Format Technology* (GIFT) is described at several places, but it's hard to know what the definitive source is.\n\nThis table is not sufficient to understand everything. Please see [Moodle's documentation](https://docs.moodle.org/en/GIFT_format) and [this reference](http://buypct.com/gift_reference.pdf) for many more details.\n\n| Symbols\t| Use |\n| ------- | ----- |\n| `//` *text*\t| Comment until end of line (optional) | \n|  `::`*title*`::`\t| Question title (optional) | \n| *text*\t| Question text (becomes title if no title specified)| \n| `[`*format*`]`\t| The *format* of the following bit of text. Options are `[html]`, `[moodle]`, `[plain]` and `[markdown]`. The default is `[moodle]` for the question text, other parts of the question default to the format used for the question text. | \n| `{`\t| Start answer(s) -- without any answers, text is a description of following questions | \n| `{T}` or `{F}`\t|  True or False answer; also `{TRUE}` and `{FALSE}` | \n| `{` ... `=`*right* ... `}`\t| Correct answer for multiple choice, (multiple answer? -- see page comments) or fill-in-the-blank| \n| `{` ... `~`*wrong* ... `}`\t| Incorrect answer for multiple choice or multiple answer| \n| `{` ... `=`*item* `->` *match* ... `}`\t| Answer for matching questions| \n| `#`*feedback text*\t| Answer feedback for preceding multiple, fill-in-the-blank, or numeric answers| \n| `####`*general feedback*\t| General feedback| \n| `{#`\t| Start numeric answer(s)| \n| &nbsp;&nbsp;&nbsp;&nbsp;*answer*`:`*tolerance*\t| Numeric answer accepted within ± tolerance range| \n| &nbsp;&nbsp;&nbsp;&nbsp;*low*`..`*high*\t| Lower and upper range values of accepted numeric answer| \n| &nbsp;&nbsp;&nbsp;&nbsp;`=%`*n*`%`*answer*`:`*tolerance*\t| n percent credit for one of multiple numeric ranges within tolerance from answer| \n| `}`\t| End answer(s)| \n| `\\`*character*\t| Backslash escapes the special meaning of `~`, `=`, `#`, `{`, `}`, and `:`| \n| `\\n`\t| Places a newline in question text -- blank lines delimit questions| \n\n[Source for above table](http://microformats.org/wiki/gift)\n\nParser in PHP: https://github.com/moodle/moodle/blob/master/question/format/gift/format.php\n\n## Background information\n\nSee these discussions in the Moodle forums: \n\n- [Deriving a Formal GIFT Specification](https://moodle.org/mod/forum/discuss.php?d=259533) \n\t- [Creating 100 multichoice questions is quicker using GIFT.](https://moodle.org/mod/forum/discuss.php?d=259533#p1177669) --[Derek Chirnside](https://moodle.org/user/view.php?id=191052&course=5)\n- [Suggesting using PEG.js with the GIFT spec](https://moodle.org/mod/forum/discuss.php?d=346431)\n\nSee this [test file from Moodle's code base](https://git.moodle.org/gw?p=moodle.git;a=blob;f=question/format/gift/examples.txt;h=e65d4f0db6415e2f318f1d024864b33c75f80c69;hb=refs/heads/MOODLE_26_STABLE).\n\n## Class model for Moodle questions (quiz) format\n\nThe following UML class diagram is an interpretation of the XML format for Moodle quiz import/export. Note that the XML format is naive, e.g., the `QUESTION` tag is overloaded using `TYPE=` and as such can't easily be schema-tized. The interpretation below aims to facilitate the understanding of the content and relations. It's a domain model reverse-engineered from a data model.\n\n![UML class diagram (domain model) loosely based on XML structure](https://www.plantuml.com/plantuml/proxy?cache=no&src=https://raw.githubusercontent.com/fuhrmanator/GIFT-grammar-PEG.js/master/MoodleQuestionDomainModel.txt&fmt=svg)\n\n## Railroad diagram of the grammar\n\nCheck out the [railroad diagram](https://dundalek.com/GrammKit/#https://raw.githubusercontent.com/fuhrmanator/GIFT-grammar-PEG.js/master/GIFT.pegjs) for this project's PEG.\n\n## Testing the editor locally\n\n- In a terminal of the cloned repo: `npm run build && node server.js`\n- Point a browser to http://localhost:8181/docs/editor/editor.html\n\n","readmeFilename":"README.md"}