made it easier to process posts

This commit is contained in:
Orion Reed 2023-08-12 14:32:50 +01:00
parent c6fcdc82ef
commit de461229c4
13 changed files with 265 additions and 58 deletions

View File

@ -2,6 +2,7 @@
"name": "gray-matter", "name": "gray-matter",
"version": "4.0.3", "version": "4.0.3",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)", "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"type":"module",
"license": "MIT", "license": "MIT",
"files": [ "files": [
"gray-matter.d.ts", "gray-matter.d.ts",

18
package-lock.json generated
View File

@ -20,6 +20,7 @@
"@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"@types/node": "^20.4.9", "@types/node": "^20.4.9",
"front-matter": "^4.0.2",
"glob": "^10.3.3", "glob": "^10.3.3",
"markdown-to-jsx": "^7.3.2", "markdown-to-jsx": "^7.3.2",
"typescript": "^5.1.6", "typescript": "^5.1.6",
@ -53,6 +54,15 @@
"node": ">=6.0" "node": ">=6.0"
} }
}, },
"deps/gray-matter/node_modules/front-matter": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/front-matter/-/front-matter-2.3.0.tgz",
"integrity": "sha512-+gOIDsGWHVAiWSDfg3vpiHwkOrwO4XNS3YQH5DMmneLEPWzdCAnbSQCtxReF4yPK1nszLvAmLeR2SprnDQDnyQ==",
"dev": true,
"dependencies": {
"js-yaml": "^3.10.0"
}
},
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
@ -3405,12 +3415,12 @@
} }
}, },
"node_modules/front-matter": { "node_modules/front-matter": {
"version": "2.3.0", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/front-matter/-/front-matter-2.3.0.tgz", "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz",
"integrity": "sha512-+gOIDsGWHVAiWSDfg3vpiHwkOrwO4XNS3YQH5DMmneLEPWzdCAnbSQCtxReF4yPK1nszLvAmLeR2SprnDQDnyQ==", "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"js-yaml": "^3.10.0" "js-yaml": "^3.13.1"
} }
}, },
"node_modules/fs-exists-sync": { "node_modules/fs-exists-sync": {

View File

@ -22,6 +22,7 @@
"@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"@types/node": "^20.4.9", "@types/node": "^20.4.9",
"front-matter": "^4.0.2",
"glob": "^10.3.3", "glob": "^10.3.3",
"markdown-to-jsx": "^7.3.2", "markdown-to-jsx": "^7.3.2",
"typescript": "^5.1.6", "typescript": "^5.1.6",

View File

@ -1,2 +1,3 @@
{"title":"Objects as Reference","date":"2023-01-11T00:00:00.000Z","location":"London, UK","slug":"test"} {"date":"2023-01-11T00:00:00.000Z","slug":"test","title":"Objects as Reference","location":"Devon, UK"}
{"title":"Foobar","date":"2023-10-30T00:00:00.000Z","location":"Somewhere in England","slug":"foobar"} {"date":"2023-02-17T00:00:00.000Z","slug":"wobblywoo","title":"Some temporary title","location":"Mars"}
{"date":"2023-10-30T00:00:00.000Z","slug":"foobar","title":"Foobar","location":"Somewhere in England"}

39
public/posts/wobblywoo.md Normal file
View File

@ -0,0 +1,39 @@
---
title: "Some temporary title"
date: 2023-02-17
location: Mars
---
# Discussion
I'm going to switch modes for this last section. I've run out of steam for this draft, so let me just touch on some things I might like to discuss in colloquial language.
Identifying three key responsibilities or roles of "object systems", and arguing that the tight coupling of these responsibilities is detrimental to our information infrastructure. Decoupling these is key to enabling "better" objects:
1. *Reference*, which conditions the ways objects come to exist and several of their key properties.
2. *Structure*, which conditions how objects are or can be interrelated and the forms they must take. E.g. filesystems impose metadata on their objects, task manager apps impose ways that tasks can be organised, etc.
3. *Identity*, which conditions the ways objects can be considered the same. This is the least-explored part of the paper so far but is super important, I think there's a lot of under-explored ways we can manage identity, but currently this is left to the mutability rules of a system (e.g. file modification) or is implicit in the structure and use of objects (e.g. we consider an image in two formats to be the same). This topic is so big and interesting it may merit its own paper, and I do have one idea for a generalisable approach, which is to view identity as a kind of *governance.* That is to say, that identity comes first from the ways that *people* agree that something is the same. We could imagine identity systems that are highly pluralistic with many overlapping identities. This governance position is currently dominated by system designers such as those designing filesystems, but I think we could articulate a much more decentralised and participatory approach to identity.
Looking at the "wants from objects", what do different discourses want from the objects of concern in their discourse? Malleable software wants interface objects that can are independent of apps; Itemised systems want user-facing data objects to be independent of application boundaries and freely structurable (calendar events, notes, tasks, contacts, etc); post-document systems want the objects currently hidden inside documents to be decoupled from the documents; and so on... One running theme through a lot of these wants is that objects should be robustly referenceable and independent, and that we need to *disaggregate* key objects into smaller referenceable parts. I'd like to expand and articulate these wants through the dimensions laid out earlier in the paper. And I'd like to argue that these discourses should be articulating demands of information *infrastructure* to enable success with these efforts, and recognise the limits of building isolated systems or new platforms — though this can be an effective way of exploring their goals.
I'd like to explore the predictive and explanatory power of this work. If it is a truly *robust* theory, which I think it could become, this needs to be proved out more empirically. Part of this would involve expanding approaches to analysis, while the dimensions are a nice start I would like to do a more systemic analysis of objects "in the wild" and explore the possibilities of formalising some of this work.
While individual systems have been explored, in practice these systems overlap and interconnect in many ways. Characterising interrelationships among multiple systems is a key point to expand on. E.g. the relation between an interface element and the "code" objects that underly it. There's lots of work that cares about these relationships and tries to do things with them, such as bidirectional lenses, linking languages, or linked data protocols. An empirical analysis would need to consider the many systems in seemingly "singular" objects: a JSON file, for example, involves file objects, unicode objects, named ontology elements, and these all interact nontrivially, such as the way that hierarchical structure is encoded in a linear structure of unicode objects.
There's a lot that could be said about expressibility, user agency, and the role of objects in "digital language" — as through reference we create new “words" to speak *with* and new objects to speak *about.*
I'd like to explore implications for infrastructure design, and this is probably a theme that needs to run through the rest of the paper...
There's a political-economic dimension, mentioned in the "public-private" dimension, that's worth expanding on. Referenceability is one way that companies can obstruct more open, decentralised, and I think generally "better" systems from emerging. One could argue that some companies benefit from a "monopoly on referenceability" and that this is something we should try and escape, a fun idea here is to borrow the notion of "adversarial interoperability" and advocate for a kind of "adversarial referenceability" as a political/economic demand [@Doctorow_2019a].
Through this work it became clear that certain roles of objects are poorly supported:
1. *semantic objects* — which gain usefulness through being stable tokens around which semantic structure can emerge — are poorly supported in our systems. Unicode words or phrases are nice tokens, but are highly dependent on files and are not independent in the way we'd like. Files (especially content-addressed ones) are stable and independent but are primarily *pointers* and have too much imposed structure to be good semantic objects. Imagining the best of both worlds is interesting to me: objects that are robust, atemporal, independent, tokens. Imagine if a phrase like "graph databases" could be its own object with a robust reference like a hash, which could be freely linked to, put into relation with other objects and be used in many contexts and places and not tied to a specific system (as files tend to be, but words do not)...
2. *relational objects* — which gain usefulness through expressing relations *between* objects — are also poorly served, as most relations are implicitly embedded in systems and have no independent representation. Research to address this often imposes *a ton* of assumptions and conditions, such as RDF or other semantic web efforts. I'm interested to explore what can be done here and am working on one approach for content-addressed systems with *content-addressed relations*, these do not impose (but can support the representation of) structure — no ordering of relata, no types/labels, no set arity, etc. These relational objects are compelling to me because they can be stable, independent, atemporal, and granular. One could imagine an ambient graph-like network emerging not through some decentralised database or protocol, but as a side effect of creating these kinds of relational objects in many different contexts.
I've focused on limited kinds of objects, things like files, words, PDFs, reminders, etc. Objects that are mostly referenced through *addressing systems.* The choice of examples in this paper need to be interrogated a lot more and there are other kinds of objects which I barely addressed at all, like the artefacts of HCI research: buttons, widgets, etc. Grappling with the wider existence of objects feels out of scope but is pretty important if this theory is to stand up to scrutiny.
Lastly, an obvious omission to this paper and discussion is a deeper exploration of the *usefulness* of this work to *specific* research efforts, this needs to change but I am still figuring out which discourses and specific research work I want to give the most attention in this paper. Feedback on this is *incredibly welcome*!
There's much more to do! And much to do that I *do not know about yet*! If you can help me figure out *any* of this I will be eternally grateful!
# References {.unnumbered}

2
public/stream.jsonl Normal file
View File

@ -0,0 +1,2 @@
{"date":"2023-01-11","markdown":">When asked, “How could you possibly have done the first interactive graphics program, the first non-procedural programming language, the first object oriented software system, all in one year?” Ivan replied: “Well, I didnt know it was hard.”\n\n— via Alan Kay, Doing with Images Makes Symbols, 1987"}
{"date":"2023-05-21","markdown":"**Little excerpt**\n\nAn approach to interfaces in which a network of transformations, constraints, preferences, and other relations connect object(s) of interest to an interface surrogate. The system as a whole is responsible for resolving the arbitrary and complex relationship between an object and surrogate and bridging that surrogate representation to a representation which is observable to users."}

View File

@ -1,18 +1,20 @@
import {glob} from 'glob'; import {glob} from 'glob';
import fs from 'fs'; import fs from 'fs';
import matter from 'gray-matter'; import fm from 'front-matter';
function loadStrings() { function loadStrings() {
const posts = glob.sync('public/posts/*.md').map((file) => { const posts = glob.sync('public/posts/*.md').map((file) => {
const content = fs.readFileSync(file, 'utf8'); const content = fs.readFileSync(file, 'utf8');
const { title, date, location } = matter(content).data; const { title, date, location } = fm(content).attributes;
const slug = file.replace('public/posts/', '').replace('.md', ''); const slug = file.replace('public/posts/', '').replace('.md', '');
return { title, date, location, slug }; return { date, slug, title, location };
}); });
posts.sort((a, b) => new Date(a.date) - new Date(b.date))
return posts; return posts;
} }
function saveStrings(posts) { function saveStrings(posts) {
console.log(posts);
const jsonl = posts.map((post) => JSON.stringify(post)).join('\n'); const jsonl = posts.map((post) => JSON.stringify(post)).join('\n');
fs.writeFileSync('public/posts.jsonl', jsonl); fs.writeFileSync('public/posts.jsonl', jsonl);
} }

View File

@ -5,12 +5,18 @@ const useStyles = createStyles((theme) => ({
fontFamily: theme.headings.fontFamily, fontFamily: theme.headings.fontFamily,
fontSize: '1.2em', fontSize: '1.2em',
fontWeight: 800, fontWeight: 800,
'&:not(:hover)': {
textDecoration: 'none',
},
}, },
link: { link: {
color: theme.black, color: theme.black,
fontFamily: theme.headings.fontFamily, fontFamily: theme.headings.fontFamily,
fontSize: '1.2em', fontSize: '1.2em',
fontWeight: 400, fontWeight: 400,
'&:not(:hover)': {
textDecoration: 'none',
},
}, },
})) }))
export function Header({ dark }: { dark?: boolean }) { export function Header({ dark }: { dark?: boolean }) {

View File

@ -6,20 +6,24 @@ import Post from '@/pages/Post'
import Stream from '@/pages/Stream' import Stream from '@/pages/Stream'
import { NotFound } from '@/pages/404' import { NotFound } from '@/pages/404'
import { MantineProvider } from '@mantine/styles' import { MantineProvider } from '@mantine/styles'
import { Box } from '@mantine/core'
import { Header } from '@/components/Header' import { Header } from '@/components/Header'
import { style } from '@/style' import { style } from '@/style'
export function App() { export function App() {
return ( return (
<MantineProvider withGlobalStyles withNormalizeCSS theme={style}> <MantineProvider withGlobalStyles withNormalizeCSS theme={style}>
<LocationProvider> <Box mb="xl">
<Router> <LocationProvider>
<Route path="/" component={Home} /> <Router>
<Route path="/posts" component={Posts} /> <Route path="/" component={Home} />
<Route path="/posts/:title" component={Post} /> <Route path="/posts" component={Posts} />
<Route path="/stream" component={Stream} /> <Route path="/posts/:title" component={Post} />
<Route default component={NotFound} /> <Route path="/stream" component={Stream} />
</Router> <Route default component={NotFound} />
</LocationProvider> </Router>
</LocationProvider>
</Box>
</MantineProvider> </MantineProvider>
) )
} }

View File

@ -1,39 +1,41 @@
import { Header } from '@/components/Header' import { Header } from '@/components/Header'
import { Container, Text } from '@mantine/core' import { Container, Text, Title, Anchor, Space } from '@mantine/core'
export function Home() { export function Home() {
return ( return (
<> <>
<Header /> <Header />
<Container size="40em"> <Container size="40em">
<Text weight={400}> <Title order={3}>Hello! 👋</Title>
At vero eos et accusamus et iusto odio dignissimos ducimus qui <Text>
blanditiis praesentium voluptatum deleniti atque corrupti quos dolores My research investigates the intersection of computing, human-system
et quas molestias excepturi sint occaecati cupiditate non provident, interfaces, and emancipatory politics. I am interested in the
similique sunt in culpa qui officia deserunt mollitia animi, id est potential of computing as a medium for thought, as a tool for
laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita collective action, and as a means of emancipation.
distinctio. Nam libero tempore, cum soluta nobis est eligendi optio </Text>
cumque nihil impedit quo minus id quod maxime placeat facere possimus, <Text>
omnis voluptas assumenda est, omnis dolor repellendus. Temporibus My current focus is basic research into the nature of digital
autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe organisation, developing theoretical toolkits to improve shared
eveniet ut et voluptates repudiandae sint et molestiae non recusandae. infrastructure, and applying this research to the design of new
Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis systems and protocols which support the self-organisation of knowledge
voluptatibus maiores alias consequatur aut perferendis doloribus and computational artifacts.
asperiores repellat. </Text>
<br /> <Title order={3}>My work</Title>
At vero eos et accusamus et iusto odio dignissimos ducimus qui <Text>
blanditiis praesentium voluptatum deleniti atque corrupti quos dolores Alongside my independent work I am a researcher at{' '}
et quas molestias excepturi sint occaecati cupiditate non provident, <Anchor href="https://block.science/">Block Science</Anchor> building{' '}
similique sunt in culpa qui officia deserunt mollitia animi, id est <i>knowledge organisation infrastructure</i> and at{' '}
laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita <Anchor href="https://economicspace.agency/">ECSA</Anchor> working on{' '}
distinctio. Nam libero tempore, cum soluta nobis est eligendi optio <i>computational media</i>. Previous work includes software and video
cumque nihil impedit quo minus id quod maxime placeat facere possimus, game development, programming tools, and film production. I have
omnis voluptas assumenda est, omnis dolor repellendus. Temporibus expertise in knowledge representation, programming systems design, and
autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe human-computer interaction.
eveniet ut et voluptates repudiandae sint et molestiae non recusandae. </Text>
Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis <Title order={3}>Get in touch</Title>
voluptatibus maiores alias consequatur aut perferendis doloribus <Text>
asperiores repellat. I am occasionally active on Twitter as <i>@OrionReedOne</i> and on
Mastadon as <i>@orion@hci.social</i>. The best way to reach me is
through Twitter or my email, <i>me@orionreed.com</i>
</Text> </Text>
</Container> </Container>
</> </>

View File

@ -6,6 +6,7 @@ import {
Text, Text,
Anchor, Anchor,
useMantineTheme, useMantineTheme,
createStyles,
} from '@mantine/core' } from '@mantine/core'
import { format } from 'date-fns' import { format } from 'date-fns'
import { useEffect, useState } from 'preact/hooks' import { useEffect, useState } from 'preact/hooks'
@ -22,10 +23,20 @@ async function getPosts() {
}) })
} }
function PostListItem({ slug, title, date }) { const useStyles = createStyles((theme) => ({
index: {
fontFamily: 'monospace',
},
}))
function PostListItem({ slug, title, date, index }) {
const { classes } = useStyles()
const black = useMantineTheme().black const black = useMantineTheme().black
return ( return (
<Group> <Group>
<Text color="dimmed" className={classes.index}>
{`${index}`.padStart(3, '0')}
</Text>
<Anchor href={`posts/${slug}`} color={black}> <Anchor href={`posts/${slug}`} color={black}>
{title} {title}
</Anchor> </Anchor>
@ -41,7 +52,7 @@ function Frame({ children }) {
<> <>
<Header /> <Header />
<Container size="40em"> <Container size="40em">
<Title>Posts</Title> <Title>2023</Title>
{children} {children}
</Container> </Container>
</> </>
@ -69,12 +80,13 @@ export function Posts() {
} else { } else {
return ( return (
<Frame> <Frame>
{posts.map((post) => { {posts.map((post, index, array) => {
return ( return (
<PostListItem <PostListItem
slug={post.slug} slug={post.slug}
title={post.title} title={post.title}
date={post.date} date={post.date}
index={array.length - 1 - index}
/> />
) )
})} })}

View File

@ -1,13 +1,116 @@
import {
Group,
Text,
useMantineTheme,
Container,
Stack,
Flex,
createStyles,
Divider,
} from '@mantine/core'
import { format } from 'date-fns'
import { useEffect, useState } from 'preact/hooks'
import { Header } from '@/components/Header' import { Header } from '@/components/Header'
import { Container } from '@mantine/core' import Markdown from 'markdown-to-jsx'
export default function Stream() { const margin = '0.3em'
const useStyles = createStyles((theme) => ({
group: {
color: theme.black,
lineHeight: '1.4em',
fontFamily: theme.headings.fontFamily,
},
item: {
flexWrap: 'nowrap',
'& :first-child': {
marginTop: 0,
},
'& p': {
marginTop: margin,
marginBottom: margin,
},
'& pre': {
marginTop: margin,
marginBottom: margin,
},
'& ul': {
marginTop: margin,
marginBottom: margin,
paddingLeft: '1.4em',
},
'& blockquote': {
marginTop: '0.8em',
marginBottom: '0.8em',
marginLeft: 0,
paddingLeft: '1em',
borderLeft: `0.25em solid ${theme.colors.gray[3]}`,
},
},
date: {
fontFamily: theme.headings.fontFamily,
marginRight: '0.2em',
whiteSpace: 'nowrap',
},
}))
function friendlyDate(dateString: string): string {
const inputDate = new Date(dateString)
return format(inputDate, 'do MMM yyyy')
}
async function getStream() {
const response = await fetch('stream.jsonl')
return await (await response.text()).split('\n').map((post) => {
return JSON.parse(post)
})
}
function StreamItem({ date, markdown }) {
const { classes } = useStyles()
const black = useMantineTheme().black
return ( return (
<> <Group className={classes.item} align="start">
<Header /> <Text color="dimmed" className={classes.date}>
<Container size="40em"> {friendlyDate(date)}
Stream is work-in-progress... Check back sometime. </Text>
</Container> <Flex>
</> <Markdown>{markdown}</Markdown>
</Flex>
</Group>
) )
} }
export default function Stream() {
const { classes } = useStyles()
const [stream, setPost] = useState<Array<object>>(null)
useEffect(() => {
getStream().then(setPost)
}, [])
if (!stream) {
return <Text>Loading stream...</Text>
} else {
return (
<>
<Header />
<Container size="40em" className={classes.group}>
<Text>
This <b>stream</b> is a place for me to think out loud and to share
as I learn. It's not a place for well-formed ideas or for things I'm
sure about. It's a place to explore, to be wrong, and to trust the
reader (and myself) that this is okay.
</Text>
<Divider my="lg" />
<Stack>
{stream.map((s) => {
return <StreamItem markdown={s.markdown} date={s.date} />
})}
</Stack>
</Container>
</>
)
}
}

View File

@ -14,4 +14,28 @@ export const style = {
}, },
black: '#24292e', black: '#24292e',
primaryColor: 'red', primaryColor: 'red',
components: {
Anchor: {
styles: (theme, { variant }) => ({
root: {
color: theme.black,
textDecoration: 'underline',
textUnderlineOffset: '0.15rem',
textDecorationThickness: '0.15rem',
textDecorationColor: theme.colors.dark[1],
'&:hover': {
textDecorationThickness: '0.15rem',
textDecorationColor: theme.black,
},
},
}),
},
Text: {
styles: (theme, { variant }) => ({
root: {
marginBottom: '0.6rem',
},
}),
},
},
} }