-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathhugo-server.R
183 lines (162 loc) · 4.93 KB
/
hugo-server.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#' Manage the hugo server
#'
#' @section Hugo version:
#' hugodown will attempt to automatically use the correct version of hugo for
#' your site (prompting you to call [hugo_install()] if needed). It looks in
#' two places:
#'
#' * If `_hugodown.yaml` is present, it looks for the `hugo_version` key.
#' * If `netlify.toml` is present, it looks in
#' `context$production$environment$HUGO_VERSION`
#'
#' This means if you already use netlify, hugodown will automatically match
#' the version of hugo that you're using for deployment.
#'
#' @description
#' `hugo_start()` starts a hugo server that will automatically re-generate
#' the site whenever the input changes. You only need to execute this once
#' per session; it continues to run in the background as you work on the site.
#' For large sites the hugo server can be slow to start; if it takes longer
#' than 30 seconds `hugo_start()` throws an error.
#'
#' `hugo_stop()` kills the server. This happens automatically when you exit
#' R so you shouldn't normally need to run this.
#'
#' `hugo_browse()` opens the site in the RStudio viewer or your web browser.
#' @export
#' @param site Path to hugo site.
#' @param auto_navigate Automatically navigate to the most recently changed
#' page?
#' @param browse Automatically preview the site after the server starts?
#' @param render_to_disk Render site to disk? The default is to serve the
#' site from memory, but rendering to disk can be helpful for debugging.
#' @param port Port to run server on. For advanced use only.
hugo_start <- function(site = ".",
auto_navigate = TRUE,
browse = TRUE,
render_to_disk = FALSE,
port = 1313) {
path <- site_root(site)
hugo_stop()
if (port_active(port)) {
abort("`hugo` already launched elsewhere.")
}
message("Starting server on port ", port)
args <- c(
"server",
"--port", port,
"--buildDrafts",
"--buildFuture",
if (auto_navigate) "--navigateToChanged",
if (render_to_disk) "--renderToDisk"
)
ps <- hugo_run_bg(path, args, stdout = "|", stderr = "2>&1")
if (!ps$is_alive()) {
abort(ps$read_error())
}
# Swallow initial text
init <- ""
now <- proc.time()[[3]]
ok <- FALSE
while (proc.time()[[3]] - now < 30) {
ps$poll_io(250)
init <- paste0(init, ps$read_output())
if (grepl("Ctrl+C", init, fixed = TRUE)) {
ok <- TRUE
break
}
}
if (!ok) {
ps$kill()
cat(init)
abort("Failed to start Hugo")
}
# Ensure output pipe doesn't get swamped
poll_process <- function() {
if (!ps$is_alive()) {
return()
}
out <- ps$read_output()
if (!identical(out, "")) {
cat(out)
}
later::later(delay = 1, poll_process)
}
poll_process()
hugodown$server <- ps
if (browse) {
hugo_browse()
}
invisible(ps)
}
#' @rdname hugo_start
#' @export
hugo_stop <- function() {
if (!hugo_running()) {
return(invisible())
}
hugodown$server$interrupt()
hugodown$server$poll_io(500)
hugodown$server$kill()
env_unbind(hugodown, "server")
invisible()
}
#' @rdname hugo_start
#' @export
hugo_browse <- function() {
if (is_installed("rstudioapi") && rstudioapi::hasFun("viewer")) {
rstudioapi::viewer("http://localhost:1313")
} else {
utils::browseURL("http://localhost:1313")
}
}
hugo_running <- function() {
env_has(hugodown, "server") && hugodown$server$is_alive()
}
port_active <- function(port) {
tryCatch({
suppressWarnings(con <- socketConnection("127.0.0.1", port, timeout = 1))
close(con)
TRUE
}, error = function(e) FALSE)
}
#' Build site
#'
#' Build static html into specified directory. Useful for debugging and some
#' deployment scenarios
#'
#' @inheritParams hugo_start
#' @param dest Destination directory. If `NULL`, the default, will build
#' in `{site}/public`
#' @param build_drafts,build_future Should drafts and future posts be included
#' in the built site?
#' @param clean Remove files in `public/` that don't exist in the source.
#' @param base_url `<string>` Optionally override the `baseURL` setting from
#' hugo config.
#' @param relative_urls `<bool>` Optionally the override the `relativeURL`
#' setting from hugo config.
#' @export
hugo_build <- function(site = ".",
dest = NULL,
build_drafts = FALSE,
build_future = FALSE,
clean = FALSE,
base_url = NULL,
relative_urls = NULL
) {
path <- site_root(site)
dest <- dest %||% path(path, "public")
args <- c(
"--destination", dest,
if (build_drafts) "--buildDrafts",
if (build_future) "--buildFuture",
if (clean) "--cleanDestinationDir"
)
config <- c(
character(),
baseUrl = if (!is.null(base_url)) base_url,
relativeURLs = if (!is.null(relative_urls)) tolower(relative_urls)
)
hugo_run(path, args, config)
invisible()
}