Skip to content

Instantly share code, notes, and snippets.

View tmcw's full-sized avatar
💭
merging your prs

Tom MacWright tmcw

💭
merging your prs
View GitHub Profile
@tmcw
tmcw / json.md
Created August 15, 2013 20:27
Why JSONP is a terrible idea and I will never use it again

Moral Concerns

JSONP is not actually JSON with padding, it's Javascript code that's executed. JSON is not a real subset of Javascript and the way it is not is important to us: via UTFGrid, we are all UTF-8 masters.

JSONP is not safe: it's Javascript that's executed. It's trivial to XSS with JSONP, because JSONP is XSS. Just have a call like mapbox.load('foo.tilejson', …) and if foo.tilejson gets replaced with destroyYoursite(), it gets run. Compare to JSON.parse, which is, on purpose, not eval.

Practical Concerns

JSONP is questionable in terms of performance. To be fast, you want to have the same callback all the time so that you can cache the response. But this leads to a page like

export function useMapKeybindings() {
const rep = usePersistence();
const historyControl = rep.useHistoryControl();
const transact = rep.useTransact();
useHotkeys(
"Command+z, Ctrl+z",
(e) => {
e.preventDefault();
historyControl("undo");
import { createContext, useContext } from "react";
import type { IPersistence } from "app/lib/persistence/ipersistence";
const notInContext = {} as IPersistence;
export const PersistenceContext = createContext<IPersistence>(notInContext);
export function usePersistence() {
return useContext(PersistenceContext);
}
export interface MomentInput {
note?: string;
putFeatures: IWrappedFeatureInput[];
deleteFeatures: IWrappedFeature["id"][];
putFolders: IFolderInput[];
deleteFolders: IFolder["id"][];
}
export interface IPersistence {
useHistoryControl(): (direction: "undo" | "redo") => Promise<void>;
{
// User ID
"id": 1,
"type": "Feature",
"properties": {
// System ID
"@id": "d13b47c0-23fb-11ed-a50b-8b6722c6e6fe"
},
"geometry": {
"type": "Point",
import { wktToGeoJSON, geoJSONToWkt } from "betterknown";
import proj4 from "proj4";
// Converting & reprojecting an EWKT string
wktToGeoJSON(`SRID=3857;POINT(-400004.3 60000.1)`, {
proj: proj4,
});
// Converting GeoJSON to WKT
geoJSONToWkt({

Hi Tom!

Here's what the Markdown for a book looks like on macwright.org:

---
categories:
  - book
layout: book
title: 'My Year of Rest and Relaxation'

A faster format in Placemark

Placemark uses GeoJSON, and JSON, everywhere. In the database, features are GeoJSON. When we're sending features into Mapbox GL, it's GeoJSON getting sent with postMessage.

GeoJSON, of course, has its issues:

  • Sending GeoJSON features across to the WebWorker that cuts tiles for Mapbox GL JS is a major bottleneck for the core editing experience.
  • GeoJSON in resident memory is bigger than it needs to be. GeoJSON's coordinate arrays, especially, are an issue - flat arrays would be much more compact.
  • Mapbox GL JS itself has to cut GeoJSON into tiles, which requires some transformation - it creates another flat representation of geometry coordinates.
@tmcw
tmcw / states-income-data.csv
Created July 29, 2022 19:18
Example files to join
State HouseholdIncome
Maryland 84805
New Jersey 82545
Hawaii 81275
Massachusetts 81215
Connecticut 78444
Alaska 77640
New Hampshire 76768
California 75235
Virginia 74222
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel='stylesheet' type='text/css' href='' />
<meta http-equiv='content-type' content='text/html; charset=utf-8' />
</head>
<body>
<button id='foo'>foo!</button>
<script>