{"id":13398567,"url":"https://github.com/NUKnightLab/TimelineJS","last_synced_at":"2025-03-14T02:31:30.554Z","repository":{"id":2644138,"uuid":"3633690","full_name":"NUKnightLab/TimelineJS","owner":"NUKnightLab","description":"TimelineJS: A Storytelling Timeline built in JavaScript. ","archived":false,"fork":false,"pushed_at":"2022-05-11T20:13:40.000Z","size":18352,"stargazers_count":8858,"open_issues_count":197,"forks_count":1559,"subscribers_count":407,"default_branch":"master","last_synced_at":"2024-04-14T06:18:02.294Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://timeline.knightlab.com","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NUKnightLab.png","metadata":{"files":{"readme":"README.markdown","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-03-06T02:12:20.000Z","updated_at":"2024-04-13T12:10:53.000Z","dependencies_parsed_at":"2022-07-12T14:58:57.111Z","dependency_job_id":null,"html_url":"https://github.com/NUKnightLab/TimelineJS","commit_stats":null,"previous_names":["veriteco/timelinejs"],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NUKnightLab%2FTimelineJS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NUKnightLab%2FTimelineJS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NUKnightLab%2FTimelineJS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NUKnightLab%2FTimelineJS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NUKnightLab","download_url":"https://codeload.github.com/NUKnightLab/TimelineJS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243447514,"owners_count":20292450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:28.636Z","updated_at":"2025-03-14T02:31:26.249Z","avatar_url":"https://github.com/NUKnightLab.png","language":"JavaScript","readme":"# This Version of Timeline is no longer under development\n\nTherefore, GitHub issues and pull requests have been disabled. \n\nKnight Lab has created a new version at https://github.com/NUKnightLab/TimelineJS3 . The new library should work with existing Google Spreadsheets, but not existing TimelineJS JSON files. The new version of TimelineJS requires a new JSON format, and there is no direct conversion tool, although it should not be too complicated to manually or programatically convert an old JSON file.\n\nKnight Lab will continue to serve this version of Timeline from\n\n* https://cdn.knightlab.com/libs/timeline/latest/js/timeline-min.js\n* https://cdn.knightlab.com/libs/timeline/latest/js/timeline.js\n* https://cdn.knightlab.com/libs/timeline/latest/css/timeline.css\n\nHowever, no future development on this line of code is planned.\n\n----\n\n**Table of Contents**\n\n- [TimelineJS](#timelinejs)\n\t- [Document history with TimelineJS](#document-history-with-timelinejs)\n\t- [Add it to your site](#add-it-to-your-site)\n\t\t- [Using Inline (easiest)](#using-inline-easiest)\n\t\t- [Using a method (advanced)](#using-a-method-advanced)\n\t\t- [Loading the files](#loading-the-files)\n\t- [Config Options](#config-options)\n\t\t- [Language](#language)\n\t\t- [Start at End](#start-at-end)\n\t\t- [Start at Slide](#start-at-slide)\n\t\t- [Start Zoom Adjust](#start-zoom-adjust)\n\t\t- [Hash Bookmark](#hash-bookmark)\n\t\t- [Debug](#debug)\n\t\t- [Map Style Types](#map-style-types)\n\t\t- [Font Options](#font-options)\n\t\t\t- [Font Combination Preview:](#font-combination-preview)\n\t- [File Formats](#file-formats)\n\t\t- [JSON:](#json)\n\t\t- [JSONP :](#jsonp-)\n\t\t- [Google Docs:](#google-docs)\n\t\t- [Storify:](#storify)\n\t- [Media](#media)\n\t- [Best practices](#best-practices)\n\t- [License](#license)\n\n# TimelineJS\n## Document history with TimelineJS\n\nThere are lots of timeline tools on the web but they are almost all either\nhard on the eyes or hard to use. Create timelines that are at the same time\nbeautiful and intuitive for users\n\nTimelineJS is great for pulling in media from different sources. Just throw in a\nlink from Twitter, YouTube, Flickr, Vimeo, Google Maps or SoundCloud and\nTimelineJS will format it to fit perfectly. More media types will be supported\nin the future.\n\nCreating one is as easy as filling in a Google spreadsheet or as detailed as\nJSON.\n\n## Add it to your site\n\n### Using Inline (*easiest*)\nPlace the embed code where you want the timeline to show in the `\u003cbody\u003e` of your site. See [Config Options](#config-options) for a full list of what you can set in the config.\n\n```html\n\t\u003cdiv id=\"timeline-embed\"\u003e\u003c/div\u003e\n\t\u003cscript type=\"text/javascript\"\u003e\n\t    var timeline_config = {\n\t\t\twidth:\t\t\t\t'100%',\n\t\t\theight:\t\t\t\t'600',\n\t\t\tsource:\t\t\t\t'path_to_json/or_link_to_googlespreadsheet',\n\t\t\tembed_id:\t\t\t'timeline-embed',\t\t\t\t//OPTIONAL USE A DIFFERENT DIV ID FOR EMBED\n\t\t\tstart_at_end: \t\tfalse,\t\t\t\t\t\t\t//OPTIONAL START AT LATEST DATE\n\t\t\tstart_at_slide:\t\t'4',\t\t\t\t\t\t\t//OPTIONAL START AT SPECIFIC SLIDE\n\t\t\tstart_zoom_adjust:\t'3',\t\t\t\t\t\t\t//OPTIONAL TWEAK THE DEFAULT ZOOM LEVEL\n\t\t\thash_bookmark:\t\ttrue,\t\t\t\t\t\t\t//OPTIONAL LOCATION BAR HASHES\n\t\t\tfont:\t\t\t\t'Bevan-PotanoSans',\t\t\t\t//OPTIONAL FONT\n\t\t\tdebug:\t\t\t\ttrue,\t\t\t\t\t\t\t//OPTIONAL DEBUG TO CONSOLE\n\t\t\tlang:\t\t\t\t'fr',\t\t\t\t\t\t\t//OPTIONAL LANGUAGE\n\t\t\tmaptype:\t\t\t'watercolor',\t\t\t\t\t//OPTIONAL MAP STYLE\n\t\t\tcss:\t\t\t\t'path_to_css/timeline.css',\t\t//OPTIONAL PATH TO CSS\n\t\t\tjs:\t\t\t\t\t'path_to_js/timeline-min.js'\t//OPTIONAL PATH TO JS\n\t\t}\n\t\u003c/script\u003e\n\t\u003cscript type=\"text/javascript\" src=\"https://cdn.knightlab.com/libs/timeline/latest/js/storyjs-embed.js\"\u003e\u003c/script\u003e\n```\n### Using a method (*advanced*)\nYou could also initialize a new timeline using the `createStoryJS` method after `storyjs-embed.js` has been loaded\n```javascript\n\tcreateStoryJS({\n\t\ttype:\t\t'timeline',\n\t\twidth:\t\t'800',\n\t\theight:\t\t'600',\n\t\tsource:\t\t'path_to_json/or_link_to_googlespreadsheet',\n\t\tembed_id:\t'my-timeline'\t\t\t// ID of the DIV you want to load the timeline into\n\t});\n```\n\nHere's a simple example:\n\n```html\n\t\u003chead\u003e\n\t\t\u003c!-- jQuery --\u003e\n\t\t\u003cscript type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js\"\u003e\u003c/script\u003e\n\t\t\u003c!-- BEGIN TimelineJS --\u003e\n\t\t\u003cscript type=\"text/javascript\" src=\"https://cdn.knightlab.com/libs/timeline/latest/js/storyjs-embed.js\"\u003e\u003c/script\u003e\n\t\t\u003cscript\u003e\n\t\t\t$(document).ready(function() {\n\t\t\t\tcreateStoryJS({\n\t\t\t\t\ttype:\t\t'timeline',\n\t\t\t\t\twidth:\t\t'800',\n\t\t\t\t\theight:\t\t'600',\n\t\t\t\t\tsource:\t\t'path_to_json/or_link_to_googlespreadsheet',\n\t\t\t\t\tembed_id:\t'my-timeline'\n\t\t\t\t});\n\t\t\t});\n\t\t\u003c/script\u003e\n\t\t\u003c!-- END TimelineJS --\u003e\n\t\u003c/head\u003e\n\t\u003cbody\u003e\n\t\t\u003cdiv id=\"my-timeline\"\u003e\u003c/div\u003e\n\t\u003c/body\u003e\n```\n\n### Loading the files\nIf you like, you may load TimelineJS from the KnightLab's CDN. The examples above demonstrate how to do this using `story-embed.js`, which is the simplest way to set up a Timeline of your own.\n\nIf for some reason you need more fine-grained control over your timeline, load the javascript and CSS files separately. We recommend that you load them from our CDN.\n\n```html\n\u003c!-- always load the CSS --\u003e\n\u003clink rel=\"stylesheet\" type=\"text/css\" href=\"https://cdn.knightlab.com/libs/timeline/latest/css/timeline.css\"\u003e\n\u003c!-- and then one of either --\u003e\n\u003cscript type=\"text/javascript\" src=\"https://cdn.knightlab.com/libs/timeline/latest/js/timeline.js\"\u003e\u003c/script\u003e\n\u003c!-- or --\u003e\n\u003cscript type=\"text/javascript\" src=\"https://cdn.knightlab.com/libs/timeline/latest/js/timeline-min.js\"\u003e\u003c/script\u003e\n\u003c!-- but no need for both --\u003e\n```\n\nIf you need to serve copies of the files from your own server, use the entire contents of the [\"/build/\" directory](https://github.com/NUKnightLab/TimelineJS/tree/master/build) of our GitHub repository. If you use a local copy of `story-embed.js` it should automatically load the other Timeline resources from your server.\n\n## Config Options\nHere are some of the options you can set in the config.\n\n### Source\n`source` Should be either the path to the JSON resource to load, or a JavaScript\nobject corresponding to the Timeline model.\n\nHere is an example using a data object:\n\n```javascript\n\n\tvar dataObject = {timeline: {headline: \"Headline\", type: ... }}\n\tcreateStoryJS({\n\t\ttype:\t\t'timeline',\n\t\twidth:\t\t'800',\n\t\theight:\t\t'600',\n\t\tsource:\t\tdataObject,\n\t\tembed_id:\t'my-timeline'\n\t});\n```\n\nIf source is a string, we will try to automatically recognize resources that are\nTwitter searches, Google Spreadsheets or Storify stories. Failing that, we assume\nthe source is either JSON or JSONP. If string matches on `.jsonp`, we will treat it\nas JSONP, otherwise, we will append `?callback=onJSONP_Data`. See more details below.\n\n### Language\n`lang`\nLocalization\n*default is `en` English*\nLanguages available:\n* `af` *Afrikaans*\n* `ar` *Arabic*\n* `hy` *Armenian*\n* `eu` *Basque*\n* `be` *Belarusian*\n* `bg` *Bulgarian*\n* `ca` *Catalan*\n* `zh-cn` *Chinese*\n* `hr` *Croatian / Hrvatski*\n* `cz` *Czech*\n* `da` *Danish*\n* `nl` *Dutch*\n* `en` *English*\n* `en-24hr` *English (24-hour time)*\n* `eo` *Esperanto*\n* `et` *Estonian*\n* `fo` *Faroese*\n* `fa` *Farsi*\n* `fi` *Finnish*\n* `fr` *French*\n* `fy` *Frisian*\n* `gl` *Galician*\n* `ka` *Georgian*\n* `de` *German / Deutsch*\n* `el` *Greek*\n* `he` *Hebrew*\n* `hi` *Hindi*\n* `hu` *Hungarian*\n* `is` *Icelandic*\n* `id` *Indonesian*\n* `ga` *Irish*\n* `it` *Italian*\n* `ja` *Japanese*\n* `ko` *Korean*\n* `lv` *Latvian*\n* `lt` *Lithuanian*\n* `lb` *Luxembourgish*\n* `ms` *Malay*\n* `ne` *Nepali*\n* `no` *Norwegian*\n* `pl` *Polish*\n* `pt` *Portuguese*\n* `pt-br` *Portuguese (Brazilian)*\n* `ro` *Romanian*\n* `rm` *Romansh*\n* `ru` *Russian*\n* `sr-cy` *Serbian - Cyrillic*\n* `sr` *Serbian - Latin*\n* `si` *Sinhalese*\n* `sk` *Slovak*\n* `sl` *Slovenian*\n* `es` *Spanish*\n* `sv` *Swedish*\n* `tl` *Tagalog*\n* `ta` *Tamil*\n* `zh-tw` *Taiwanese*\n* `te` *Telugu*\n* `th` *Thai*\n* `tr` *Turkish*\n* `uk` *Ukrainian*\n\n\n\nHelp us add more. Grab a copy of a language file and replace it with your language [Example language file](https://github.com/NUKnightLab/TimelineJS/blob/master/source/js/Core/Language/locale/en.js) and find your language's [two letter code here](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)\n\n###Start at End\n`start_at_end`\nset to true to start the timeline on the last date.\n*default is false*\n\n###Start at Slide\n`start_at_slide`\nYou can tell TimelineJS to start at a specific slide number\n*default is 0*\n\n###Start Zoom Adjust\n`start_zoom_adjust`\nThis will tweak the default zoom level. Equivalent to pressing the zoom in or zoom out button the specified number of times. Negative numbers zoom out.\n*default is 0*\n\n###Hash Bookmark\n`hash_bookmark`\nset to true to allow bookmarking slides using the hash tag\n*default is false*\n\n###Debug\n`debug`\nWill log events etc to the console.\n*default is false*\n\n\n###Map Style Types\nDue to recent changes to the Google Maps API, you need a [API Key](https://developers.google.com/places/documentation/#Authentication) in order to use custom map types.\n`gmap_key:`\n*required in order to use maptype*\n\n`maptype:`\n* [Stamen Maps ](http://maps.stamen.com)\n\t* `toner`\n\t* `toner-lines`\n\t* `toner-labels`\n\t* `watercolor`\n\t* `sterrain`\n\n* Google Maps\n\t* `ROADMAP`\n\t* `TERRAIN`\n\t* `HYBRID`\n\t* `SATELLITE`\n\n* OpenStreetMap\n\t- `osm`\n\n###Font Options\n`font:`\n* `AbrilFatface-Average` *Abril Fatface \u0026 Average*\n* `Arvo-PTSans` *Arvo \u0026 PT Sans*\n* `Bevan-PotanoSans` *Bevan \u0026 Potano Sans*\n* `BreeSerif-OpenSans` *Bree Serif \u0026 Open Sans*\n* `DroidSerif-DroidSans` *Droid Serif \u0026 Droid Sans*\n* `Georgia-Helvetica` *Georgia \u0026 Helvetica Neue*\n* `Lekton-Molengo` *Lekton \u0026 Molengo*\n* `Merriweather-NewsCycle` *Merriweather \u0026 News Cycle*\n* `NewsCycle-Merriweather` *News Cycle \u0026 Merriweather*\n* `NixieOne-Ledger` *Nixie One \u0026 Ledger*\n* `Pacifico-Arimo` *Pacifico \u0026 Arimo*\n* `PlayfairDisplay-Muli` *Playfair Display \u0026 Muli*\n* `PoiretOne-Molengo` *Poiret One \u0026 Molengo*\n* `PTSerif-PTSans` *PT Serif \u0026 PT Sans*\n* `PT` *PT Sans \u0026 PT Narrow \u0026 PT Serif*\n* `Rancho-Gudea` *Rancho \u0026 Gudea*\n* `SansitaOne-Kameron` *Sansita One \u0026 Kameron*\n* Or make your own\n\n####Font Combination Preview:\n![Font Combination Preview](http://timeline.knightlab.com/static/img/make/font-options.png)\n\n## File Formats\n\n### JSON:\n\nJSON is the native data format for TimelineJS.\n\nRemember, JSON is picky. A misplaced comma or quotation mark can\nprevent the timeline from loading properly.\n\nHere is the full model:\n```javascript\n\n{\n\t\"timeline\":\n\t{\n\t\t\"headline\":\"The Main Timeline Headline Goes here\",\n\t\t\"type\":\"default\",\n\t\t\"text\":\"\u003cp\u003eIntro body text goes here, some HTML is ok\u003c/p\u003e\",\n\t\t\"asset\": {\n\t\t\t\"media\":\"http://yourdomain_or_socialmedialink_goes_here.jpg\",\n\t\t\t\"credit\":\"Credit Name Goes Here\",\n\t\t\t\"caption\":\"Caption text goes here\"\n\t\t},\n\t\t\"date\": [\n\t\t\t{\n\t\t\t\t\"startDate\":\"2011,12,10,07,02,10\",\n\t\t\t\t\"endDate\":\"2011,12,11,08,11\",\n\t\t\t\t\"headline\":\"Headline Goes Here\",\n\t\t\t\t\"text\":\"\u003cp\u003eBody text goes here, some HTML is OK\u003c/p\u003e\",\n\t\t\t\t\"tag\":\"This is Optional\",\n\t\t\t\t\"classname\":\"optionaluniqueclassnamecanbeaddedhere\",\n\t\t\t\t\"asset\": {\n\t\t\t\t\t\"media\":\"http://twitter.com/ArjunaSoriano/status/164181156147900416\",\n\t\t\t\t\t\"thumbnail\":\"optional-32x32px.jpg\",\n\t\t\t\t\t\"credit\":\"Credit Name Goes Here\",\n\t\t\t\t\t\"caption\":\"Caption text goes here\"\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\t\"era\": [\n\t\t\t{\n\t\t\t\t\"startDate\":\"2011,12,10\",\n\t\t\t\t\"endDate\":\"2011,12,11\",\n\t\t\t\t\"headline\":\"Headline Goes Here\",\n\t\t\t\t\"text\":\"\u003cp\u003eBody text goes here, some HTML is OK\u003c/p\u003e\",\n\t\t\t\t\"tag\":\"This is Optional\"\n\t\t\t}\n\n\t\t]\n\t}\n}\n```\n\n### JSONP :\n\nTimeline can use a variation of JSONP to allow you to easily load data across different domains.\n\nTo allow this to happen, the file must end with the extension `.jsonp`\n\nHere is the full model:\n```javascript\nstoryjs_jsonp_data = {\n\t\"timeline\":\n\t{\n\t\t\"headline\":\"The Main Timeline Headline Goes here\",\n\t\t\"type\":\"default\",\n\t\t\"text\":\"\u003cp\u003eIntro body text goes here, some HTML is ok\u003c/p\u003e\",\n\t\t\"asset\": {\n\t\t\t\"media\":\"http://yourdomain_or_socialmedialink_goes_here.jpg\",\n\t\t\t\"credit\":\"Credit Name Goes Here\",\n\t\t\t\"caption\":\"Caption text goes here\"\n\t\t},\n\t\t\"date\": [\n\t\t\t{\n\t\t\t\t\"startDate\":\"2011,12,10\",\n\t\t\t\t\"endDate\":\"2011,12,11\",\n\t\t\t\t\"headline\":\"Headline Goes Here\",\n\t\t\t\t\"text\":\"\u003cp\u003eBody text goes here, some HTML is OK\u003c/p\u003e\",\n\t\t\t\t\"tag\":\"This is Optional\",\n\t\t\t\t\"classname\":\"optionaluniqueclassnamecanbeaddedhere\",\n\t\t\t\t\"asset\": {\n\t\t\t\t\t\"media\":\"http://twitter.com/ArjunaSoriano/status/164181156147900416\",\n\t\t\t\t\t\"thumbnail\":\"optional-32x32px.jpg\",\n\t\t\t\t\t\"credit\":\"Credit Name Goes Here\",\n\t\t\t\t\t\"caption\":\"Caption text goes here\"\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\t\"era\": [\n\t\t\t{\n\t\t\t\t\"startDate\":\"2011,12,10\",\n\t\t\t\t\"endDate\":\"2011,12,11\",\n\t\t\t\t\"headline\":\"Headline Goes Here\",\n\t\t\t\t\"tag\":\"This is Optional\"\n\t\t\t}\n\n\t\t]\n\n\t}\n}\n```\n\n### Google Docs:\n\nIf you don’t want to mess with JSON, fire up Google Docs and build your\ntimeline in a spreadsheet. It’s as simple as dropping a date, text, and links\ninto the appropriate columns in TimelineJS’s template.\n\nYou can find the template here: [TimelineJS Google Spreadsheet Template](https://drive.google.com/previewtemplate?id=0AppSVxABhnltdEhzQjQ4MlpOaldjTmZLclQxQWFTOUE\u0026mode=public\u0026pli=1#)\n\nThere are only a couple things you need to know in order to create a timeline\nusing Google Docs:\n\n  1. Make the spreadsheet public:   \n\tGoogle Docs are automatically set to private but the spreadsheet must be\n\tpublic.\n\n\tClick the blue “Share” button on the top right-hand corner. In the “Share\n\tsettings” window, you’ll see the private setting of the spreadsheet: click\n\t“Change...”. In the Visibility options window, choose “Public on the Web” and\n\tsave.\n\n  2. Publish to the Web  \n\tUnder the File menu, select “Publish to the Web.”\n\n\tIn the next window, check the box next to “Automatically republish when\n\tchanges are made.” Uncheck all other boxes. Click “start publishing.” This\n\twill give you the URL to embed in your HTML file.\n\n  3. Copy/paste the Web URL into your TimelineJS HTML file  \n\tAfter you publish the spreadsheet, Google Docs will generate a link to the\n\tfile. Copy the link for the Web Page option (as opposed to PDF, HTML, XLS,\n\tetc.), then paste it into the timeline’s HTML file (see [Add it to your site](#add-it-to-your-site) )\n\n\n\n### Storify:\n\nSupport for Storify is still in its early stages. It works though. Just paste a link to the storify story as the source.\n\n## Media\n\nIncluded in the zip file is a kitchen sink example. This timeline shows how to\nincorporate the different media types from different services like Twitter,\nYouTube, Flickr, Instagram, TwitPic, Wikipedia, Dailymotion, SoundCloud and Vimeo.\n\nJust copy and paste the address of the media from the browser bar\ninto the media parameter. TimelineJS will auto-magically pull in the media via their api and\nformat it.\n\n## Best practices\n\nTips and tricks to best utilize TimelineJS\n\n  1. Keep it light - don’t get bogged down by text or other elements\n  2. Pick stories that have a strong chronological narrative. It does not work well for stories that need to jump around in the timeline.\n  3. Include events that build up to major occurrences, not just the major events.\n  4. Don't overwhelm the user. A timeline with hundreds of events is probably not the best use of the format.\n\n## License\nThis Source Code Form is subject to the terms of the Mozilla Public\nLicense, v. 2.0. If a copy of the MPL was not distributed with this\nfile, You can obtain one at http://mozilla.org/MPL/2.0/.\n","funding_links":[],"categories":["JavaScript","Timeline","目录","Framework or Library","others","UI Components","时间轴"],"sub_categories":["Runner","框架、库和组件","Just Awesome","Timeline","运行器","运行器e2e测试"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNUKnightLab%2FTimelineJS","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNUKnightLab%2FTimelineJS","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNUKnightLab%2FTimelineJS/lists"}