Internal Interface
Documentation for LiveServer.jl
's internal interface
File watching
There are two key types related to file watching:
- one to wrap a file being watched (
LiveServer.WatchedFile
), - one for the file watcher itself wrapping the list of watched files and what to do upon file changes ("callback" function)
Any file watcher will be a subtype of the abstract type LiveServer.FileWatcher
with, for instance, the default watcher being LiveServer.SimpleWatcher
.
WatchedFile
LiveServer.WatchedFile
— TypeWatchedFile
Struct for a file being watched containing the path to the file as well as the time of last modification.
LiveServer.has_changed
— Functionhas_changed(wf::WatchedFile)
Check if a WatchedFile
has changed. Returns -1 if the file does not exist, 0 if it does exist but has not changed, and 1 if it has changed.
LiveServer.set_unchanged!
— Functionset_unchanged!(wf::WatchedFile)
Set the current state of a WatchedFile
as unchanged
FileWatcher
Key types
LiveServer.FileWatcher
— TypeFileWatcher
Abstract Type for file watching objects such as SimpleWatcher
.
LiveServer.SimpleWatcher
— TypeSimpleWatcher([callback]; sleeptime::Float64=0.1) <: FileWatcher
A simple file watcher. You can specify a callback function, receiving the path of each file that has changed as an AbstractString
, at construction or later by the API function set_callback!
. The sleeptime
is the time waited between two runs of the loop looking for changed files, it is constrained to be at least 0.05s.
Functions related to a FileWatcher
LiveServer.start
— Functionstart(fw::FileWatcher)
Start the file watcher and wait to make sure the task has started.
LiveServer.stop
— Functionstop(fw::FileWatcher)
Stop the file watcher. The list of files being watched is preserved and new files can still be added to the file watcher using watch_file!
. It can be restarted with start
. Returns a Bool
indicating whether the watcher was running before stop
was called.
LiveServer.set_callback!
— Functionset_callback!(fw::FileWatcher, callback::Function)
Set or change the callback function being executed upon a file change. Can be "hot-swapped", i.e. while the file watcher is running.
LiveServer.watch_file!
— Functionwatch_file!(fw::FileWatcher, f_path::AbstractString)
Add a file to be watched for changes.
LiveServer.file_watcher_task!
— Functionfile_watcher_task!(w::FileWatcher)
Helper function that's spawned as an asynchronous task and checks for file changes. This task is normally terminated upon an InterruptException
and shows a warning in the presence of any other exception.
Additional helper functions:
LiveServer.is_running
— Functionis_running(fw::FileWatcher)
Checks whether the file watcher is running.
LiveServer.is_watched
— Functionis_watched(fw::FileWatcher, f_path::AbstractString)
Checks whether the file specified by f_path
is being watched.
Live serving
The serve
method instantiates a listener (HTTP.listen
) in an asynchronous task. The callback upon an incoming HTTP stream decides whether it is a standard HTTP request or a request for an upgrade to a websocket connection. The former case is handled by LiveServer.serve_file
, the latter by LiveServer.ws_tracker
. Finally, LiveServer.file_changed_callback
is the function passed to the file watcher to be executed upon file changes.
LiveServer.serve_file
— Functionserve_file(fw, req::HTTP.Request; inject_browser_reload_script = true)
Handler function for serving files. This takes a file watcher, to which files to be watched can be added, and a request (e.g. a path entered in a tab of the browser), and converts it to the appropriate file system path.
The cases are as follows:
- FILE: the path corresponds exactly to a file. If it's a html-like file, LiveServer will try injecting the reloading
<script>
(see fileclient.html
) at the end, just before the</body>
tag. Otherwise we let the browser attempt to show it (e.g. if it's an image). - WEB-DIRECTORY: the path corresponds to a directory in which there is an
index.html
, same action as (1) assuming theindex.html
is implicit. - PLAIN-DIRECTORY: the path corresponds to a directory in which there is not an
index.html
, list the directory contents. - 404: not (1,2,3), a 404 is served.
All files served are added to the file watcher, which is responsible to check whether they're already watched or not. Finally the file is served via a 200 (successful) response. If the file does not exist, a response with status 404 and message is returned.
Missing docstring for LiveServer.ws_upgrade
. Check Documenter's build log for details.
LiveServer.ws_tracker
— Functionws_tracker(ws::HTTP.WebSockets.WebSocket, target::AbstractString)
Adds the websocket connection to the viewers in the global dictionary WS_VIEWERS
to the entry corresponding to the targeted file.
LiveServer.file_changed_callback
— Functionfile_changed_callback(f_path::AbstractString)
Function reacting to the change of the file at f_path
. Is set as callback for the file watcher.
Additional helper functions:
LiveServer.get_fs_path
— Functionget_fs_path(req_path::AbstractString; silent=false)
Return the filesystem path corresponding to a requested path, or an empty String if the file was not found.
Cases:
- an explicit request to an existing
index.html
(e.g.foo/bar/index.html
) is given –> serve the page and change WEB_DIR unless a parent dir should be preferred (e.g. foo/ has an index.html) - an implicit request to an existing
index.html
(e.g.foo/bar/
orfoo/bar
) is given –> same as previous case after appending theindex.html
- a request to a file is given (e.g.
/sample.jpeg
) –> figure out what it is relative to, reconstruct the full system path and serve the file - a request for a dir without index is given (e.g.
foo/bar
) –> serve a dedicated index file listing the content of the directory.
LiveServer.update_and_close_viewers!
— Functionupdate_and_close_viewers!(wss::Vector{HTTP.WebSockets.WebSocket})
Take a list of viewers, i.e. WebSocket connections from a client, send a message with data "update" to each of them (to trigger a page reload), then close the connection. Finally, empty the list since all connections are closing anyway and clients will re-connect from the re-loaded page.
Helper functions associated with servedocs
LiveServer.servedocs_callback!
— Functionservedocs_callback!(args...)
Custom callback used in servedocs
triggered when a file is modified.
If the file is docs/make.jl
, the callback will check whether any new files have subsequently been generated in the docs/src
folder and add them to the watched files, it will also remove any file that may have been deleted or renamed.
If the file is either in docs/src
, a pass of Documenter is triggered to regenerate the documentation, subsequently the LiveServer will render the pages produced in docs/build
.
Arguments
See the docs of the parent function servedocs
.
LiveServer.scan_docs!
— Functionscan_docs!(dw::SimpleWatcher, args...)
Scans the docs/
folder and add all relevant files to the watched files.
Arguments
See the docs of the parent function servedocs
.
Miscellaneous
LiveServer.example
— Functionexample()
Simple function to copy an example website folder to the current working directory that can be watched by the LiveServer to get an idea of how things work.
Example
LiveServer.example()
cd("example")
serve()
Missing docstring for LiveServer.set_verbose
. Check Documenter's build log for details.